使用 GCC 32 位与 64 位说明将 C 反汇编为程序集 x86_64

问题描述 投票:0回答:1

我正在尝试通过逆向工程程序学习汇编 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 字节堆栈对齐吗?

c assembly x86-64 disassembly
1个回答
0
投票

我认为发生这种情况是因为 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
)是一个意外的值,您的代码可能会崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.