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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user