[英]How to call printf() using NASM assembly on godbolt.org?
Trying to run linux NASM printf() on https://godbolt.org/z/G66bdzoof , but it's returning this error:尝试在https://godbolt.org/z/G66bdzoof上运行 linux NASM printf() ,但它返回此错误:
ASM generation compiler returned: 0 /usr/bin/ld: /app/example.o:/app/example.asm:14: undefined reference to `printf' Execution build compiler returned: 1
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
Question问题
Are there some kind of compiler options missing?是否缺少某种编译器选项?
The godbolt example is using these compilation options: Godbolt 示例使用以下编译选项:
-g -f elf -F stabs /tmp/compiler-explorer-compiler2022626-8227-fdi87r.9yqas/example.asm
The problem isn't assembling, NASM executes fine.问题不在于组装,NASM 执行良好。 The problem is linking , with
ld
.问题是与
ld
链接。 The Compiler Explorer build is linking into a static executable without libraries, presumably just ld -m elf_i386 -o foo foo.o
编译器资源管理器构建链接到没有库的 static 可执行文件,大概只是
ld -m elf_i386 -o foo foo.o
The Compiler Explorer UI only gives you control over nasm
options, not ld
options, so you can't pass -lc
to link the C library. Compiler Explorer UI 只能让您控制
nasm
选项,而不是ld
选项,因此您不能通过-lc
链接 C 库。 If you use the "library' dropdown on Godbolt, it says "no libraries are configured for this language". (vs. for C++, there are libs like Google::Benchmark you can add tell it to link with; some of the libraries are not header-only, so must actually generate linker options).如果您使用 Godbolt 上的“库”下拉菜单,它会显示“没有为此语言配置库”。(与 C++ 相比,您可以添加诸如 Google::Benchmark 之类的库,告诉它链接;一些库不是仅标题,因此必须实际生成 linker 选项)。
You're going to want to use a debugger to single-step your code anyway, so install a dev setup locally.无论如何,您都将希望使用调试器来单步执行您的代码,因此请在本地安装开发设置。 https://www.onlinegdb.com/ has assembly support, but only GCC (so GAS syntax, AT&T or Intel but not with NASM directives).
https://www.onlinegdb.com/具有汇编支持,但仅支持 GCC(因此 GAS 语法,AT&T 或 Intel,但不支持 NASM 指令)。
And yes, using a debugger is basically essential.是的,使用调试器基本上是必不可少的。 Without that you're just wasting your own time (and everyone else's if you ask other people to spend time looking at code you haven't single-stepped yourself).
否则,您只是在浪费自己的时间(如果您要求其他人花时间查看您自己没有单步执行的代码,那么其他人也是如此)。 It's like trying to build a robot blindfolded.
这就像试图制造一个蒙着眼睛的机器人。 See the bottom of the x86 tag wiki for asm debugging tips for Linux or Windows.
有关 Linux 或 Windows 的 asm 调试技巧,请参阅x86 标签 wiki的底部。 (Your current program will only work on Linux; it uses the 32-bit
int 0x80
system-call ABI to exit.) (您当前的程序只能在 Linux 上运行;它使用 32 位
int 0x80
系统调用 ABI 退出。)
Normally you'd want to write a main
if you're using C library functions, and don't use a raw _exit
system-call if using stdio functions like printf.通常,如果您使用 C 库函数,您会想要编写一个
main
,并且如果使用像 printf 这样的 stdio 函数,则不要使用原始的_exit
系统调用。 With output to a pipe or network socket (not a terminal), stdout will be full-buffered not line-buffered, so you'll get no output when you _exit
without calling fflush.使用 output 到 pipe 或网络套接字(不是终端),stdout 将是全缓冲而不是行缓冲,所以当你调用
_exit
时你不会得到 Z78E6221F6393D1356681DB_exDZ.
But linking with libc will work even when you write your own _start
(skipping the CRT startup code), if you dynamically link, not static.但是,即使您编写自己的
_start
(跳过 CRT 启动代码),与 libc 的链接也可以工作,如果您动态链接,而不是 static。 glibc on Linux has dynamic linker hooks that let it initialize itself before _start
runs (unlike on some other systems, eg cygwin), but if you statically link then your _start
is truly the first instructions that run in user-space. Linux 上的 glibc 具有动态 linker 钩子,可以让它在
_start
运行之前自行初始化(与其他一些系统不同,例如 cygwin),但是如果您静态链接,那么您的_start
确实是在用户空间中运行的第一条指令。 Calling functions like printf that depend on data structures like global stdout
will crash.调用 printf 等依赖于全局
stdout
等数据结构的函数将崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.