[英]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.