1
votes

I am new to ASM, and I'm trying to create a basic hello world program, using a function :

section .text
     global main

print_msg:

     push rbp
     mov rbp, rsp

     mov rax, 1
     mov rdi, 1
     mov rsi, Buffer       ;to change
     mov rdx, BufferSize   ;to change
     syscall

     mov rsp, rbp
     pop rbp

     ret

main:

     mov rdi, Buffer
     mov rsi, BufferSize
     call print_msg

     mov rax, 60
     mov rdi, 0
     syscall

section .rodata

Buffer:     db 'Hello, world !', 0x0A
BufferSize: equ $-Buffer

This code actually work, but only because I directly copied Buffer in rsi and BufferSize in rdx, in my "print_msg" function, but I want to copy the received arguements in these two registers, I saw something like :

mov rsi, [rsp + 8]
mov rdx, [rsp + 12]

But It doesn't work here.

2

2 Answers

2
votes

x86-64 uses registers to pass arguments, as your code also illustrates:

 mov rdi, Buffer
 mov rsi, BufferSize
 call print_msg

If you loaded rdi and rsi with the arguments, why do you expect them to be on the stack in the called function? CALL doesn't do anything to the registers, and only puts the return address on the stack. Thus, your two arguments are still happily in rdi and rsi. Just mov them to the correct place:

 mov rdx, rsi
 mov rsi, rdi
 mov rax, 1
 mov rdi, 1
 syscall
1
votes

You can; you need to push the arguments before the call. Like this:

push Buffer
push BufferSize
call print_msg
add rsp, 16

Then they become accessible as [rbp+16], [rbp+24]. But that's a bad idea. Commonly accepted x86_64 calling conventions call for passing first few arguments in registers. On Linux, that's RDI, RSI, RDX, RCX, R8, and R9. So as long as you don't reset RSI and RDI inside the function (like you do now), you're good.