導入
関数を呼ぶ call と、戻る ret。この2つが、スタックを使って「どこに戻るか」を記憶しています。
説明
main:
mov edi, 5 ; 第1引数 = 5(呼び出し規約: 第1引数は rdi/edi)
call square ; square を呼ぶ(戻り先アドレスをスタックに積む)
; ここに戻ってくる。結果は eax に入っている
mov ebx, eax
ret
square:
mov eax, edi ; eax = 引数
imul eax, edi ; eax = eax * 引数(2乗)
ret ; スタックから戻り先を取り出してそこへ戻る
call square… ①次の命令のアドレス(戻り先)をスタックに push し、②squareへジャンプします。ret… スタックから戻り先アドレスを pop して、そこへジャンプします。だから呼び出し元に戻れます。- 引数は
rdi, rsi, rdx, rcx, ...の順、戻り値はrax―― という**呼び出し規約(System V ABI)**に従います。第1章のレジスタ表とつながります。
「関数を呼ぶと戻ってこられる」という当たり前は、スタックが戻り先を覚えていることで実現しています。