x86 アセンブリで関数を呼び出す


x86 アセンブリに関する 5 回目の投稿です.この投稿では、x86 アセンブリで関数を呼び出す方法を示します.

以下は、main 以外に 3 つの関数を持つ単純なプログラムです.

global main
extern printf
section .text
main:
        mov rdi, 5
        call times2
        mov rdi, rax
        call print_value
        call exit
times2:
        push rbp
        mov rbp, rsp

        mov rax, rdi
        add rax, rax

        mov rsp, rbp
        pop rbp
        ret
print_value:
        push rbp
        mov rbp, rsp

        push rdi
        mov rdi, fmt
        pop rsi
        mov rax, 0
        call printf wrt ..plt

        mov rsp, rbp
        pop rbp
        ret
exit:
        mov rdi, 0 ; exit code 0
        mov rax, 60 ; system call for exit
        syscall

section .data
fmt: db "The value is %d", 10, 0



関数に値を渡す



上記のコードは、最初の 6 つの引数 (整数とポインター) がレジスターを介して渡される Linux 64 ビット ABI に従っています.スタックまたはハードコードされたメモリ位置で引数を渡すこともできます.

機能のプロローグとエピローグ



関数 times2print_value の最初と最後を関数のプロローグとエピローグと呼びます.

  push rbp
  mov rbp, rsp

  ...

  mov rsp, rbp
  pop rbp
  ret



これは、使用するスタックを準備するための規則です.プロローグは呼び出された関数の新しいスタック フレームを作成し、エピローグは呼び出し関数のスタック フレームを復元します.