0

我有两个源文件,一个在汇编中,一个在 c 中。该程序集包含对 c 源代码中的静态字符串的引用。我在程序集中定义了一个从 c 源代码调用的函数,它工作正常,没有任何问题。但是,当我尝试从程序集中调用 printf 并将 c 源文件中的字符串作为参数传递时,我得到了乱码输出或根本没有输出。

我使用nasm将程序集编译成elf32-i386,使用gcc编译c文件。幸运的是,我尝试过使用和不使用调试信息并得到相同的结果。

以下是简单的源文件:

电源:

SECTION .text

global s_func
extern c_str
extern printf

s_func:
    sub esp, 4
    mov dword [esp], c_str
    call printf
    add esp, 4
    ret

主.c:

#include <stdio.h>
const char* c_str = "Sup."; 
extern void s_func(void);

int main(void)
{
    printf(c_str); //prints as expected
    s_func(); //weird stuff
}

生成文件:

main : main.o main.s.o
    gcc main.o main.s.o -o main

main.o :
    gcc -g -c main.c -o main.o
main.s.o :
    nasm -f elf main.s -o main.s.o

这是让我印象深刻的部分,如果你将这两个文件编译成对象然后将它们链接在一起,你会发现对 printf 的调用没有什么不同,无论是源代码。代码段相同,并且 c_str 在两个汇编列表中包含相同的地址。

在 main.c 中调用:

    printf(c_str); //prints as expected
 80483ed:   a1 14 a0 04 08          mov    0x804a014,%eax
 80483f2:   89 04 24                mov    %eax,(%esp)
 80483f5:   e8 06 ff ff ff          call   8048300 <printf@plt>

调用 main.s

08048410 <s_func>:
 8048410:   83 ec 04                sub    $0x4,%esp
 8048413:   b8 14 a0 04 08          mov    $0x804a014,%eax
 8048418:   89 04 24                mov    %eax,(%esp)
 804841b:   e8 e0 fe ff ff          call   8048300 <printf@plt>
 8048420:   83 c4 04                add    $0x4,%esp
 8048423:   c3                      ret    

也许我想保留一些寄存器?我已经在 s_func 上设置了一个正常的堆栈帧,但是它仍然失败。

4

1 回答 1

0

我认为链接目标文件时存在问题(由于在程序集中使用了打印)。

我认为最好的方法是创建一个 GAS 程序集,其中包含一个使用 c 库的 printf 的函数,然后使用“as”命令来组装文件。

然后使用 gcc 编译器编译 c 代码并使用以下命令将 GAS 创建的目标文件链接在一行中。

如果 GAS 创建的目标文件是 main_s.o,

gcc main_c.c main_s.o -o main

所以 gcc 首先创建 main_c.c 的对象格式,然后链接 main_c.o 和 main_s.o,它会给出当前链接的 elf 文件。

于 2012-04-26T05:58:09.067 回答