用汇编语言编写函数

15

我正在使用汇编语言(nasm)编写代码,并希望包含函数,目前我已经有:

function0:

code

jmp return0

如果函数只被调用一次,那么就可以使用跳转到函数0并将返回链接到下方标签的方法来调用该函数。但是,是否有更好的方法呢?


4
“call/ret”是指函数调用和返回操作。想要了解基础知识,可以查看编译器生成的汇编代码。 - EOF
2个回答

18

(假设是 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中。


2
调用约定因平台/处理器而异。例如,x86-64尝试在退回到堆栈之前尽可能在寄存器中传递多个参数。_EAX_并不总是包含返回值,这也取决于调用约定和返回的类型。 - Michael Petch
3
传统上,在x86中,EAX通常含有返回值(或返回值的引用),尤其是在cdecl和stdcall调用约定中。我知道浮点数通常按大多数调用约定返回到XMM寄存器中,但是,是的,我主要是指cdecl和stdcall调用约定,因为OP似乎还没有理解各种调用约定的要点。 - Goodies

2

这里有一种全新且非常简单的汇编语言函数编写方式(带有多个返回值):

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接