研究一个简单的代码反汇编输出和内存映射

时间:2014-10-04 15:39:53

标签: c++ memory assembly

有人可以向我解释下面发生了什么吗? 问题:

  • 为什么我的变量不在寄存器中?
  • 为什么寄存器rbp包含内存缓存行的地址而不包含i的地址(即4字节)?
  • 这是什么意思? movl $0x5,-0x4(%rbp); %negative 0x4是什么意思?

int main(int argc, char* argv[])
{
    int i = 5;  // line 25
    i ++;       // line 26
}
-----------------------------------------------------

Disassembly:
25                  int i = 5;
00000000004014f4:   movl $0x5,-0x4(%rbp)
26                  i ++;
00000000004014fb:   addl $0x1,-0x4(%rbp)
-----------------------------------------------------

Register Values:
rbp: 0x23fe60
-----------------------------------------------------

Memory map at line 25:
Address  |   0-3  |   4-7  |   8-B  |   C-F  |
0x23fe60 |00000000|00000000|00000000|05000000|

Memory map at line 26:
Address  |   0-3  |   4-7  |   8-B  |   C-F  |
0x23fe60 |00000000|00000000|00000000|06000000|

注意:上面是由Eclipse生成的,我在64位机器上使用mingw进行编译。

4 个答案:

答案 0 :(得分:3)

  • 为什么变量不留在寄存器中?

因为你的编译器不喜欢它。它决定将变量i放在堆栈上。

  • 为什么寄存器rbp包含内存缓存行的地址而不包含i的地址(即4字节)?

rbp不包含内存缓存的地址rbp基本指针,它指向堆栈的底部。 -0x4(%rbp)是变量i在内存中(堆栈上)的位置。它表示rbp MINUS 4 的值。为什么4?因为i需要4个字节。所以 i的地址。

请参阅http://en.wikibooks.org/wiki/X86_Disassembly/The_Stack

  • 这是什么意思? movl $0x5,-0x4(%rbp); %negative 0x4的含义是什么?

有两种常见的汇编语法

  1. AT& T,这是一个难以理解的混乱
  2. “常规”英特尔语法
  3. 遗憾的是,您的代码位于AT& T. %是AT& T语法中引用变量的方式。 -0x4是数字-4的十六进制表示(请参阅上面的答案)。

    请参阅http://en.wikipedia.org/wiki/X86_assembly_language#Syntax

答案 1 :(得分:2)

  • 没有'缓存地址' - 缓存是从程序中抽象出来的,只有CPU和操作系统知道缓存以及如何将内存地址转换为缓存地址'

  • 变量i在堆栈上分配。 rbp是框架的基本指针'它指向当前函数在堆栈上执行的帧。所以-0x4(%rbp)意味着在偏移量4(向后 - 后来回到那个点)到寄存器rbp,变量i被定位。 详细了解堆栈的工作原理及其框架的外观:http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/stack.html

  • movl $0x5,-0x4(%rbp)是有效的,你是对的,看起来很奇怪来自英特尔语法世界。但实际上这是AT& T语法代码的一个例子。请阅读此处以获取进一步说明:http://en.wikipedia.org/wiki/X86_assembly_language#Syntax

我真的认为你会从阅读中受益:http://lwn.net/Articles/250967, 在思考大图片时,它确实给了我很多帮助。关于记忆。

答案 2 :(得分:2)

  • 你的意思是“不在登记簿中吗?”因为您的程序没有使用高优化设置进行编译(但如果您使用高优化值编译,则整个过程将为空,因为它不会“执行任何操作”(没有副作用)。包含您的变量的地址肯定会是当CPU执行这些指令时引入内存缓存

    • register rbp包含函数堆栈框架的基础,它是从中分配本地自动变量的地方,这是由您的语言的调用约定指定的。

    • 在这种情况下,mov指令是立即值到内存位置的移动。 %作为注册名称的前缀。由于堆栈传统上向下增长,因此本地自动变量的偏移量是从帧/堆栈的底部开始的负偏移量。

答案 3 :(得分:0)

  • 为什么我不会留在寄存器中?

这是编译器的决定。在过去,人们会使用关键字register向编译器提供经常使用该变量的提示,以便编译器可以使用该字段的寄存器而不是堆栈条目。现在不建议这样做,因为编译器现在非常聪明,并且通常会比我们更好地进行优化。

  • 为什么寄存器rbp包含内存缓存行的地址和 不是i的地址(即4个字节)?

在输入函数时,局部变量将被压入堆栈。在此rbp之后将设置为rsp的值,即堆栈指针。当rsp指向下一个空闲空间时,rbp也是如此,所以你需要-4来获取推送到堆栈的最后一个变量的地址,在本例中为i

  • 这是什么意思? movl $ 0x5,-0x4(%rbp);什么%和 负0x4是什么意思?

将值0x5放入地址rbp-4。