.global _start exit: @ Exit the program with a status code of 0 @mov r0, #0 @ `exit` syscall requires the status code to be written to r0 mov r7, #1 @ `exit` syscall's number is 1. Move it to r7 (which is the register svc reads to know which syscall to execute) svc 0 @ execute the syscall print: @ r1 => buffer to print. r2 => how many bytes to print @ print to stdout mov r0, #1 @ Use STDOUT fd as the write fd mov r7, #4 @ call write(2) svc 0 bx lr @ return to caller fail: @ push the result of open() onto the stack before calling print() push {r0} ldr r1, =OPEN_FAIL mov r2, #31 bl print pop {r0} @mov r0, #1 bl exit open_and_read_file: @ open file ldr r0, =FILE @ filepath mov r1, #0 @ flags mov r2, #0 @ mode_t mov r7, #5 svc 0 cmp r0, #0 blt fail @ read the file contents @ r0 needs the fd, which it should already be since the call to open() set r0 to the fd. ldr r1, =buffer @ pointer to buffer to read into mov r2, #50 @ how many bytes to read mov r7, #3 svc 0 @ print the contents of the buffer ldr r1, =buffer mov r2, #50 bl print ldr r1, =NEWLINE mov r2, #1 bl print mov r0, #0 bl exit strlen: mov r0, #0 strlen_loop: ldrb r2, [r1, r0] cmp r2, #0 bxle lr add r0, r0, #1 b strlen_loop direntry_loop: cmp r4, r8 bxge lr push {lr} add r1, r5, #10 @ offset 10 bytes into the dirent struct to reach d_name. bl strlen mov r2, r0 bl print ldr r1, =NEWLINE mov r2, #1 bl print pop {lr} @ load the value (as 16-bits zero-extended as opposed to loading 32-bits and then extending that ourselves with UXTH) @ in the memory address of r5 offset by 8 bytes to get us the d_reclen ldrh r6, [r5, #8] add r5, r5, r6 @ skip to the next dirent add r4, r4, r6 @ accumulate how many bytes we read b direntry_loop @ TODO: read args @ TODO: if no arg passed, use current directory. _start: @ open file ldr r0, =DIR @ filepath mov r1, #0 @ flags mov r2, #0 @ mode_t mov r7, #5 svc 0 cmp r0, #0 blt fail @ read the directory contents @ r0 needs the fd, which it should already be since the call to open() set r0 to the fd. ldr r1, =buffer @ pointer to linux_dirent structure @ TODO: we can allocate the required memory on the stack instead of in the bss section I think. mov r2, #16384 @ how many bytes to read mov r7, #0x8d @ getdents(2) svc 0 mov r8, r0 @ store how many bytes the getdents syscall read, so we can use that to exit the direntry loop mov r4, #0 @ initialize r4 to 0 ldr r5, =buffer bl direntry_loop mov r0, #0 bl exit .data FILE: .asciz "/home/hisham/asm.txt" DIR: .asciz "/home/hisham" OPEN_FAIL: .ascii "Failed to open file descriptor\n" NEWLINE: .ascii "\n" .bss buffer: .skip 16384 name: .skip 256