用gdb调试的时候,汇编代码前面的调试信息是什么意思?

c y*_* yj 6 c c++ gdb

用gdb调试c代码时,显示的汇编代码是

0x000000000040116c main+0 push %rbp
  0x000000000040116d main+1 mov %rsp,%rbp
!0x0000000000401170 main+4 movl $0x0,-0x4(%rbp)
  0x0000000000401177 main+11 jmp 0x40118d <main+33>
  0x0000000000401179 main+13 mov -0x4(%rbp),%eax
  0x000000000040117c main+16 mov %eax,%edx
  0x000000000040117e main+18 mov -0x4(%rbp),%eax
Run Code Online (Sandbox Code Playgroud)

第一条汇编指令前面的0x000000000040116d是这个函数的虚拟地址吗?main+1 是这个程序集与 main 函数的偏移量吗?下一个程序集是 main+4。这是否意味着第一个mov %rsp,%rbp三个字节?如果是这样,为什么是movl $0x0,-0x4(%rbp)7 个字节?

我正在使用服务器。版本是:Linux version 4.15.0-122-generic (buildd@lcy01-amd64-010) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #124~16.04.1-Ubuntu SMP.

Sam*_*hik 3

几乎是的。很明显,例如,在第一个地址上添加 4 就会得到 所示的地址main+4,在其上再添加 7 就会得到 的相应地址main+11

就这两个移动指令而言:它们非常不同,并且执行完全不同的操作。它们是两种截然不同的移动,这就是 x86 机器语言中每种移动所需的字节数,因此其中一种移动比另一种移动需要更多字节也就不足为奇了。至于确切的原因总的来说,这引发了一场关于 x86 机器语言指令集的根本原因和最初设计目标的非常漫长、广泛和激烈的讨论。其中大部分内容实际上不再适用(实际上,您可能会觉得很无聊),因为现代 x86 CPU 与其原始一代完全不同。但它必须保持二进制兼容。因此,像这样的小奇怪现象。

只是为了让您有一个基本的了解:第一步是在两个 CPU 寄存器之间移动。不需要长篇小说来说明从哪里到哪里。第二步必须指定一个 32 位值(准确地说是 0)、一个 CPU 寄存器和一个内存偏移量。这必须在某个地方指定。您必须在某处找到字节来指定所有的小细节。