变量与参数

Tutorial: C与汇编 Category: C语言 Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
1. 示例 1
  • 源码
int x;

void main()
{
    int y;

    x = 1;
    y = 2;

    return;
}
  • 汇编
00401010   push        ebp                   ; 保存调用者的基指针
00401011   mov         ebp, esp              ; 将当前栈顶esp的值设置成新的基指针ebp
00401013   sub         esp, 0x44             ; 为局部变量在栈上分配0x4468字节)的空间
00401016   push        ebx                   ; 保存寄存器ebx的值
00401017   push        esi                   ; 保存寄存器esi的值
00401018   push        edi                   ; 保存寄存器edi的值
00401019   lea         edi, [ebp - 0x44]     ; 加载局部变量区域的起始地址到edi寄存器
0040101C   mov         ecx, 0x11             ; 将循环计数器ecx设置为0x111700401021   mov         eax, 0xCCCCCCCC       ; 将调试值0xCCCCCCCC加载到eax中
00401026   rep stos    dword ptr [edi]       ; 将eax的值复制到edi指向的内存位置,rep重复17次,填充局部变量空间

7:        x = 1;
00401028   mov         dword ptr [x (00427c64)], 1  ; 将整数1赋给全局变量x // 全局变量地址固定

8:        y = 2;
00401032   mov         dword ptr [ebp - 4], 2       ; 将整数2赋给局部变量y // 局部变量存放在堆栈中,只有在用的时候才会分配内存

00401039   pop         edi                        ; 恢复之前保存的edi寄存器的值
0040103A   pop         esi                        ; 恢复之前保存的esi寄存器的值
0040103B   pop         ebx                        ; 恢复之前保存的ebx寄存器的值
0040103C   mov         esp, ebp                   ; 恢复esp栈指针的值为ebp基指针的值,释放局部变量
0040103E   pop         ebp                        ; 恢复调用者的ebp基指针的值
0040103F   ret                                    ; 返回到调用main函数的下一条指令

固定套路:
    1. push ebp          // 存 ebp
    2. mov ebp, esp      // ebp = esp
    3. sub esp, XXX      // esp 下移,分配小栈
    4. push 相关的寄存器  // sp 还在减
    5. edi 获取到 ebp - XXX, 就是未push之前,sp的值
    6. eax=CCCCCCCC, ecx = XXX / 4 = n 个 dword
    7. 填充小栈
    8. ss:[ebp - 4] 开始存放的局部变量
    9. pop 相关寄存器, sp 回归到小栈栈顶
    10. mov esp,ebp 还原原先的sp
    11. pop ebp 还原 ebp
    12. rep,pop ip
2. 示例 2
  • 源码
int m;

int plus(int x, int y)
{
    int z = x + y;
    return z;
}

void main()
{
    int x, y;
    x = 2;
    y = 3;

    m = plus(x, y);

    return;
}
  • 汇编
1:    int m;
2:
3:    int plus(int x, int y)
4:    {
00401010   push        ebp
00401011   mov         ebp,esp // 新的ebp, 参数源地址在老的[ebp - 4]中,所以这里要用正偏移了
00401013   sub         esp,44h // 新的小栈,plus的小栈
// 堆栈图:
// ...
// - EBP
// -0040D473 call 的返回 +4
// -2                    +8
// -3                    +C
00401016   push        ebx
00401017   push        esi
00401018   push        edi
00401019   lea         edi,[ebp-44h]
0040101C   mov         ecx,11h
00401021   mov         eax,0CCCCCCCCh
00401026   rep stos    dword ptr [edi]
5:        int z = x + y;
00401028   mov         eax,dword ptr [ebp+8]    // 参数,正偏移
0040102B   add         eax,dword ptr [ebp+0Ch]  // 参数,正偏移
0040102E   mov         dword ptr [ebp-4],eax    // 局部变量,负偏移,存放在plus的小栈中
6:        return z;
00401031   mov         eax,dword ptr [ebp-4] // 返回值
7:    }
00401034   pop         edi
00401035   pop         esi
00401036   pop         ebx
00401037   mov         esp,ebp
00401039   pop         ebp
0040103A   ret
8:
9:    void main()
10:   {
0040D440   push        ebp
0040D441   mov         ebp,esp
0040D443   sub         esp,48h
0040D446   push        ebx
0040D447   push        esi
0040D448   push        edi
0040D449   lea         edi,[ebp-48h]
0040D44C   mov         ecx,12h
0040D451   mov         eax,0CCCCCCCCh
0040D456   rep stos    dword ptr [edi]
11:       int x, y;
12:       x = 2;
0040D458   mov         dword ptr [ebp-4],2 // 局部变量 负偏移
13:       y = 3;
0040D45F   mov         dword ptr [ebp-8],3 // 局部变量 负偏移
// 堆栈图:
// -
// -
// - ESP
// - ecx
// - eax
// - edi
// - esi
// - ebx
// - ESP(sub esp,48h)
// -CCCCCCCC
// -CCCCCCCC
// -CCCCCCCC  (中间是main的小栈)
// -CCCCCCCC
// -CCCCCCCC
// -3
// -2
// - EBP
14:
15:       m = plus(x, y);
0040D466   mov         eax,dword ptr [ebp-8] // 局部变量3 负偏移
0040D469   push        eax  // 注意这里,是新的 ebp +C 传参
0040D46A   mov         ecx,dword ptr [ebp-4] // 局部变量2 负偏移
0040D46D   push        ecx // 注意这里,是xinde ebp +8 传参
0040D46E   call        @ILT+5(plus) (0040100a) // 新的ebp + 4, 0040100A   jmp         plus (00401010)
0040D473   add         esp,8 // 堆栈平衡
0040D476   mov         [m (00427c64)],eax // 全局变量,存放在内存中
16:
17:       return;
18:   }
0040D47B   pop         edi
0040D47C   pop         esi
0040D47D   pop         ebx
0040D47E   add         esp,48h
0040D481   cmp         ebp,esp
0040D483   call        __chkesp (0040d400)
0040D488   mov         esp,ebp
0040D48A   pop         ebp
0040D48B   ret
3. 示例 3
  • 源码
int m;

int plus(int x, int y)
{
    int z = x + y;
    return z;
}

int plus1(int x, int y, int z)
{
    int z1 = plus(x, y);
    int z2 = z + z1;
    return z2;
}

void main()
{
    int x = 1;
    int y = 2;
    int z = 3;

    m = plus1(x, y, z);

    return;
}
  • 汇编
1:    int m;
2:
3:    int plus(int x, int y)
4:    {
00401030   push        ebp
00401031   mov         ebp,esp
00401033   sub         esp,44h
00401036   push        ebx
00401037   push        esi
00401038   push        edi
00401039   lea         edi,[ebp-44h]
0040103C   mov         ecx,11h
00401041   mov         eax,0CCCCCCCCh
00401046   rep stos    dword ptr [edi]
5:        int z = x + y;
00401048   mov         eax,dword ptr [ebp+8]
0040104B   add         eax,dword ptr [ebp+0Ch]
0040104E   mov         dword ptr [ebp-4],eax
6:        return z;
00401051   mov         eax,dword ptr [ebp-4]
7:    }
00401054   pop         edi
00401055   pop         esi
00401056   pop         ebx
00401057   mov         esp,ebp
00401059   pop         ebp
0040105A   ret
8:
9:    int plus1(int x, int y, int z)
10:   {
00401070   push        ebp
00401071   mov         ebp,esp
00401073   sub         esp,48h
00401076   push        ebx
00401077   push        esi
00401078   push        edi
00401079   lea         edi,[ebp-48h]
0040107C   mov         ecx,12h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]
11:       int z1 = plus(x, y);
00401088   mov         eax,dword ptr [ebp+0Ch]
0040108B   push        eax // 参数1
0040108C   mov         ecx,dword ptr [ebp+8]
0040108F   push        ecx // 参数2
00401090   call        @ILT+5(plus) (0040100a) // push 00401095
00401095   add         esp,8 // 外平栈 2个参数,8个字节
00401098   mov         dword ptr [ebp-4],eax // 局部变量
12:       int z2 = z + z1;
0040109B   mov         edx,dword ptr [ebp+10h]
0040109E   add         edx,dword ptr [ebp-4]
004010A1   mov         dword ptr [ebp-8],edx
13:       return z2;
004010A4   mov         eax,dword ptr [ebp-8]
14:   }
004010A7   pop         edi
004010A8   pop         esi
004010A9   pop         ebx
004010AA   add         esp,48h
004010AD   cmp         ebp,esp
004010AF   call        __chkesp (00401140)
004010B4   mov         esp,ebp
004010B6   pop         ebp
004010B7   ret
15:
16:   void main()
17:   {
004010D0   push        ebp
004010D1   mov         ebp,esp
004010D3   sub         esp,4Ch
004010D6   push        ebx
004010D7   push        esi
004010D8   push        edi
004010D9   lea         edi,[ebp-4Ch]
004010DC   mov         ecx,13h
004010E1   mov         eax,0CCCCCCCCh
004010E6   rep stos    dword ptr [edi]
18:       int x = 1;
004010E8   mov         dword ptr [ebp-4],1
19:       int y = 2;
004010EF   mov         dword ptr [ebp-8],2
20:       int z = 3;
004010F6   mov         dword ptr [ebp-0Ch],3
21:
22:       m = plus1(x, y, z);
004010FD   mov         eax,dword ptr [ebp-0Ch]
00401100   push        eax // 参数1
00401101   mov         ecx,dword ptr [ebp-8]
00401104   push        ecx // 参数2
00401105   mov         edx,dword ptr [ebp-4]
00401108   push        edx // 参数3
00401109   call        @ILT+0(plus1) (00401005)
0040110E   add         esp,0Ch // 外平栈, 3个参数, 12 字节
00401111   mov         [m (00427c50)],eax // 全局变量
23:
24:       return;
25:   }
00401116   pop         edi
00401117   pop         esi
00401118   pop         ebx
00401119   add         esp,4Ch
0040111C   cmp         ebp,esp
0040111E   call        __chkesp (00401140)
00401123   mov         esp,ebp
00401125   pop         ebp
00401126   ret