0

C で呼び出し元の関数に 1 つのレジスタ値を返す x86 アセンブリ関数を記述するための正しい構文は何ですか? スタック操作が含まれている場合は、後でこれをどのようにクリーンアップしますか? 簡単な例を教えていただければ幸いです。前もって感謝します。

4

3 に答える 3

1

gccを使用すると、インラインアセンブリを使用でき、スタックについてあまり心配する必要はありません。

unsigned int get_eax(void) {
    unsigned int eax;
    asm("" : "=a" (eax));
    return eax;
}

これは、命令のないアセンブリセクションを使用し、eaxの値を。という名前の変数に入れる必要があることを示す出力制約がありますeax

unsigned intはレジスターに使用しますが、これはあまり移植性がありませんが、インラインアセンブリはとにかくあまり移植性がありません。変数はレジスタのサイズである必要があります。

于 2013-02-12T12:59:21.577 に答える
1

原則として、次のヘッダーとフッターが 32 ビット プロシージャに使用されます。

MyProc:
; prologue
    push  ebp
    mov   ebp, esp

    sub   esp, sizeof_local_variables   ; this is optional, if your procedure
                                        ; needs some local variables.

; here write your code. 
; The arguments are accessible on addresses [ebp+8+some_const]
; The local variables are on addresses [ebp-some_const] 
; where some_const must be less than sizeof_local_variables of course.

; Return the result in EAX register if you want to return it to C/C++ or other HLL.

; epilogue
    mov   esp, ebp       ; restores the stack pointer as it was on the entry
    retn  n              ; returns to the caller. If you are using CCALL convention
                         ; (usualy in C code) you have to omit "n" constant.
                         ; n is the count of bytes of the pushed arguments.
                         ; in 32bit environment it must be multiply of 4

「push ebp/mov ebp, esp」というシーケンスは、「enter」という命令で、「mov esp, ebp」は「leave」という命令で提供できますが、私はそれをより理解しやすくすることを好み、ほとんどのプラットフォームでは明示的な命令を使用する方が高速です。

于 2013-02-12T12:49:17.043 に答える
0

Linux では、int を返す場合は eax を返し、long (64 ビット モードのみ) を返す場合は rax を返します。

于 2013-02-12T12:46:33.790 に答える