汇编语言如 nasm
c语言代码
PUBLIC void adder1(int a,int b);
void cstart()
{
adder1(1,4);
}
汇编代码:
global adder1
adder1:
push ebp
mov ebp,esp
mov word [ebp+0x8],1
pop ebp
ret
首先要说明的是汇编要使他们能执行,通过编译之后,还需要用ld(连接器)把目标文件连接成起来,我们并不说如何执行他们,而是看他们相互执行时的堆栈的编号情况。
把调试的代码放上来(汇编的),也就是最终经过编译连接后的。
1 call .+0x0000000b (0x0000141c) ; e80b000000
2 push ebp ; 55
3 mov ebp, esp ; 89e5
4 sub esp, 0x00000008 ; 83ec08
5 mov dword ptr ss:[esp+0x4], 0x00000004 ; c744240404000000
6 mov dword ptr ss:[esp], 0x00000001 ; c7042401000000
7 call .+0x0000000a (0x00001440) ; e80a000000
8 push ebp ; 55
9 mov ebp, esp ; 89e5
10 mov word ptr ss:[ebp+0x8], 0x0001 ; 66c745080100
11 pop ebp ; 5d
12 ret ; c3
13 leave ; c9
14 ret ; c3
这里开始的call是我们之前的“汇编调用c的堆栈的变化”里说的那样从汇编程序调用c语言,还是把那代码一起贴上来:
extern cstart
global _start
_start:
call cstart
**********具体分析*********
开始时call cstart(在汇编代码里) 调用c语言,它会产生这样的代码(如果没参数,应该说有参数也一样)
push ebp
mov ebp,esp
......
pop ebp
ret 可以看我们上一次说的”汇编调用c的堆栈变化分析“
而我们经过编译连接后的代码好像也是这样的,不过毕竟还是有区别
4 sub esp, 0x00000008 ; 83ec08
5 mov dword ptr ss:[esp+0x4], 0x00000004 ; c744240404000000
6 mov dword ptr ss:[esp], 0x00000001 ; c7042401000000
4-6,他正如我们说的那样,在c代码里,调用一个c函数,他会先把参数压栈,这里就是它的实现,先把esp减小,然后在把参数压如进去。
再看8-12 他是不是和我们自己写的代码(汇编)一样呢 没错是那样的
所以,4-12是函数adder1的相应实现,这很好理解。
现在让你比较迷惑的是13了吧 ,你会觉得这里换成pop ebp好像就能说同了吧,leave,他是与enter相应的指令
; enter n: (等价于)
push ebp
mov ebp, esp
sub esp, n
MeaningENTER constructs a stack frame for a high-level language procedure call (http://www.posix.nl/linuxassembl ... a.html#section-A.27)
; leave (等价于)
mov esp, ebp
pop ebp
Meaning:LEAVE destroys a stack frame of the form created by the ENTER instruction(http://www.posix.nl/linuxassembl ... a.html#section-A.94)
看到这里,你一定想多了解一些stack frame了吧,http://blog.chinaunix.net/u/14966/showart_366009.html 给个连接
我想你大概意思应该知道的差不多了吧,在3那里,esp还和ebp等价(值相等),但经过了函数adder1(4-12),因为要开辟一个stack frame,esp已经比ebp小了,具体来说是ebp-esp=8 那么这里的leave,他就是把那个stack frame清除掉,是通过mov esp,ebp 使他们的值再次回到3那里相等处。 相信你应该差不多了解了吧
c 语言调用汇编堆栈的详细分析
最新推荐文章于 2022-04-21 17:13:13 发布