簡體   English   中英

如何在 godbolt.org 上使用 NASM 程序集調用 printf()?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM