1. 例子1

C++代码:

int main()
{
    func1(5);
}

对应的汇编代码为:

 1    PUBLIC    _main
 2    _TEXT    SEGMENT
 3    _main    PROC 
 4            push    ebp
 5            mov        ebp, esp
 6            push    5
 7            call    ?func1@@YAXH@Z
 8            add        esp, 4
 9            xor        eax, eax
10            pop        ebp
11            ret        0
12    _main    ENDP
13    _TEXT    ENDS

解释:
L3-L12是main函数和procedure
L4, 5, 10是函数main的栈框架
ebp: base pointer,用于索引函数的参数和本地变量。先把之前的ebp入栈,再把main的ebp作为新的ebp。调用结束后恢复原函数的ebp。
L6:func1的函数入栈
L7:C++对函数名func1生成的符号,把函数的参数、参数类型都编码进去(因为有重载)
ESP:stack point
L8:退栈操作
L9:函数返回值清零,代表main函数返回0
L11:返回,但不对栈做额外的更改。不是main返回值为0的意思。

2. 例子2

void func1(int n)
{
    int a = n + 1;
    func2(a);
}

对应的汇编代码为:

 1    _a{% math_inline %} = -4
 2    _n{% endmath_inline %} = 8
 3    ?func1@@YAXH@Z PROC
 4        push    ebp
 5        mov        ebs, esp
 6        push    ecx
 7        mov        eax, DWORD PTR _n{% math_inline %}[ebp]
 8        add        eax, 1
 9        mov        DWORD PTR _a{% endmath_inline %}[ebp], eax
10        mov        ecx, DWORD PTR _a$[ebp]
11        push    ecx
12        call    ?func2@@YZXH@Z
13        add        esp, 4
14        mov        esp, ebp
15        pop        ebp
16        ret        0
17    ?func1@@YZXH@Z ENDP

解释:
L4, 5, 14, 15为函数func1的栈框架
L6:腾出变量a在栈上的空间
L7:通过ebp+8得到入参n的值,并把值放入eax
L9:把eax存入ebp-4的位置入
L10-11:把ebp-4位置上的值读到ecx上并入栈,用于func1函数的参数入栈
L13:bar函数的参数退栈

3. 调用过程中的栈变化

栈空间的内容 说明
main函数已经使用的空间
func1的参数5 main L6
“返回到main后的下一句指令”的地址 main L7
寄存器保留的空间 从这里开始是func1的空间,对寄存器的push操作放到这里
a=5 参数的空间,L9
func2的参数5 func1 L11
“返回到func1后的下一句指令”的地址 L12
func2的可用空间

results matching ""

    No results matching ""