第一节 1.1C语言
1、注意参数
和局部变量
在堆栈
中的存储方式
2、参数
在调用函数前
就已经存入堆栈
,从[EBP+8]、[EBP+C]、……开始。
3、局部变量
是在调用函数
后,存入缓冲区里
,从[EBP-4]、[EBP-8]、……开始
4、函数运算得到的结果,通常存在EAX里
。
第一节 1.2逆向汇编
第一节 1.3练习1
练习1:编写一个函数能够对任意2个整数实现加法,并分析函数的反汇编.
int Plus(int x,int y)
#include <iostream>
#include<Windows.h>
//实现加法功能的函数
int plus(int x,int y)
{
return x + y;
}
int main()
{
//调用函数plus();
plus(1,2);
system("pause");
}
第一节 1.4练习2
练习2:编写一个函数,能够对任意3个整数实现加法,并分析函数的反汇编(要求使用上一个函数).
int Plus2(int x,int y,int z)
#include "stdio.h" int plus(int x,int y) { return x+y; } int plus2(int x,int y,int z) { int i = plus(x,y); return plus(i,z); } void main(int argc,char* argv[]) { plus2(1,2,3); }
第一节 1.3练习3
3、编写一个函数,能够实现对任意5个整数实现加法(使用Plus1和Plus2).
并分析一个函数的反汇编代码.
int Plus3(int a,int b,int c,int d,int e)
#include "stdio.h"
int plus(int x,int y)
{
return x+y;
}
int plus2(int x,int y,int z)
{
int i = plus(x,y);
return plus(i,z);
}
int plus3(int a,int b,int c,int d,int e)
{
int i;
int r;
i = plus(a,b);
r = plus2(c,d,e);
return i+r;
}
void main(int argc,char* argv[])
{
plus3(5,6,7,8,9);
}
第二节 2.1裸函数与汇编写法
1、裸函数的写法
2、如何在C语言里写汇编代码
声明一个裸函数后,编译器不会生成任何的代码
#include <iostream>
#include<Windows.h>
//构造裸函数
int __declspec(naked) plus(int x,int y)
{
__asm
{
//提升堆栈
push ebp
mov ebp,esp
sub esp,0x40
//保护现场
push edi
push ebx
push esi
//填充缓冲区
lea edi,dword ptr ss:[ebp-0x40]
mov ecx,0x10
mov eax,0xcccccccc
rep stosd
//加法功能
mov eax,[ebp+0x8]
add eax,[ebp+0xc]
//恢复现场
pop esi
pop ebx
pop edi
//降低堆栈
mov esp,ebp
pop ebp
ret
}
}
int main()
{
plus(1,2);
system("pause");
}
第二节 2.2调用约定
1、参数是如何传入堆栈?
2、如何平衡堆栈的?
————————————————————————-
调用约定 | 参数压栈 | 平衡堆栈 |
---|---|---|
_cdecl (C和C++默认的调用约定) | 从右至左 | 调用者清理 |
_stdcall API使用的调用约定 | 从右至左 | 自身清理 |
_fastcall | ecx/edx传送前两个剩下的从右至左 | 自身清理(只有2个参数,不需要内平栈) |
————————————————————————
_cdecl
cdecl(C declaration,即C声明)是源起C语言的一种调用约定,也是C语言的事实上的标准。
1.函数实参
在线程栈上按照从右至左的顺序依次压栈
2.函数结果保存在寄存器EAX/AX/AL中
3.浮点型结果存放在寄存器ST0中
4.编译后的函数名前缀以一个下划线字符 例:sumExample
编译后:_sumExample
5.调用者负责
从线程栈中弹出实参(即清栈
)
6.8比特或者16比特长的整形实参提升为32比特长
7.受到函数调用影响的寄存器(volatile registers):EAX, ECX, EDX, ST0 - ST7, ES, GS
8.不受函数调用影响的寄存器: EBX, EBP, ESP, EDI, ESI, CS, DS
9.RET指令从函数被调用者返回到调用者(实质上是读取寄存器EBP所指的线程栈之处保存的函数返回地址并加载到IP寄存器)
10.堆栈平衡是由调用函数来执行的(在call [地址]
,之后会有add esp x
,x表示参数的字节数
)
标签:汇编,函数,int,C语言,noopener,plus,rel,堆栈 From: https://www.cnblogs.com/bonelee/p/17278094.html