c 语言调用汇编堆栈的详细分析

来源:互联网 发布:mac地址是唯一的吗 编辑:程序博客网 时间:2024/05/07 04:51

汇编语言如 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那里相等处。  相信你应该差不多了解了吧

原创粉丝点击