web-dev-qa-db-ja.com

アセンブラで関数を書く

アセンブラー(nasm)でコードを書いていますが、関数を含めたいのですが、現時点では

function0:

code

jmp return0

関数はfunction0にジャンプして呼び出され、戻り値は関数が呼び出される下のラベルにリンクしますが、これは関数が1回呼び出された場合にのみ機能しますが、これを行うためのより良い方法はありますか?

7
PStag

(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に保存されます。

10
Goodies

これは、アセンブリで関数を記述するための新しい非常に簡単な方法です(多くの戻り値があります)。

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
0
Tazerout Islam