Search code examples
linuxassemblycommand-linex86-64calling-convention

Function arguments in x86-64 asm


So I have to do this project for school that consists of reading a file in brainfuck and interpret it as assembly. The code works if I save the file path as a String inside the .data section, but what I want to have it so it gets the file path as an argument when starting the code in the terminal.

I have tried popping 3 times(since the stack should be number of args/ addres of program/ first arg), and then setting %rdi to the value at the adress of the 3rd popped item, but it returns "./interpreter" instead of the file path

This is the code that works:

.data
filePath: .asciz "brainF.b"
fileRead: .asicz "r"

.text
.global main
main:
    call fileReader #moves filePath to %rdi, fileRead to %rsi, calls fopen and reads the file
    #code that grabs the read string and interprets it

but what I want is:

.data
fileRead: .asciz "r"

.text
.global main
main:
    #get 1st argument from terminal(file path) and store it in %rdi
    call fileReader #moves fileRead to %rsi, calls fopen and reads the file

and here's how I have to compile and link(this part can't be changed, that's how my teacher wants me to do it):

gcc -o interpreter interpreter.s
./interpreter brainF.b

Solution

  • The 64 bit calling convention passes first 6 function arguments in registers, so argc is in rdi and argv is in rsi. The first command line argument is argv[1] so to access that you need to load 8(%rsi):

    .globl main
    main:
        subq $8, %rsp           # align stack
        movq 8(%rsi), %rsi      # fetch argv[1]
        leaq fmt(%rip), %rdi    # format string
        xorl %eax, %eax         # no xmm used
        call printf             # print
        xorl %eax, %eax         # zero return value
        addq $8, %rsp           # restore stack
        ret                     # done
    
    .data
    fmt: .string "First argument is %s\n"
    

    $ ./a.out foo bar
    First argument is foo
    

    Of course you should check argc to see if you received enough arguments.