我最近一直在用 Windows 中的 GCC 练习 x86 汇编。我目前正在混合汇编和 C 代码以进行测试。我遇到了一些奇怪的东西,我无法用我目前的知识来解释,所以我求助于 SO。
让我们看一个最小的例子。我们在 C 代码中有一个test_func()函数,我们希望将其转换为汇编,然后从 C 代码中调用它。这个函数虽然是从项目中调用其他函数,但问题就在这里。从程序集中对其他一些 C 代码函数的任何调用都会给我一个分段错误。
我们希望在汇编中看到的函数:
#include "rf_string.h"
void test_func()
{//nonsense function, just calling another C function of the project
RF_String s;
rfString_Init(&s,"anything");
}
要求 gcc 为此吐出汇编代码给我们:
.file "to_asm.c"
.section .rdata,"dr"
.align 4
LC0:
.ascii "anything\0"
.text
.globl _test_func
.def _test_func; .scl 2; .type 32; .endef
_test_func:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $40, %esp
movl $LC0, 4(%esp)
leal -16(%ebp), %eax
movl %eax, (%esp)
movl _rfString_Init, %eax
call *%eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
然后通过将其保存到一个名为“asm_test.S”的文件中,并将其包含到项目的构建过程中,它可以很好地构建和链接。所以我们尝试制作一个简单的程序来调用该函数。
int main()
{
test_func();
return 0;
}
调试的时候问题就来了。从汇编代码内部调用另一个 C 函数时出现分段错误。对于我尝试从汇编代码调用的任何其他函数都会发生这种情况,它与我使用的函数没有任何关系。
我认为这与这里的函数调用有关:
movl %eax, (%esp)
movl _rfString_Init, %eax
call *%eax
为什么要这样做,这是什么意思?具体为什么不简单地调用该函数?%eax 寄存器前的 * 是什么?我还需要补充一点,如果我用一个简单的函数调用来替换最后两行,如下所示,一切似乎都工作得很好,这真的让我感到困惑。
call _rfString_Init
另一个小问题是关于所有这些 cfi_directives。如果我要根据 SO 中提出的问题的答案来判断,它们似乎是为异常处理目的而生成的。问题是,就代码的功能而言,我可以安全地忽略它们吗?