你如何解释这个反汇编清单?
How would you explain this disassembly listing?
我有一个简单的 C 语言函数,在单独的文件中 string.c:
void var_init(){
char *hello = "Hello";
}
编译为:
gcc -ffreestanding -c string.c -o string.o
然后我使用命令
objdump -d string.o
查看反汇编列表。我得到的是:
string.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <var_init>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # b <var_init+0xb>
b: 48 89 45 f8 mov %rax,-0x8(%rbp)
f: 90 nop
10: 5d pop %rbp
11: c3 retq
我迷失了对这个清单的理解。 "Writing OS from scratch"这本书说了一些旧的反汇编并略微揭开了其中的谜团,但他们的清单完全不同,我什至没有看到像作者所说的那样将数据解释为我的代码。
这个命令
lea 0x0(%rip),%rax
将字符串文字的地址存储在寄存器rax
中。
还有这个命令
mov %rax,-0x8(%rbp)
将寄存器 rax
中的地址复制到分配的堆栈内存中。从堆栈中的偏移量可以看出地址占用8个字节-0x8
.
这个存储只是因为你在调试模式下编译才会发生;它通常会被优化掉。接下来发生的事情是局部变量(在堆栈指针下方的 red-zone 中)被有效地丢弃,因为函数拆除了它的堆栈框架和 returns.
您正在查看的 material 可能包括一个 sub , %rsp
或类似的分配 space 给低于 RBP 的当地人,然后再分配 space ; x86-64 System V ABI 在叶函数中不需要它(不调用任何其他函数);他们可以只使用阅读区。 (另见 ). Or compile with gcc -mno-red-zone
, which you probably want anyway for freestanding code: Why can't kernel code use a Red Zone
然后它恢复调用者 RBP 的保存值(早先设置为帧指针;请注意,space 本地的地址是相对于 RBP 寻址的)。
pop %rbp
并退出,有效地将 return 地址弹出到 RIP
retq
除了@VladfromMoscow 的解释外,我只是认为发帖者查看编译为程序集时会发生什么而不是使用 objdump 查看它可能会有所帮助,因为这样可以更清楚地看到数据 ( IMO) 和 RIP 相对寻址可能更有意义。
gcc -S x.s
产量
.file "x.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.globl var_init
.type var_init, @function
var_init:
.LFB0:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rax
movq %rax, -8(%rbp)
nop
popq %rbp
ret
.LFE0:
.size var_init, .-var_init
.ident "GCC: (Alpine 8.3.0) 8.3.0"
.section .note.GNU-stack,"",@progbits
我有一个简单的 C 语言函数,在单独的文件中 string.c:
void var_init(){
char *hello = "Hello";
}
编译为:
gcc -ffreestanding -c string.c -o string.o
然后我使用命令
objdump -d string.o
查看反汇编列表。我得到的是:
string.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <var_init>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # b <var_init+0xb>
b: 48 89 45 f8 mov %rax,-0x8(%rbp)
f: 90 nop
10: 5d pop %rbp
11: c3 retq
我迷失了对这个清单的理解。 "Writing OS from scratch"这本书说了一些旧的反汇编并略微揭开了其中的谜团,但他们的清单完全不同,我什至没有看到像作者所说的那样将数据解释为我的代码。
这个命令
lea 0x0(%rip),%rax
将字符串文字的地址存储在寄存器rax
中。
还有这个命令
mov %rax,-0x8(%rbp)
将寄存器 rax
中的地址复制到分配的堆栈内存中。从堆栈中的偏移量可以看出地址占用8个字节-0x8
.
这个存储只是因为你在调试模式下编译才会发生;它通常会被优化掉。接下来发生的事情是局部变量(在堆栈指针下方的 red-zone 中)被有效地丢弃,因为函数拆除了它的堆栈框架和 returns.
您正在查看的 material 可能包括一个 sub , %rsp
或类似的分配 space 给低于 RBP 的当地人,然后再分配 space ; x86-64 System V ABI 在叶函数中不需要它(不调用任何其他函数);他们可以只使用阅读区。 (另见 gcc -mno-red-zone
, which you probably want anyway for freestanding code: Why can't kernel code use a Red Zone
然后它恢复调用者 RBP 的保存值(早先设置为帧指针;请注意,space 本地的地址是相对于 RBP 寻址的)。
pop %rbp
并退出,有效地将 return 地址弹出到 RIP
retq
除了@VladfromMoscow 的解释外,我只是认为发帖者查看编译为程序集时会发生什么而不是使用 objdump 查看它可能会有所帮助,因为这样可以更清楚地看到数据 ( IMO) 和 RIP 相对寻址可能更有意义。
gcc -S x.s
产量
.file "x.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.globl var_init
.type var_init, @function
var_init:
.LFB0:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rax
movq %rax, -8(%rbp)
nop
popq %rbp
ret
.LFE0:
.size var_init, .-var_init
.ident "GCC: (Alpine 8.3.0) 8.3.0"
.section .note.GNU-stack,"",@progbits