アセンブラー(nasm)でコードを書いていますが、関数を含めたいのですが、現時点では
function0:
code
jmp return0
関数はfunction0にジャンプして呼び出され、戻り値は関数が呼び出される下のラベルにリンクしますが、これは関数が1回呼び出された場合にのみ機能しますが、これを行うためのより良い方法はありますか?
(NASM x86を想定)
関数を呼び出すにはcall
を使用し、関数から戻るにはret
を使用します。
call
と入力すると、次の命令のアドレスがスタックにPush
されます。 ret
がヒットすると、そのアドレスはpop
スタックから外れ、jmp
がそれにアドレス指定されます。
func:
xor eax, eax
mov eax, 10
add eax, 5
ret ;// essentially identical to: pop [register] -> jmp [register]
_start:
call func
mov ebx, eax ;// Address of this instruction is pushed onto the stack
;// ebx is now 15
呼び出し規約では、EAX
レジスタに戻り値を含める必要があります。 __ cdecl呼び出し規約 はスタック上のパラメーターを受け取ることにも注意してください。前述のリンク先のページの例をご覧ください。 NASM関数は、関数で使用するために、スタックフレームを設定し、スタックからパラメーターを取得します。値はEAX
に保存されます。
これは、アセンブリで関数を記述するための新しい非常に簡単な方法です(多くの戻り値があります)。
function:
sub esp, ( 4 * ret_count)
pushad
mov ebp, esp
;code
;acces first argument with ( dword[ebp + 32 + (4*ret_count) + (4*arg_num)]
;write first return value with ( mov dword[ebp + 36 + (4*ret_pointer)]
popad
add esp, ( 4 * ret_count)
ret
その後、次のような戻り値にアクセスできます。
call function
mov eax, dword[esp] ; 1st ret
mov ebx, dword[esp - 4] ; 2nd ret
; or you can just pop them :
pop eax
pop ebx