misc: less useless comments; document utility functions; follow the AAPCS calling convention
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
[default_config]
|
||||||
|
version = "0.10.0"
|
||||||
|
instruction_set = "arm"
|
||||||
|
assembler = "gas"
|
||||||
|
|
||||||
|
[default_config.opts]
|
||||||
|
compiler = "arm-linux-gnueabihf-gcc"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.out
|
||||||
|
out
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
/* Linux standard file descriptors */
|
||||||
|
.equ STDIN, 0x0
|
||||||
|
.equ STDOUT, 0x1
|
||||||
|
.equ STDERR, 0x2
|
||||||
|
|
||||||
|
.equ ENOENT, 0xFFFFFFFE
|
||||||
|
.equ ENOTDIR, 0xFFFFFFEC
|
||||||
|
|
||||||
@@ -1,18 +1,33 @@
|
|||||||
.include "syscalls.S"
|
.include "syscalls.S"
|
||||||
.include "errors.S"
|
.include "constants.S"
|
||||||
|
.include "string.S"
|
||||||
|
|
||||||
.global _start
|
.global _start
|
||||||
|
|
||||||
exit: @ r0 should have the status code to exit with
|
/*
|
||||||
mov r7, #SYS_EXIT @ Move the exit syscall number to r7 (which is the register svc reads to know which syscall to execute)
|
Exits the program with the provided exit code
|
||||||
svc 0 @ execute the syscall
|
|
||||||
|
|
||||||
print: @ r1 => buffer to print. r2 => how many bytes to print. clobbers r0
|
@args:
|
||||||
@ print to stdout
|
r0 => exit code
|
||||||
mov r0, #1 @ Use STDOUT fd as the write fd
|
*/
|
||||||
mov r7, #SYS_WRITE @ call write(2)
|
exit:
|
||||||
|
mov r7, #SYS_EXIT
|
||||||
svc 0
|
svc 0
|
||||||
bx lr @ return to caller
|
|
||||||
|
/*
|
||||||
|
print to stdout
|
||||||
|
|
||||||
|
@args:
|
||||||
|
r1 => pointer to buffer to print
|
||||||
|
r2 => how many bytes to print
|
||||||
|
@clobbers:
|
||||||
|
r0
|
||||||
|
*/
|
||||||
|
print:
|
||||||
|
mov r0, #STDOUT
|
||||||
|
mov r7, #SYS_WRITE
|
||||||
|
svc 0
|
||||||
|
bx lr
|
||||||
|
|
||||||
open_fail:
|
open_fail:
|
||||||
push {r0}
|
push {r0}
|
||||||
@@ -48,81 +63,12 @@ fd_not_found:
|
|||||||
mov r0, #1
|
mov r0, #1
|
||||||
bl exit
|
bl exit
|
||||||
|
|
||||||
open_and_read_file:
|
|
||||||
@ open file
|
|
||||||
ldr r0, =FILE @ filepath
|
|
||||||
mov r1, #0 @ flags
|
|
||||||
mov r2, #0 @ mode_t
|
|
||||||
mov r7, #SYS_OPEN
|
|
||||||
svc 0
|
|
||||||
|
|
||||||
cmp r0, #0
|
|
||||||
blt open_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, #SYS_READ
|
|
||||||
svc 0
|
|
||||||
|
|
||||||
@ print the contents of the buffer
|
|
||||||
ldr r1, =buffer
|
|
||||||
mov r2, #50 @ FIXME: hardcoded badness
|
|
||||||
bl print
|
|
||||||
|
|
||||||
ldr r1, =NEWLINE
|
|
||||||
mov r2, #1
|
|
||||||
bl print
|
|
||||||
|
|
||||||
mov r0, #0
|
|
||||||
bl exit
|
|
||||||
|
|
||||||
strlen: @ r0 holds the string length. r1 should be a pointer to the start of the string.
|
|
||||||
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: alphabetically sort the directory entries before printing them.
|
|
||||||
_start:
|
_start:
|
||||||
ldr r0, [sp]
|
ldr r0, [sp]
|
||||||
cmp r0, #1
|
cmp r0, #1
|
||||||
ldrgt r0, [sp, #8]
|
ldrgt r0, [sp, #8]
|
||||||
ldrle r0, =FALLBACK_DIR
|
ldrle r0, =FALLBACK_DIR
|
||||||
|
|
||||||
@ open file
|
|
||||||
@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, #SYS_OPEN
|
mov r7, #SYS_OPEN
|
||||||
@@ -133,7 +79,6 @@ _start:
|
|||||||
cmp r0, #0
|
cmp r0, #0
|
||||||
blt open_fail
|
blt open_fail
|
||||||
|
|
||||||
@ 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.
|
||||||
@@ -146,16 +91,36 @@ _start:
|
|||||||
cmp r0, #0
|
cmp r0, #0
|
||||||
blt dir_read_fail
|
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 r4, #0 @ initialize r4 to 0
|
mov r4, #0 @ initialize r4 to 0
|
||||||
ldr r5, =buffer
|
ldr r5, =buffer
|
||||||
bl direntry_loop
|
1:
|
||||||
|
push {r0}
|
||||||
|
|
||||||
|
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 {r0}
|
||||||
|
|
||||||
|
@ 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
|
||||||
|
|
||||||
|
cmp r4, r0
|
||||||
|
blt 1b
|
||||||
|
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
bl exit
|
bl exit
|
||||||
|
|
||||||
.data
|
.data
|
||||||
FILE: .asciz "/home/illusion/asm.txt"
|
|
||||||
FALLBACK_DIR: .asciz "."
|
FALLBACK_DIR: .asciz "."
|
||||||
OPEN_FAIL: .ascii "Failed to open file descriptor"
|
OPEN_FAIL: .ascii "Failed to open file descriptor"
|
||||||
DIR_READ_FAIL: .ascii "Failed to read the directory\n"
|
DIR_READ_FAIL: .ascii "Failed to read the directory\n"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Current implementation only counts the bytes instead of characters.
|
||||||
|
|
||||||
|
@args:
|
||||||
|
r1 => pointer to the string
|
||||||
|
@returns:
|
||||||
|
r0 => string length
|
||||||
|
@clobbers:
|
||||||
|
r2
|
||||||
|
*/
|
||||||
|
strlen:
|
||||||
|
mov r0, #0
|
||||||
|
1:
|
||||||
|
ldrb r2, [r1, r0]
|
||||||
|
cmp r2, #0
|
||||||
|
bxle lr
|
||||||
|
|
||||||
|
add r0, r0, #1
|
||||||
|
b 1b
|
||||||
|
|
||||||
|
/*
|
||||||
|
@input r1, r2 - pointers to the strings to compare
|
||||||
|
@return r0 - 0 if equal, -1 if a < b, 1 if a > b
|
||||||
|
*/
|
||||||
|
strcmp: @ TODO: implement
|
||||||
Reference in New Issue
Block a user