汇编指令与函数调用

核心内容:

一、寄存器ebp、esp、eax、ecx,eip

二、汇编语言命令mov、 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

举例:pop 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; } 结束

本页共116段,3376个字符,5622 Byte(字节)