Home > Back-end >  How to link my nasm program to access argc?
How to link my nasm program to access argc?

Time:11-22

Working on Linux, x86_64.

I'm learning assembly programming, and having a hard time finding appropriate documentation and discerning which documentation is applicable.

Using nasm as my assembler, and ld as my linker, I produced this program to exit the program with a code equal to the number of program arguments.

nasm -felf64 hello.s && ld hello.o && ./a.out "$@"
echo $?
section .text
   global _start
    
_start:
    mov rax, 60
    syscall

This is based on the idea that the syscall takes the exit code from rdi, and the argc value also seems to be placed in rdi, based on some experiments with Godbolt Compiler Explorer.

This doesn't work, always producing exit code 0.

However, when I change _start to main and use gcc instead of ld, the program works.

nasm -felf64 hello.s && gcc -o a.out hello.o && ./a.out "$@"
echo $?
section .text
   global main
    
main:
    mov rax, 60
    syscall

This produces an exit code equal to the number of shell arguments.

After much trial and error and wandering Google, I was finally able to get this working, but my problem is that I don't know why it works. I'm really struggling to know which documentation I need to be reading. Currently I'm just trying everything I can find and piecing together the bits that work.

CodePudding user response:

main is a function that takes argc as its first argument, so when main is entered, the value of argc will be in rdi, as you expected. _start is not a function, so registers and the stack will not be set up as they'd be if it were. According to the AMD64 System V ABI, _start will instead find argc on top of the stack (i.e., where the return address would be if it were a function). To make your program work with it, do mov rdi, [rsp] before syscall (it doesn't matter whether it's before or after mov rax, 60).

When you use gcc instead of ld, code for _start from glibc gets linked into your program that calls main with the standard function calling convention, which is why it works then.

  • Related