需要解释 64 位汇编指令而不是 32 位

rai*_*ver 1 x86 assembly disassembly 32bit-64bit att

我正在阅读 Hacking : The Art of Exploitation 这本书,它使用 32 位汇编,我的机器是 64 位。现在我明白这不是一件好事,但这就是问题所在。

当我调试这个程序时,

  Reading symbols from ./a.out...
(gdb) break main
Breakpoint 1 at 0x113d: file first.c, line 6.
(gdb) run
Starting program: /home/kingvon/Desktop/asm/a.out 

Breakpoint 1, main () at first.c:6
6               for(i=0; i < 10; i++){
(gdb) x/3i $rip
=> 0x55555555513d <main+8>:     movl   $0x0,-0x4(%rbp)
   0x555555555144 <main+15>:    jmp    0x555555555156 <main+33>
   0x555555555146 <main+17>:    lea    0xeb7(%rip),%rdi        # 0x555555556004
Run Code Online (Sandbox Code Playgroud)

这是我在我的机器上看到的(64 位),

0x55555555513d <main+8>:     movl   $0x0,-0x4(%rbp)
Run Code Online (Sandbox Code Playgroud)

但在示例(32 位)中,它说:

0x55555555513d <main+8>:     mov   DWORD PTR [ebp-4],0x0
Run Code Online (Sandbox Code Playgroud)

从读取 32 位程序集很明显,这应该意味着机器会将 0 的值移动到存储在 EBP 寄存器中的内存位置减去 4。我知道两条指令做同样的事情,但我觉得 64 指令看起来不像它的真正含义。64 条指令如何解释/措辞?我知道寄存器名称在 64 位上是不同的

Pet*_*des 5

仅构建 32 位可执行文件可能最容易,因此您可以更密切地关注本书,使用gcc -m32. 在您从中学习时,不要尝试将教程移植到另一个操作系统或 ISA,这很少成功。(例如,不同的调用约定,而不仅仅是不同的大小。)

在 GDB 中,使用像你的书展示的那样set disassembly-flavor intel获得 GAS.intel_syntax noprefix反汇编,而不是默认的 AT&T 语法。对于 objdump,请使用objdump -drwC -Mintel. 另请参阅如何从 GCC/clang 程序集输出中去除“噪音”?有关查看 GCC 输出的更多信息。

(参见https://stackoverflow.com/tags/att/infohttps://stackoverflow.com/tags/intel_syntax/info)。

两条指令都是立即数 0 的双字存储,相对于帧指针指向的位置偏移 -4。 (这是它的实现方式,i=0因为您在编译时禁用了优化。)

  • @raincouver:所以安装你的发行版的`gcc-multilib`包或者它所谓的任何东西,比如Arch的`lib32-gcc-libs`。(没有它,您可以构建并链接纯 asm 静态可执行文件,在其中编写自己的 `_start` 并且不链接任何库,但其他所有内容都需要 `/usr/lib32/libc.so` 等等,是的32 位标头甚至可以编译。) (2认同)