1

私は Linux 64 ビットで NASM を研究しており、いくつかのコード例を実装しようとしています。ただし、次の例で問題が発生しました。関数 donothing は NASM で実装されており、C で実装されたプログラムで呼び出されることになっています。

ファイル main.c:

#include <stdio.h>
#include <stdlib.h>

int donothing(int, int);

int main() {
    printf(" == %d\n", donothing(1, 2));
    return 0;
}

ファイル first.asm

global donothing

section .text
    donothing:
    push rbp
    mov rbp, rsp
    mov eax, [rbp-0x4]
    pop rbp
    ret

donthing が行うことは、最初のパラメーターの値を返すことだけです。しかし、donothing が呼び出されると、値 0 が 1 ではなく出力されます。rbp+0x4 を試しましたが、うまくいきません。次のコマンドを使用してファイルをコンパイルします。

  nasm -f elf64 first.asm && gcc first.o main.c

gcc -s を使用して C で関数 'test' をコンパイルすると、パラメーターを取得するために生成されるアセンブリ コードは次のようになります。

int test(int a, int b) {
    return a > b;
}

上記の関数 'test' に対して gcc によって生成されたアセンブリ:

test:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    movl    -4(%rbp), %eax
    cmpl    -8(%rbp), %eax
    setg    %al
    movzbl  %al, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

では、何もしないことの何が問題なのですか?

4

1 に答える 1

4

x86-64 呼び出し規約では、最初のいくつかのパラメーターは、スタックではなくレジスターで渡されます。あなたの場合、12RDIとを見つける必要がありRSIます。

コンパイルされた C コードでわかるように、afromedibfromを取得しますesi(ただし、それらをメモリに配置することで不要な中間ステップを実行します)。

于 2013-06-19T15:04:51.377 に答える