[英]How to call printf() using NASM assembly on godbolt.org?
尝试在https://godbolt.org/z/G66bdzoof上运行 linux NASM printf() ,但它返回此错误:
ASM 生成编译器返回:0 /usr/bin/ld: /app/example.o:/app/example.asm:14: undefined reference to `printf' 执行构建编译器返回:1
extern printf
global _start
section .data
message db "Hello World!", 10, 0
section .text
_start:
; print message
push dword message
call printf
add esp, 4
; exit with code 0
mov eax,1
mov ebx,0
int 80h
问题
是否缺少某种编译器选项?
Godbolt 示例使用以下编译选项:
-g -f elf -F stabs /tmp/compiler-explorer-compiler2022626-8227-fdi87r.9yqas/example.asm
问题不在于组装,NASM 执行良好。 问题是与ld
链接。 编译器资源管理器构建链接到没有库的 static 可执行文件,大概只是ld -m elf_i386 -o foo foo.o
Compiler Explorer UI 只能让您控制nasm
选项,而不是ld
选项,因此您不能通过-lc
链接 C 库。 如果您使用 Godbolt 上的“库”下拉菜单,它会显示“没有为此语言配置库”。(与 C++ 相比,您可以添加诸如 Google::Benchmark 之类的库,告诉它链接;一些库不是仅标题,因此必须实际生成 linker 选项)。
无论如何,您都将希望使用调试器来单步执行您的代码,因此请在本地安装开发设置。 https://www.onlinegdb.com/具有汇编支持,但仅支持 GCC(因此 GAS 语法,AT&T 或 Intel,但不支持 NASM 指令)。
是的,使用调试器基本上是必不可少的。 否则,您只是在浪费自己的时间(如果您要求其他人花时间查看您自己没有单步执行的代码,那么其他人也是如此)。 这就像试图制造一个蒙着眼睛的机器人。 有关 Linux 或 Windows 的 asm 调试技巧,请参阅x86 标签 wiki的底部。 (您当前的程序只能在 Linux 上运行;它使用 32 位int 0x80
系统调用 ABI 退出。)
通常,如果您使用 C 库函数,您会想要编写一个main
,并且如果使用像 printf 这样的 stdio 函数,则不要使用原始的_exit
系统调用。 使用 output 到 pipe 或网络套接字(不是终端),stdout 将是全缓冲而不是行缓冲,所以当你调用_exit
时你不会得到 Z78E6221F6393D1356681DB_exDZ.
但是,即使您编写自己的_start
(跳过 CRT 启动代码),与 libc 的链接也可以工作,如果您动态链接,而不是 static。 Linux 上的 glibc 具有动态 linker 钩子,可以让它在_start
运行之前自行初始化(与其他一些系统不同,例如 cygwin),但是如果您静态链接,那么您的_start
确实是在用户空间中运行的第一条指令。 调用 printf 等依赖于全局stdout
等数据结构的函数将崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.