Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to print the number of command-line arguments in X86-64 Assembly?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

enter image description here

.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):

  1. That stack layout is for the initial entry point, not main.
  2. You are popping the rbp you just pushed and not anything already on the stack.
  3. You pop into rsp which will bite you later.
  4. While main also gets argc as an argument, the 64 bit calling convention does not pass it on the stack.
  5. You try to pass argc in rdi when it should be rsi as it is the second argument to printf. Since int is 32 bit you can use esi.
  6. printf tries to interpret argc as a string because you used %s instead of %d in the format string.
  7. You do not zero %al for printf (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"
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading