汇编指令与函数调用

核心内容:
一、寄存器ebp、esp、eax、ecx,eip
二、汇编语言命令mv、 push、 pop、 add、 sub
三、函数调用

一、寄存器
IA-32下,通用寄存器:ebp、esp、eax、ecx, 专用寄存器eip。
ebp——栈底指针寄存器:指向栈底(存放栈底地址)
esp——栈顶指针寄存器:指向栈顶(存放栈顶地址)
eax——累加器:使用频率最高,用于算术运算、逻辑运算和外设传送信息等
ecx——计数器:作为循环操作等指令中的计数器
eip——指令指针:指向(存放)当前执行指令的地址

二、汇编语言命令
1、mov——传送指令
定义:把一个字节、字或双字的操作数从源位置传送到目的位置,可以实现立即数到通用寄存器或主存的传送,通用寄存器与通用寄存器、主存或段寄存器之间的传送,主存与段寄存器之间的传送。
举例:mv ebp, esp
解释:相当于C语言中赋值语句=,ebp=esp

2、push——进栈指令
定义:进栈指令push先将ESP减小作为当前栈顶,然后可以将立即数、通用寄 存器和段寄存器或存储器操作数传送到当前栈顶。
格式:push src
举例:push ebp
解释:相当于C语言中esp+=4, *esp=ebp
作用:为ebp当前存放的地址,在栈顶开辟空间存入它,用作调用子函数时的现场保护

3、pop——出栈指令
定义:与入栈指令相反,它先将栈顶的数据传送到通用寄存器、存储单元或段寄存器中,然后ESP增加作为当前栈顶。
格式:pop src
举例:push ebp
解释:相当于C语言中 ebp=*esp, esp+=4
作用:调用子函数结束后,恢复主函数的ebp

4、add——加法指令
格式:add dest, src
解释:相当于dest+=src

5、sub——减法指令
格式:sub dest, src
解释:相当于dest-=src

6、call——函数调用指令
格式:call 函数名
作用:(1)将程序当前执行的位置IP压入堆栈中;(2)转移到调用的子程序。

三、函数调用
1、C语言程序:
int sum(int a, int b) {int c=a+b; return c;}
int main() { int x=10; int y=20; int z=add(x,y); return 0; }

2、汇编:
int main()
{

int x=10, y=20;
mov dword ptr [x],0Ah
mov dword ptr [y],14h
int z=fun(x,y);
mov eax,dword ptr [y]
push eax
mov ecx,dword ptr [x]
push ecx
call fun (0A41096h)
add esp,8
mov dword ptr [z],eax
return 0;
xor eax,eax
}
int fun(int a, int b)
{

push ebp
mov ebp,esp
sub esp,0CCh
int c=a+b;
mov eax,dword ptr [a]
add eax,dword ptr [b]
mov dword ptr [c],eax
return c;
mov eax,dword ptr [c]
}
mov esp,ebp
pop ebp
ret

3、图
在这里插入图片描述

4、分析
(1) int main() {
汇编命令比较多,主要是push一些寄存器以及为main函数在内存上开辟空间,开辟空间范围从ebp到esp,其中ebp存储高地址,esp存储底地址。

(2) int x=10, y=20;
mov dword ptr [x],0Ah
mov dword ptr [y],14h
mov指令是传送指令,dword意思是双字即4个字节, ptr意思是是指针,0A是10的十六进制,意思就是在main函数中申请4个字节,存入x=10。y=20同理。

(3) int z=add(x,y); 传参和接收返回值
1)mov eax,dword ptr [y]
2)push eax
3)mov ecx,dword ptr [x]
4) push ecx
5)call fun (0A41096h)
6) add esp,8
7)mov dword ptr [z],eax
1)2)意思是把y的值赋给eax,然后栈顶esp抬高4个字节,最后把eax的值存入此时esp指向的地址,总的来说就是要给b=y=10开辟空间并保存它,不过还需eax的中转;3)4)同理;5)先push eip+1(作用时保护指令的地址,等回到主函数时能继续执行下去),然后再转入子函数fun中;至于6)7)就要等到函数跳转回来再执行了,后面进入子函数中。

(4)int sum(int a, int b) {
push ebp
mov ebp,esp
sub esp,0CCh
这里主要进行栈的开辟:将ebp的值压入栈中(作用是保护主函数栈底的地址);再把esp的值赋给ebp,目的是为fun函数开辟栈底;最后给esp加0CCh ,开辟栈顶,这样就开辟出了函数fun的空间,即从栈底ebp到栈顶esp。

(5)int c=a+b;
mov eax,dword ptr [a]
add eax,dword ptr [b]
mov dword ptr [c],eax
把a的值给eax;然后给eax+=b;最后把eax的值给c。

(6) return c;
mov eax,dword ptr [c]
把c的值给寄存器eax,由eax将返回值带入主函数中。

(7)} 栈帧回退
1)mov esp,ebp
2)pop ebp
3)ret
1)栈顶回退 ;2)栈底回退,与之前的push ebp呼应;3)先是pop eip,让指令回到主函数中(与之前的push eip呼应) 。

(8) int z=add(x,y);
1)add esp,8
2)mov dword ptr [z],eax
1)释放传参时申请的空间;2)用eax把参数传回给z

(9) return 0; } 结束

猜你喜欢

转载自blog.csdn.net/qq_42953408/article/details/87438003