簡體   English   中英

x86_64 Linux 系統的 GCC 調用約定

[英]GCC calling convention for x86_64 Linux systems

我編寫了一個最小函數來測試我是否可以調用/鏈接 C 和 x86_64 匯編代碼。

這是我的main.c

#include <stdio.h>

extern int test(int);

int main(int argc, char* argv[])
{

    int a = 10;
    
    int b = test(a);

    printf("b=%d\n", b);

    return 0;
}

這是我的test.asm

section .text
    global test

test:
    mov ebx,2
    add eax,ebx
    ret

我使用這個腳本構建了一個可執行文件

#!/usr/bin/env bash

nasm -f elf64 test.asm -o test.o

gcc -c main.c -o main.o

gcc main.o test.o -o a.out

我寫了test.asm卻沒有任何真正的線索我在做什么。 然后我離開並做了一些閱讀,現在我不明白我的代碼是如何工作的,因為我說服自己不應該這樣。

以下是我認為這不起作用的原因列表:

  • 我不保存或恢復基指針(設置堆棧幀)。 我實際上不明白為什么需要這樣做,但是我看過的每個示例都是這樣做的。
  • Linux 系統上 gcc 編譯器的調用約定應該是通過堆棧傳遞參數。 在這里,我假設參數是使用eaxebx傳遞的。 我不認為這是對的。
  • ret可能希望從某個地方獲取一個返回地址。 我很確定我沒有提供這個。
  • 甚至可能還有其他我不知道的原因。

我寫的東西產生了正確的輸出,這完全是僥幸嗎?

我對此完全陌生。 雖然我聽說過一些 x86 概念,但這是我第一次真正嘗試編寫一些概念。 必須從某個地方開始?

編輯:供將來參考,這里是一個更正的代碼

test:
                    ; save old base pointer
    push rbp        ; sub rsp, 8; mov [rsp] rbp
    mov rbp, rsp    ; mov rbp, rsp ;; rbp = rsp
                    ; initializes new stack frame

    add rdi, 2      ; add 2 to the first argument passed to this function
    mov rax, rdi    ; return value passed via rax

                    ; did not allocate any local variables, nothing to add to
                    ; stack pointer
                    ; the stack pointer is unchanged

    pop rbp         ; restore old base pointer

    ret             ; pop the return address off the stack and jump
                    ; call and ret modify or save the rip instruction pointer

我不保存或恢復基指針(設置堆棧幀)。 我實際上不明白為什么需要這樣做,但是我看過的每個示例都是這樣做的。

那是不需要的。 嘗試使用-O3編譯一些 C 代碼,然后您會發現它不會發生。

Linux 系統上 gcc 編譯器的調用約定應該是通過堆棧傳遞參數。 這里我假設參數是使用 eax 和 ebx 傳遞的。 我不認為這是對的。

那部分只是因為僥幸而起作用。 該程序集恰好也按照您編譯的方式將10放入eax中,但不能保證這種情況總是會發生。 再一次,用-O3編譯,它就不會了。

ret 可能希望從某個地方獲取一個返回地址。 我很確定我沒有提供這個。

這部分很好。 返回地址由調用者提供。 當你的函數被輸入時,它總是在堆棧的頂部。

甚至可能還有其他我不知道的原因。

是的,還有一個: ebx已保存呼叫,但您正在破壞它。 如果調用函數(或堆棧中高於它的任何東西)使用它,那么這會破壞它。

我寫的東西產生了正確的輸出,這完全是僥幸嗎?

是的,因為上面的第二點和第四點。

作為參考,這里是gcc-O0 (默認優化級別)和-O3下從您的 C 代碼生成的程序集的比較: https ://godbolt.org/z/7P13fbb1a

暫無
暫無

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

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