我正在尝试通过逆向工程程序学习汇编 x86_64,以了解汇编的工作原理。为此,我使用 gcc 编译器将 C 代码反汇编为汇编代码。我为此使用的命令是
gcc -O0 -S my_C_code.c
但是,在这样做时,编译器会混合生成 32 位和 64 位指令。这让我感到困惑,因为我认为编译器只会生成 64 位指令。这方面的一个例子是:
subq $32 , %rsp
movl %edi , -20(%rbp)
movl %esi , -24(%rbp)
movq %rdx , -32(%rbp)
编译器使用 64 位指令生成第一条指令,但接下来的两条指令使用 32 位指令。程序的其他部分类似。对于上下文,上面的代码片段取自一个子例程,该子例程有 3 个参数:分别是一个整数、一个整数和一个指针。
根据我目前所读的内容,我认为发生这种情况是因为 32 位寄存器用于整数,64 位寄存器用于指针。这就提出了另一个问题。我能够成功地将 %edi 寄存器和与之相关的所有内容更改为 64 位。但是,在为 %esi 寄存器这样做时,我遇到了分段错误。这可能是由于 16 字节堆栈对齐吗?
我认为发生这种情况是因为 32 位寄存器用于整数,64 位寄存器用于指针。
可能你的 C 代码使用了
int
。我认为编译器将 int
识别为 4 字节,因此使用了 32 位寄存器。如果你使用像 int64_t
这样的东西,将使用 64 位寄存器。
我能够成功地将 %edi 寄存器和与之相关的所有内容更改为 64 位。但是,在为 %esi 寄存器这样做时,我遇到了分段错误。
记住
esi
/edi
是 4 个字节,而 rsi
/rdi
是 8 个字节。
原来的状态是
+--------+-----+
| rbp-24 | esi |
+--------+-----+
| rbp-20 | edi |
+--------+-----+
如果把
edi
改成rdi
,那么
+--------+------------------------+
| rbp-24 | esi |
+--------+------------------------+
| rbp-20 | High-bytes of rdi |
+--------+------------------------+
| rbp-16 | Low-bytes of rdi (edi) |
+--------+------------------------+
如果把
esi
改成rsi
,那么
+--------+------------------------+-----+
| rbp-24 | High-bytes of rsi | |
+--------+------------------------+-----+
| rbp-20 | Low-bytes of rsi (esi) | edi |
+--------+------------------------+-----+
您会注意到
rsi
包含 edi
值。
我不知道你的 C 代码,所以这是一个猜测,但可能是一个函数调用。如果第二个参数(在 System V AMD64 ABI 上是
rsi
)是一个意外的值,您的代码可能会崩溃。