133 lines
2.9 KiB
ArmAsm
133 lines
2.9 KiB
ArmAsm
.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
|