簡體   English   中英

裝配程序是否會與 C 庫鏈接?

[英]Will the assembly program be linked with a C library?

我有以下匯編程序,它通過適當的系統調用將“hello world”打印到屏幕上:

.global _start

     .text
            _start:
            # write(1, message, 13)
            mov     $1, %rax                # system call 1 is write
            mov     $1, %rdi                # file handle 1 is stdout
            mov     $message, %rsi          # address of string to output
            mov     $13, %rdx               # number of bytes
            syscall                         # invoke operating system to do the write
    
            # exit(0)
            mov     $60, %rax               # system call 60 is exit
            xor     %rdi, %rdi              # we want return code 0
            syscall                         # invoke operating system to exit
    message:
            .ascii  "Hello, world\n"

如果我在 ubuntu 終端中發出命令gcc hello.s ,匯編代碼是否會與網頁中的某個人爭辯的 C 庫相關聯? 如果是,那是為什么? 匯編代碼似乎沒有在任何地方引用 C 代碼。

如果我在 ubuntu 終端中發出命令 gcc hello.s ,匯編代碼是否會與網頁中的某個人競爭的 C 庫鏈接?

是的。

如果是,那是為什么?

這是gcc命令在鏈接時的記錄默認行為,因為它主要用於 C 程序。

匯編代碼似乎沒有在任何地方引用 C 代碼。

沒關系,因為匯編器和 linker 不檢查是否有。

默認行為是設置涉及 C 庫、其標准啟動代碼和您的代碼的鏈接。 如果您運行gcc -v hello.s ,您可以看到詳細信息:

/usr/lib/gcc/x86_64-linux-gnu/9/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper -plugin-opt=-fresolution=/tmp/ccVrfSjS.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/9 -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/9/../../.. /tmp/cc17H49O.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o

crt*.o文件是啟動代碼, -lc鏈接 C 庫。

在 C 程序中,標准啟動代碼應該是第一個運行的東西,以便初始化庫並按照編譯的 C 代碼所期望的方式設置各種東西。 因此,它定義了用作程序入口點的_start label,它包含對名為main的符號的調用。 因此,只有在您提供的代碼確實定義了一個名為main的符號並且沒有定義一個名為_start的符號時,鏈接才能成功(因為不允許有兩個,否則 linker 將不知道使用哪個)。 無論哪種情況,您的代碼都不是這種情況。

如果您想要一些其他行為,它由命令行開關決定,而不是由代碼的內容決定。 -nostdlib告訴 linker 不要包含 C 庫及其啟動代碼; 在這種情況下,您的代碼必須提供_start並且不需要main 因此,如果您使用gcc -nostdlib -no-pie foo.s編譯,您的代碼將成功編譯並運行。

(需要-no-pie選項,因為您的代碼在mov $message, %rsi中使用絕對 static 地址作為立即數。這些限制為 32 位,因此如果要將代碼重新定位到任意位置,則無法工作在 64 位地址空間中。更好的做法是使用 RIP 相對尋址: lea message(%rip), %rsi ,然后你就不需要-no-pie了。你也可以使用mov的形式64 位立即數, movabs $message, %rsi ,但它使用更多字節的代碼。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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