试图在https://godbolt.org/z/G66bdzoof上运行linux (),但它返回了以下错误:
ASM生成编译器返回:0 /usr/bin/ld: /app/example.o: /app/example.o:/app/example.asm:14:未定义的对“`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问题
是否缺少某种编译器选项?
哥德波特例子正在使用以下编译选项:
-g -f elf -F stabs /tmp/compiler-explorer-compiler2022626-8227-fdi87r.9yqas/example.asm发布于 2022-07-26 16:16:46
问题不在组装,NASM执行得很好。问题是与ld的链接。编译器资源管理器构建是链接到一个没有库的静态可执行文件,大概只有ld -m elf_i386 -o foo foo.o
编译器资源管理器UI只允许您控制nasm选项,而不是ld选项,因此不能通过-lc链接C库。如果你在戈德螺栓上使用“库”下拉列表,它会说“没有为这种语言配置任何库”。(与C++相比,还有像Google::Benchmark这样的库,您可以添加告诉它链接;有些库不是头库--仅限于头,因此必须实际生成链接器选项)。
无论如何,您都希望使用调试器来单步执行代码,所以在本地安装一个dev安装程序。https://www.onlinegdb.com/有组装支持,但只有GCC (所以气体语法,AT&T或英特尔,但不符合纳斯达克指令)。
是的,使用调试器基本上是必不可少的。没有这些,你只是在浪费你自己的时间(如果你让其他人花时间看代码,你自己还没有一步一步)。就像试图制造一个蒙着眼睛的机器人。有关Linux或Windows的asm调试技巧,请参见x86标记wiki的底部。(您的当前程序只在Linux上工作;它使用32位int 0x80系统调用ABI退出。)
通常,如果使用C库函数,则需要编写main;如果使用printf之类的stdio函数,则不要使用原始_exit系统调用。当输出到管道或网络套接字(不是终端)时,stdout将被完全缓冲,而不是行缓冲,因此当您不调用fflush时,您将没有输出。
但是,即使编写自己的_start (跳过CRT启动代码),如果动态链接而不是静态链接,与libc的链接也会工作。Linux上的glibc有动态链接器挂钩,允许它在_start运行之前初始化自己(与其他一些系统不同,比如cygwin),但是如果静态链接,那么_start确实是在用户空间中运行的第一个指令。调用依赖于全局stdout等数据结构的printf之类的函数将崩溃。
https://stackoverflow.com/questions/73126416
复制相似问题