学习拆卸

4 c assembly gcc disassembly

为了理解下面发生了什么,我正在制作小型C程序,然后将其反转,并尝试理解其objdump输出.

C程序是:

#include <stdio.h>

int function(int a, int b, int c) {
    printf("%d, %d, %d\n", a,b,c);
}

int main() {
    int a;
    int *ptr;

    asm("nop");
    function(1,2,3);
}
Run Code Online (Sandbox Code Playgroud)

函数的objdump输出给出了以下内容.

080483a4 <function>:
 80483a4:   55                      push   ebp
 80483a5:   89 e5                   mov    ebp,esp
 80483a7:   83 ec 08                sub    esp,0x8
 80483aa:   ff 75 10                push   DWORD PTR [ebp+16]
 80483ad:   ff 75 0c                push   DWORD PTR [ebp+12]
 80483b0:   ff 75 08                push   DWORD PTR [ebp+8]
 80483b3:   68 04 85 04 08          push   0x8048504
 80483b8:   e8 fb fe ff ff          call   80482b8 <printf@plt>
 80483bd:   83 c4 10                add    esp,0x10
 80483c0:   c9                      leave  
Run Code Online (Sandbox Code Playgroud)

请注意,在调用printf之前,三个带有偏移量8,16,12的DWORD(它们必须是function相反顺序的参数)被压入堆栈.之后会推送一个十六进制地址,它必须是格式字符串的地址.

My doubt is

  1. 我没有直接将3个DWORDS和格式说明符直接压入堆栈,而是希望看到esp被手动递减,然后将值推入堆栈.怎么能解释这种行为?

Dig*_*oss 5

好吧,有些机器有一个堆栈指针,就像任何其他寄存器一样,所以推送东西的方式是,减少后跟商店.

但是有些机器,比如x86 32/64,有一个执行宏操作的push指令:递减指针进行存储.

宏观操作,顺便说一句,有一个有趣的历史.有时,某些机器上的某些示例比使用简单指令执行基本操作要慢.

我怀疑今天是否经常出现这种情况.现代x86非常精致.CPU会将您的操作码本身分解为微操作,然后将其存储在缓存中.微操作具有特定的流水线和时隙要求,最终结果是x86内部有一个RISC cpu,整个过程非常快,具有良好的架构层代码密度.