110 likes | 201 Views
Learn how assembly language programs can access command-line arguments using indirect addressing and how to display them in an efficient manner. Explore the mechanisms that the system's command-line interpreter uses to parse user inputs.
E N D
‘command-line’ arguments How can an assembly language program find out what the user typed on the command-line?
Supplying arguments • Whenever a user launches any application by typing its file’s pathname at a terminal, it is possible to supply additional inputs in the form of command-line arguments: $ ./appname <arg1> <arg2> … • But how does that program find out what was typed?
The shell’s setup • The system’s command-line interpreter will ‘parse’ the command-line input-string, and will setup an array of pointers to the line’s substrings, and provide the count of their number • Upon entry, this information will be at the top of the application’s stack
The stack upon entry command-line: $ ./myprogram abc ijk xyz application’s stack NULL argv[3] argv[2] argv[1] argv[0] 4 SS:RSP
Indirect addressing • Your application can discover the number of strings that were typed by using indirect memory addressing via register RSP .section .data argc: .quad 0 # space for argument count .section .text _start: # copy the number of command-line arguments to ‘argc’ mov (%rsp), %rax # get the argument-count mov %rax, argc # and store it in a variable …
Showing ‘argc’ • You can use our ‘rax2uint’ subroutine to convert the number of arguments into a string of decimal numerals for printing .section .data msg: .ascii “OK, the number of command-line strings was “ buf: .ascii “ \n” len: .quad . - msg .section .text _start: mov (%rsp), %rax # get the ‘argc’ value mov $buf, %rdi # point EDI to buffer call rax2uint # convert number to string # now use the ‘sys_write’ system-call to print the ‘msg’
Showing the args • You can easily design a program-loop that displays each of the command-line’s args • You have two choices for how you control your loop’s termination: • You can use the ‘count’ of the pointers • You can stop when the next pointer is NULL 3 argv[0] argv[1] argv[2] NULL RSP
Array-addressing • You also have choices about how you will access elements in the array of pointers • You can use an array-pointer that advances • You can use an array-index that increments • In either case, you’ll need to know how to use indirect forms of memory-addressing displacement( base, index, scale )
The advancing pointer # select a register to be used as a pointer to the current array-element lea 8(%rsp), %rbx # point RBX to argv[0] nxarg: mov (%rbx), %rsi # get next array-element or %rsi, %rsi # is this pointer null? jz finis # yes, finished # else display string whose address is in RSI add $8, %rbx # advance array-pointer jmp nxarg # and process its entry finis:
The incrementing index # select a register to be used as an index for the current array-element xor %rbx, %rbx # initialize array-index nxarg: mov 8(%rsp, %rbx, 8), %rsi # get next array-element or %rsi, %rsi # is the pointer null? jz finis # yes, finished # else display string whose address is in RSI inc %rbx # increment array-index jmp nxarg # and process its entry finis:
Demo: ‘myargs.s’ • This program demonstrates one way that an assembly language application can do a display of its command-line arguments • It decrements the ‘argc’ counter at (%rsp) to determine when the loop will terminate • Why do you think the programmer did not use register RCX as the loop-counter for this application? (Try it!)