首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OSX64位C++ DIsassembly逐行

OSX64位C++ DIsassembly逐行
EN

Stack Overflow用户
提问于 2013-02-23 06:26:15
回答 3查看 525关注 0票数 0

我一直在通读以下系列文章:http://www.altdevblogaday.com/2011/11/09/a-low-level-curriculum-for-c-and-c

显示的反汇编代码和我在运行相同代码时生成的反汇编代码有很大的不同,我缺乏对这些差异的理解。

有没有人可以一行一行地介绍它,也许可以解释它在每一步中做了什么?从我所做的搜索中,我感觉到前几行与帧指针有关,在我的反汇编代码中似乎也有一些额外的行,以确保在将新值放入寄存器之前是空的(在本文的代码中没有)。

我使用XCode 4中的g++编译器在OSX (原作者使用的是Windows)上运行这个程序。我真的不知道这些差异是否是由于操作系统、架构(32位vs64位可能?)或者编译器本身。我猜它甚至可能是代码--我的代码包装在main函数声明中,而原始代码没有提到这一点。

我的代码:

代码语言:javascript
复制
int main(int argc, const char * argv[])
{

    int x = 1;
    int y = 2;
    int z = 0;

    z = x + y;

}

我的反汇编代码:

代码语言:javascript
复制
0x100000f40:  pushq  %rbp
0x100000f41:  movq   %rsp, %rbp
0x100000f44:  movl   $0, %eax
0x100000f49:  movl   %edi, -4(%rbp)
0x100000f4c:  movq   %rsi, -16(%rbp)
0x100000f50:  movl   $1, -20(%rbp)
0x100000f57:  movl   $2, -24(%rbp)
0x100000f5e:  movl   $0, -28(%rbp)
0x100000f65:  movl   -20(%rbp), %edi
0x100000f68:  addl   -24(%rbp), %edi
0x100000f6b:  movl   %edi, -28(%rbp)
0x100000f6e:  popq   %rbp
0x100000f6f:  ret    

原始文章中的反汇编代码:

代码语言:javascript
复制
mov    dword ptr [ebp-8],1
mov    dword ptr [ebp-14h],2
mov    dword ptr [ebp-20h],0
mov    eax, dword ptr [ebp-8]
add    eax, dword ptr [ebp-14h]
mov    dword ptr [ebp-20h],eax

完整的逐行分解将非常有启发性,但对理解这一点的任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-23 06:41:17

您的反汇编代码和本文的代码之间有两个主要区别。

其一,本文使用的是Intel汇编语法,而反汇编代码使用的是传统的Unix/AT&T汇编语法。在Wikipedia上记录了两者之间的一些差异。

另一个不同之处在于,本文省略了设置堆栈框架的函数prologue和销毁堆栈帧并返回给调用者的函数epilogue。他反汇编的程序必须包含做这些事情的指令,但是他的反汇编程序没有显示这些指令。(实际上,如果启用了优化器,堆栈帧可能会被省略,但显然没有启用。)

还有一些细微的差异:您的代码对局部变量使用的布局略有不同,并且您的代码在不同的寄存器中计算总和。

在苹果电脑上,g++不支持发送英特尔助记符,但clang支持:

代码语言:javascript
复制
:; clang -S -mllvm --x86-asm-syntax=intel t.c
:; cat t.s
    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    push    RBP
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset rbp, -16
    mov RBP, RSP
Ltmp4:
    .cfi_def_cfa_register rbp
    mov EAX, 0
    mov DWORD PTR [RBP - 4], EDI
    mov QWORD PTR [RBP - 16], RSI
    mov DWORD PTR [RBP - 20], 1
    mov DWORD PTR [RBP - 24], 2
    mov DWORD PTR [RBP - 28], 0
    mov EDI, DWORD PTR [RBP - 20]
    add EDI, DWORD PTR [RBP - 24]
    mov DWORD PTR [RBP - 28], EDI
    pop RBP
    ret
    .cfi_endproc


.subsections_via_symbols

如果添加-g标志,编译器将添加调试信息,包括源文件名和行号。它太大了,不能完整地放在这里,但这是相关的部分:

代码语言:javascript
复制
    .loc    1 4 14 prologue_end     ## t.c:4:14
Ltmp5:
    mov DWORD PTR [RBP - 20], 1
    .loc    1 5 14                  ## t.c:5:14
    mov DWORD PTR [RBP - 24], 2
    .loc    1 6 14                  ## t.c:6:14
    mov DWORD PTR [RBP - 28], 0
    .loc    1 8 5                   ## t.c:8:5
    mov EDI, DWORD PTR [RBP - 20]
    add EDI, DWORD PTR [RBP - 24]
    mov DWORD PTR [RBP - 28], EDI
票数 0
EN

Stack Overflow用户

发布于 2013-02-23 06:29:53

原始文章中的所有代码都在您的代码中,只是周围有一些额外的东西。这一点:

代码语言:javascript
复制
0x100000f50:  movl   $1, -20(%rbp)
0x100000f57:  movl   $2, -24(%rbp)
0x100000f5e:  movl   $0, -28(%rbp)
0x100000f65:  movl   -20(%rbp), %edi
0x100000f68:  addl   -24(%rbp), %edi
0x100000f6b:  movl   %edi, -28(%rbp)

直接对应于文章中提到的6个说明。

票数 2
EN

Stack Overflow用户

发布于 2013-02-23 06:36:36

首先,“出自原始文章”的汇编程序使用的是"Intel“语法,而你的帖子中的”反汇编输出“是"AT&T语法”。这解释了指令的参数顺序是“从后到前”,让我们不要争论哪一个是对的或错的,好吗?,寄存器名称的前缀是%,常量的前缀是$。在引用寄存器的内存位置/偏移量的方式上也存在差异-英特尔汇编程序中的dword ptr [reg+offs]转换为l作为指令的后缀,而offs(%reg)

32位与64位重命名了一些寄存器- %rbp与文章代码中的ebp相同。

实际的偏移量(例如-20)是不同的,部分原因是64位的寄存器更大,还因为你将argcargv作为函数参数的一部分,这些参数作为函数开头的一部分存储-我有一种感觉,原来的文章实际上是在反汇编一个不同于main的函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15034247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档