diff options
Diffstat (limited to 'md/writeup/arm64_assembly_command_line_arguments.md')
-rw-r--r-- | md/writeup/arm64_assembly_command_line_arguments.md | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/md/writeup/arm64_assembly_command_line_arguments.md b/md/writeup/arm64_assembly_command_line_arguments.md new file mode 100644 index 0000000..7b18375 --- /dev/null +++ b/md/writeup/arm64_assembly_command_line_arguments.md @@ -0,0 +1,199 @@ +title: ARM64 process command line arguments in assembly +keywords:raspi5,asm,c,kernel,arm64 + +# ARM64 process command line arguments in assembly + +## Intro + +Goal is to learn how to get command line arguments in assembly +and do basic processing for Linux kernel, all is tested with Raspberry Pi4 on 64bit OS. + +## Location of arguments + +Operating system provides number of arguments, command line arguments and +environment variables. Pointers for those located in stack and location +of actual values also reference in allocated stack from operating system. + +## Checking for argument number + +Number of arguments passed to command line utility is located +at stack pointers first value. Argument number located at +_sp_ address, after that there is arguments here we check number +of arguments if there is less then 1, it always more then 1 as +first argument is always program calling path + +```c + ldr x3, [sp] + cmp x3, #1 + b.LE exit_program +``` + + +## Printing out all arguments + +Pointers to the argument values are after the stack pointers first value. +As first value in stack pointer is number of arguments passed then need to +ensure to not go over it. + +### Write strlen function + +There is no default strlen instruction in assembly, so need to write +one our-self. I used _x0_ as input argument, _x1_ as internal counter +_w2_ to get and compare string char and _x1_ is where final amount +of characters is saved. + +```c +//param 0: x0 pointer to string +//using registers: x2 +//return result in x1: +strlen: + mov x1, #0 //number of arguments +loop_strlen_till_0: + //check if str[] element is 0 + ldrb w2, [x0] //ldrb w2, [x2] + //if element of string is zero then exit + cbz w2, string_element_eq_zero + //if element isnt 0 then add +1 to counted size + add x1, x1, 1 + //increase str pointer +1 + add x0, x0, #1 + b loop_strlen_till_0 +string_element_eq_zero: + ret +``` + + +### Printing out all arguments passed + +Next step is to utilize strlen function and printout all arguments +passed from command line + +```c +argument_print_loop: + //number of arguments now in x4 + //get the value of the first argument + //add x0, sp, #8 + mov x0, x4 + ldr x0, [x0] + //x0 points to firt argument of programm name + bl strlen + + //write + mov x2, x1 + mov x0, #1 //set stdout + ldr x1, [x4] //point to programm name + //ldr x5, =program_len //hopefully correct size of print_arg + //ldr x2, [x5] + mov w8, #64 + svc #0 + + //print new line + mov x0, #1 //set stdout + ldr x1, =new_line //point to newline + mov x2, #1 + mov w8, #64 + svc #0 + + add x4, x4, #8 + sub x3, x3, 1 + cmp x3, 1 + b.GE argument_print_loop +``` + +All programm seems to work ok + +## Source code + +Final source code of this example + +```c +.data + +hello_world: + .ascii "print arg program\n" +hello_world_len = . - hello_world + +new_line: + .ascii "\n" + +program_len: .quad 11 + +.text +.global _start +_start: + //save to x0 number of arguments + ldr x3, [sp] + //save to x1 address of first argument + add x4, sp, #8 + + //write hello world + mov x0, #1 + ldr x1, =hello_world + ldr x2, =hello_world_len + mov w8, #64 + svc #0 + +argument_print_loop: + //number of arguments now in x4 + + //get the value of the first argument + mov x0, x4 + ldr x0, [x0] //x0 points to firt argument of programm name + bl strlen + + //write + mov x2, x1 + mov x0, #1 //set stdout + ldr x1, [x4] //point to programm name + mov w8, #64 + svc #0 + + //print new line + mov x0, #1 //set stdout + ldr x1, =new_line //point to newline + mov x2, #1 + mov w8, #64 + svc #0 + + + add x4, x4, #8 + sub x3, x3, 1 + cmp x3, 1 + b.GE argument_print_loop + + +exit_program: + //exit(0) + ldr x0, #0 + mov w8, #93 + svc #0 + +//param 0: x0 pointer to string +//using registers: x2 +//return result in x1: +strlen: + mov x1, #0 //number of arguments +loop_strlen_till_0: + //check if str[] element is 0 + ldrb w2, [x0] //ldrb w2, [x2] + //if element of string is zero then exit + cbz w2, string_element_eq_zero + //if element isnt 0 then add +1 to counted size + add x1, x1, 1 + //increase str pointer +1 + add x0, x0, #1 + b loop_strlen_till_0 +string_element_eq_zero: + ret +``` + +## Comilation size + +|Program name |Uncompressed size|Compressed size| +|---|---|---| +|print_arg| 1552 bytes | 481 bytes | + + +## Links + +[Make tiny binary](/writeup/arm64_make_tiny_binary.md)
\ No newline at end of file |