14

I am writing code in assembler (nasm) and I want to include functions, at the moment I have

function0:

code

jmp return0

the function is called with a jump to function0 with the return linking to a label below where the function is called, however this only works if the function is called once, is there a better way to do this?

PStag
  • 291
  • 1
  • 4
  • 7
  • 4
    `call/ret`? Try looking at compiler-generated assembly to understand the basics. – EOF Mar 01 '16 at 23:17

2 Answers2

17

(assuming NASM x86)

Use call in order to call the function and ret to return from the function.

What occurs when you type call is that the address of the next instruction is pushed into the stack. When ret is hit, it will pop that address off the stack and jmp to it.

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

Calling convention dictates that the EAX register should contain the return value. Also note that the __cdecl calling convention takes parameters on the stack. Take a look at the examples in the afore-linked page. The NASM function will set up its stack frame and take parameters from the stack in order to use in the function. The value is stored in EAX.

Goodies
  • 4,439
  • 3
  • 31
  • 57
  • 2
    Calling convention varies from platform/processor to platform/processor. For example x86-64 attempts to pass a number of parameters in registers if possible before it falls back to the stack. _EAX_ doesn't always contain the return value, and again it depends on the Calling convention, and the type being returned. – Michael Petch Mar 02 '16 at 00:52
  • 3
    Conventionally, EAX contains the return value (or reference to it) more often than not, especially in x86. I know that floating points are generally returned in the XMM registers as per most calling conventions, but yes, I am referring mostly to the cdecl and stdcall conventions since OP doesn't seem to be at the point of understanding various calling conventions yet. – Goodies Mar 02 '16 at 00:57
2

Here is a new, very easy way to write functions in assembly (with many return values):

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

After that, you can access return values like this:

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
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574