【问题标题】:Using stdlib.h functions directly in assembly直接在汇编中使用 stdlib.h 函数
【发布时间】:2019-09-28 15:30:20
【问题描述】:

我必须做一个汇编 (x86) 程序,它从用户输入中获取 2 个长数字,使用函数将它们相加,然后打印结果。当我使用 read 系统调用时,我得到一个 ASCII 十六进制代码的字符串,我不能像这样添加数字。所以我想使用atol,它是stdlib.h 的一个函数,将字符串转换为long。如何在程序集中包含库?还有另一种方法可以做到这一点吗?

我已经试过了:

  1. .file "stdlib.h"(我有当前目录下的lib)

错误:未定义对atol'的引用

  1. 使用 clang 将 stdlib.h 与 .s 文件一起编译

错误:stdlib.h:文件无法识别:文件格式无法识别

  1. 只用#include<stdlib.h> 制作一个.c 文件并用.s 文件编译它

错误:未定义对 `atol' 的引用

我运行的comads是

clang function.s -c -g
ld function.o -o function

【问题讨论】:

  • stdlib.h 是头文件,而不是库。它仅包含函数声明。请发布您尝试过的实际代码,因为它应该可以使用atol。另外,你用什么汇编器?
  • 请编辑您的问题以添加您的完整代码。发布代码,以便我可以将其复制到文件中并编译它以重现问题。还要发布您键入的确切命令以组装和链接代码。
  • 完美,谢谢
  • 只是不要尝试使用stdlib.h
  • 如果这是家庭作业,我会与教授核实,以确保您可以在 C 库中调用 atoi 之类的东西。教授可能希望您自己编写这样的转换程序。

标签: c linux assembly clang x86-64


【解决方案1】:

链接器抱怨没有找到atol,因为它是C 库中的一个函数,但是您没有告诉链接器在链接期间将C 库添加到您的程序中。要解决此问题,请将 -lc 传递给链接器以在链接期间添加 C 库:

ld -o function function.o -lc

-lc 放在最后非常重要,否则链接可能无法正常工作。这是因为链接器按照您指定的顺序从库中选择函数。当您在function.o 之前指定-lc 时,它会忽略该库,因为它现在不需要其中的任何内容。然后它看到function.o 带有未定义的atol 并且没有找到定义,导致链接失败。

最后,当你使用 C 库时,你应该像普通的 C 程序一样从main 函数启动你的程序(即将_start 重命名为main)并通过 C 编译器链接:

clang -g -o function function.s

这会导致 C 库自动链接并正确初始化它,从而防止一些奇怪的错误。如果您使用 C 库中的任何 IO 函数,例如 printf,您还应该通过调用 exit 来结束您的程序,以便正确刷新标准 IO 流。

请注意,stdlib.h 文件是一个红鲱鱼。汇编编程不需要头文件。它们的目的是告诉 C 编译器某些函数的类型是什么。如果您不使用 C 编译器,则不需要这样做。 .file 指令没有按照您的预期执行。

【讨论】:

  • clang -nostartfiles start.s 也有效:省略 CRT 但包括 libc 等默认库。
  • @PeterCordes 是的,但是 libc 可能没有正确初始化,你需要知道你在做什么。
  • OP 正在通过 x86-64 System V ABI 使用 syscall。至少在 Linux 上,动态链接的 glibc 会自行初始化。关于 MacOS 及其 libc 的 IDK。一般来说,如果您想使用 libc 函数,建议使用main 而不是_start 并不是 建议。但是学习 libc 可以使用动态链接器技巧来初始化自己是非常简洁的,IMO,并且手工编写 asm 的重点可能主要是一种学习练习。
  • @PeterCordes 但是如果 OP 选择做一个静态链接呢?仅仅因为 glibc 对构建不良的程序有一个后备,并不意味着依赖它是一个好主意。
【解决方案2】:

您向项目添加了一个编译单元(.c 文件)。这在包含的头文件“stdlib.h”中引入了函数的原型。你想要的是对该函数的引用。这应该在使用该函数的汇编文件中引入。

extern 语句添加到汇编程序文件应该可以完成这项工作。您不需要包含包含的 C 文件。您必须在链接器设置中添加相应的库。但是即使你成功链接了一个 EXE 文件,你也可能会遇到问题,因为 stdlib 中的某些函数需要初始化。您还必须调用 C 运行时初始化函数。

【讨论】:

  • 这可能适用于 MASM 和 NASM。他正在使用llvm-asas 汇编程序(或在后端使用它们的前端)。使用这些汇编程序,任何无法在文件中解析的符号都会自动被视为外部符号。他可能缺少的是链接到 C 库。
  • 如何将其链接到 C 库?
  • @juanpbm 将-lc 传递给链接器。这个链接在 C 库中。
猜你喜欢
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多