I’m trying to print the number of command line arguments that are present in an Assembly program in x86-64.
It’s from my understanding that argument information is stored on the stack.
I feel like I’m missing something fundamental on how to retrieve items stored from the stack but I don’t know exactly what.
.file "args.s"
.globl main
.type main, @function
.section .data
format_string:
.string "Argument: %s\n"
.section .text
main:
pushq %rbp
movq %rsp, %rbp
popq %rsp ; get argc
movq %rsp, %rdi ; move argc to rdi, first parameter register
movq $format_string, %rdi ; pass in the string to be used and give the parameter
call printf
leave
ret
.size main, .-main
>Solution :
You have the following problems (at least):
- That stack layout is for the initial entry point, not
main. - You are popping the
rbpyou just pushed and not anything already on the stack. - You pop into
rspwhich will bite you later. - While
mainalso getsargcas an argument, the 64 bit calling convention does not pass it on the stack. - You try to pass
argcinrdiwhen it should bersias it is the second argument toprintf. Sinceintis 32 bit you can useesi. printftries to interpretargcas a string because you used%sinstead of%din the format string.- You do not zero
%alforprintf(this is not fatal since it only needs to be an upper bound so any value in there should work)
Optional: your code is not position independent which is recommended (and sometimes required) in modern systems. You can put your format string into .rodata as it is read only.
A fixed version could look like:
.globl main
main:
push %rbp # rbp not used, for alignment only
mov %edi, %esi # move argc to second parameter register
lea format_string(%rip), %rdi # the format string is the first parameter
xor %eax, %eax # 0 xmm registers used
call printf@plt
xor %eax, %eax # return 0 to behave nicely
pop %rbp
ret
.section .rodata
format_string: .string "Arguments: %d\n"
