feat: we now read the passed directory in argv[1]; learned about aliasing immediate values; figured out how the syscall return values work; better error messages

This commit is contained in:
2025-08-20 00:00:19 +02:00
parent afab4501d6
commit 2b037241d1
+68 -24
View File
@@ -1,27 +1,48 @@
.global _start .global _start
exit: exit: @ r0 should have the status code to exit with
@ Exit the program with a status code of 0 mov r7, #SYS_EXIT @ Move the exit syscall number to r7 (which is the register svc reads to know which syscall to execute)
@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 svc 0 @ execute the syscall
print: @ r1 => buffer to print. r2 => how many bytes to print print: @ r1 => buffer to print. r2 => how many bytes to print. clobbers r0
@ print to stdout @ print to stdout
mov r0, #1 @ Use STDOUT fd as the write fd mov r0, #1 @ Use STDOUT fd as the write fd
mov r7, #4 @ call write(2) mov r7, #SYS_WRITE @ call write(2)
svc 0 svc 0
bx lr @ return to caller bx lr @ return to caller
fail: open_fail:
@ push the result of open() onto the stack before calling print() push {r0} @ push the result of open() onto the stack before calling print()
push {r0}
ldr r1, =OPEN_FAIL ldr r1, =OPEN_FAIL
mov r2, #31 mov r2, #31
bl print bl print
pop {r0} pop {r0}
@mov r0, #1 bl exit
dir_read_fail:
push {r0} @ save the result of open() because print() clobbers r0
ldr r1, =DIR_READ_FAIL
mov r2, #29
bl print
pop {r0}
bl exit
fd_not_dir:
ldr r1, =FD_NOT_DIR
mov r2, #24
bl print
mov r0, #1
bl exit
fd_not_found:
ldr r1, =FD_NOT_FOUND
mov r2, #58
bl print
mov r0, #1
bl exit bl exit
open_and_read_file: open_and_read_file:
@@ -29,22 +50,22 @@ open_and_read_file:
ldr r0, =FILE @ filepath ldr r0, =FILE @ filepath
mov r1, #0 @ flags mov r1, #0 @ flags
mov r2, #0 @ mode_t mov r2, #0 @ mode_t
mov r7, #5 mov r7, #SYS_OPEN
svc 0 svc 0
cmp r0, #0 cmp r0, #0
blt fail blt open_fail
@ read the file contents @ read the file contents
@ r0 needs the fd, which it should already be since the call to open() set r0 to the fd. @ 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 ldr r1, =buffer @ pointer to buffer to read into
mov r2, #50 @ how many bytes to read mov r2, #50 @ how many bytes to read
mov r7, #3 mov r7, #SYS_READ
svc 0 svc 0
@ print the contents of the buffer @ print the contents of the buffer
ldr r1, =buffer ldr r1, =buffer
mov r2, #50 mov r2, #50 @ FIXME: hardcoded badness
bl print bl print
ldr r1, =NEWLINE ldr r1, =NEWLINE
@@ -54,7 +75,7 @@ open_and_read_file:
mov r0, #0 mov r0, #0
bl exit bl exit
strlen: strlen: @ r0 holds the string length. r1 should be a pointer to the start of the string.
mov r0, #0 mov r0, #0
strlen_loop: strlen_loop:
ldrb r2, [r1, r0] ldrb r2, [r1, r0]
@@ -90,27 +111,37 @@ direntry_loop:
b direntry_loop b direntry_loop
@ TODO: read args
@ TODO: if no arg passed, use current directory.
_start: _start:
ldr r0, [sp]
cmp r0, #1
ldrgt r0, [sp, #8]
ldrle r0, =FALLBACK_DIR
@ open file @ open file
ldr r0, =DIR @ filepath @ldr r0, =FALLBACK_DIR @ filepath
mov r1, #0 @ flags mov r1, #0 @ flags
mov r2, #0 @ mode_t mov r2, #0 @ mode_t
mov r7, #5 mov r7, #SYS_OPEN
svc 0 svc 0
cmp r0, #ENOENT
beq fd_not_found
cmp r0, #0 cmp r0, #0
blt fail blt open_fail
@ read the directory contents @ read the directory contents
@ r0 needs the fd, which it should already be since the call to open() set r0 to the fd. @ 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 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. @ 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 r2, #16384 @ how many bytes to read
mov r7, #0x8d @ getdents(2) mov r7, #SYS_GETDENTS
svc 0 svc 0
cmp r0, #ENOTDIR
beq fd_not_dir
cmp r0, #0
blt dir_read_fail
mov r8, r0 @ store how many bytes the getdents syscall read, so we can use that to exit the direntry loop 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 mov r4, #0 @ initialize r4 to 0
ldr r5, =buffer ldr r5, =buffer
@@ -120,11 +151,24 @@ _start:
bl exit bl exit
.data .data
FILE: .asciz "/home/hisham/asm.txt" FILE: .asciz "/home/illusion/asm.txt"
DIR: .asciz "/home/hisham" FALLBACK_DIR: .asciz "."
OPEN_FAIL: .ascii "Failed to open file descriptor\n" OPEN_FAIL: .ascii "Failed to open file descriptor"
DIR_READ_FAIL: .ascii "Failed to read the directory\n"
FD_NOT_DIR: .ascii "File is not a directory\n"
FD_NOT_FOUND: .ascii "Failed to open file descriptor: No such file or directory\n"
NEWLINE: .ascii "\n" NEWLINE: .ascii "\n"
.equ SYS_EXIT, 0x01
.equ SYS_READ, 0x03
.equ SYS_WRITE, 0x04
.equ SYS_OPEN, 0x05
.equ SYS_FSTAT, 0x6C
.equ SYS_GETDENTS, 0x8D
.equ ENOENT, 0xFFFFFFFE
.equ ENOTDIR, 0xFFFFFFEC
.bss .bss
buffer: buffer:
.skip 16384 .skip 16384