【问题标题】:Explanation of the disassembly of the simplest program (x86)最简单程序的反汇编说明(x86)
【发布时间】:2010-05-25 00:14:42
【问题描述】:

以下代码

int _main() {return 0;}

使用命令编译:

gcc -s -nostdlib -nostartfiles 01-simple.c -o01-simple.exe

gcc 版本 4.4.1 (TDM-1 mingw32)

OllyDbg 产生了这个输出:

你能解释一下这里发生了什么吗? 到目前为止的分析:

// these two seems to be an idiom:
PUSH EBP        // places EBP on stack
MOV EBP, ESP    // overwrites EBP with ESP

MOV EAX, 0      // EAX = 0

LEAVE          // == mov esp, ebp
               //    pop ebp
               // according to 
               // http://en.wikipedia.org/wiki/X86_instruction_listings

这一切的意义是什么?

【问题讨论】:

标签: c assembly x86 ollydbg


【解决方案1】:

这会创建一个stack frame

PUSH EBP      
MOV EBP, ESP  

在使用的调用约定中,返回值通过EAX 发回(所以0 存在是因为您编写了return 0; - 尝试将其更改为return 1; 并查看它如何影响代码) .

MOV EAX, 0 

这告诉处理器清理堆栈帧(相当于MOV ESP, EBP 后跟POP EBP,这与创建堆栈帧时所做的相反):

LEAVE

【讨论】:

    【解决方案2】:

    指令在运行时加载器进入int _main()函数时建立栈帧,

    推送 EBP MOV EBP,ESP

    堆栈帧已设置并访问参数(如果提供任何参数)将偏移EBP + 参数的大小(WORD、BYTE、LONG 等)。

    通常EAX寄存器是从运行环境返回退出状态给操作系统加载器的正常寄存器,

    移动 EAX, 0 离开

    换句话说,程序已成功退出,向操作系统返回 0。

    在使用返回的情况下,堆栈帧会在运行时执行时恢复,然后再将控制权交还给操作系统。

    POP EBP

    普遍的共识是,如果发生错误,该值将不为零,并且可以从批处理文件(回到旧的 DOS 时代)和用于检查程序是否成功运行的 unix 脚本中使用根据批处理文件或脚本的性质继续。

    【讨论】:

      【解决方案3】:

      “MOV EAX,0”指令是函数的主体。标头代码用于为您的代码设置运行空间。

      “LEAVE”指令将您的代码返回到它所在的位置。尽管您说没有标准库,但链接器中还有很多其他代码。

      【讨论】:

      • leave 不会在任何地方返回任何内容。 leave 取消设置当前函数的堆栈帧。为了返回单独的ret 指令仍然是必要的。
      猜你喜欢
      • 1970-01-01
      • 2011-07-08
      • 1970-01-01
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-18
      • 1970-01-01
      相关资源
      最近更新 更多