【问题标题】:What is the correct way to link assembly code with C code using gcc使用 gcc 将汇编代码与 C 代码链接的正确方法是什么
【发布时间】:2018-05-05 05:35:45
【问题描述】:

假设您有以下汇编文件:

  .file "print.s"
  .intel_syntax noprefix

  .text

  .globl _start
  .type _start, @function
_start:
  mov rax, 1
  mov rdi, 1
  lea rsi, hello_string
  mov rdx, 14
  syscall
  mov rax, 60
  mov rdi, 0
  syscall
  .size _start, .-_start

  .file "string.s"
  .intel_syntax noprefix

  .data

  .globl hello_string
  .type hello_string, @object
hello_string:
  .string "Hello, world!\n"
  .size hello_string, 14

如果你运行as string.s -o string.oas print.s -o print.o,然后运行ld *.o -o hello.elf,你会得到一个打印Hello, world!的可执行文件。现在假设您将 print.s 中的 _start 标签更改为 print,并且您有以下 C 文件:

// main.c
void print(void);

int main (void) {
  print();
  return 0;
}

我想运行 gcc -o main.elf main.c string.s print.s 之类的东西来获取我的两个汇编文件并将它们链接到标准 C 运行时。所写的这个命令不起作用。我收到以下错误消息:

/usr/bin/ld: /tmp/ccc1yRif.o: relocation R_X86_64_32S against symbol `hello_string' can not be used when making a shared object; recompile with -fPIC

我不知道如何正确使用 -fPIC 标志来使事情正常进行。我什至不确定这是否是我应该做的。我可以尝试使用内联汇编器来执行此操作,但对于我的实际用例,这将非常烦人,我更愿意学习如何将汇编块正确链接到我的 C 程序中。我无法在网上找到很多关于此的信息。

问题:如何正确使用 GNU 链接器将汇编文件链接到 C 运行时?

编辑:在How to link a C object file with a Assembly Language object file? 中,OP 询问如何仅使用ld 来解决类似的链接问题。我想使用gcc,这是链接问题中推荐的解决方案,但我什至无法让它工作。

【问题讨论】:

  • @RobinGreen:嗨,罗宾,这个问题有点不同。 OP 询问如何仅使用ld 进行链接。我想使用gcc,这是他们推荐的答案,但它对我不起作用,我不明白为什么
  • 但是您的称呼方式与推荐答案中的方式不同。显然,您可以省略 -m32,因为您正在编写 64 位代码,但看起来您应该输出 .o 而不是 .elf
  • 我明白你在说什么。也许我应该首先从我​​的 c 文件生成一个目标文件,然后将三个目标文件与 gcc 组合在一起。但是,当我尝试使用 gcc main2.c -o main2.o 准确编译 OPs C 文件 main2.c 时,链接器出错并抱怨对 strlength 的未定义引用
  • @RobinGreen:你知道如何让 gcc 输出一个可重定位的目标文件吗?我在手册中看不到它的标志。 -o 输出一个elf 文件,opsys 可以直接加载该文件。这是不可重定位的,所以不能再链接了

标签: c assembly x86-64


【解决方案1】:

好的,所以我现在想通了。错误消息似乎告诉我 gcc 正在尝试创建共享对象。这让我想到了问题gcc 6.2.0 is attempting to create shared object when it shouldn't?

解决办法是运行gcc -no-pie main.c string.s print.s -o main.elf

根据手册页,-no-pie 告诉 gcc 不要生成与位置无关的可执行文件。

【讨论】:

  • 更好的解决方案是编写定义和引用字符串的 C 代码(例如,返回字符串地址的小函数),将其编译为程序集,检查程序集以查看编译器以与位置无关的方式引用字符串,然后在您自己的代码中使用该技术。
  • @EricPostpischil:是的,这是个好主意!谢谢你的想法
猜你喜欢
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 2013-04-11
  • 2010-12-12
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多