mirror of
https://github.com/pkivolowitz/asm_book.git
synced 2026-06-21 01:56:47 +08:00
lots of progress on file_ops - tired now
This commit is contained in:
parent
10bbbab3a1
commit
2c660ca745
1 changed files with 96 additions and 35 deletions
|
|
@ -19,71 +19,132 @@ fd .req w28
|
|||
main: stp x29, x30, [sp, -16]!
|
||||
stp x27, x28, [sp, -16]!
|
||||
bl open_file
|
||||
// w0 will contain either the file descriptor of the new
|
||||
// file or -1 for a failure. Note that the value in w0
|
||||
// has also been copied to "fd" - a register alias.
|
||||
cmp w0, wzr
|
||||
bge 1f
|
||||
// w0 will contain either the file descriptor of the new
|
||||
// file or -1 for a failure. Note that the value in w0
|
||||
// has also been copied to "fd" - a register alias.
|
||||
cmp w0, wzr
|
||||
bge 1f
|
||||
// If we get here, the open has failed. Use perror() to
|
||||
// print a meaningful error and branch to exit. The return
|
||||
// code of the program will be set to non-zero inside open_fail.
|
||||
bl open_fail
|
||||
// code of the program will be set to non-zero inside fail.
|
||||
ldr x0, =fname
|
||||
bl fail
|
||||
b 99f
|
||||
|
||||
1: // When we get here, the file is open. Write some data to it.
|
||||
// If write_file returns non-zero, it signifies an error. If
|
||||
// so, branch to the file closing code since the file is open.
|
||||
// The error message will be printed in write_data.
|
||||
bl write_data
|
||||
cbnz w0, 10f
|
||||
// If write_file returns non-zero, it signifies an error. If
|
||||
// so, branch to the file closing code since the file is open
|
||||
// after printing an error message.
|
||||
bl write_data
|
||||
cbz w0, 10f
|
||||
// If we get here, there was an error in write_data. Print
|
||||
// a reasonable error message then branch to the clean usleep
|
||||
// code.
|
||||
ldr x0, =wf // load legend
|
||||
bl fail // print error
|
||||
b 50f // branch to clean up.
|
||||
|
||||
// When we get here, we are done. Close the file.
|
||||
10: mov w0, fd
|
||||
bl close
|
||||
mov retval, wzr
|
||||
// Seek back to position zero preparing to read the file back.
|
||||
// The return value in x0 (off_t) is the return value of
|
||||
// lseek().
|
||||
10: bl seek_zero
|
||||
cbz x0, 20f
|
||||
// If we get here, the seek failed. Cause a reasonable
|
||||
// message to be printed then branch to the clean up code.
|
||||
ldr x0, =sf
|
||||
bl fail
|
||||
b 50f
|
||||
20:
|
||||
// When we get here, we are done. Close the file.
|
||||
50: mov w0, fd
|
||||
bl close
|
||||
mov retval, wzr
|
||||
|
||||
99: ldp x27, x28, [sp], 16
|
||||
ldp x29, x30, [sp], 16
|
||||
mov w0, retval
|
||||
ret
|
||||
|
||||
/* This function attempts to open a file for both reading and
|
||||
writing. Return values will be checked to ensure the file is
|
||||
opened. If successful, 0 is returned (and the file descriptor
|
||||
is squirreled away in register "fd".
|
||||
/* open_file()
|
||||
This function attempts to open a file for both reading and
|
||||
writing. Return values will be checked to ensure the file is
|
||||
opened. If successful, the fd is returned (and is squirreled
|
||||
away in register "fd"). If unsuccessful, the -1 returned by
|
||||
open() is passed back to the caller.
|
||||
|
||||
Explanation of the magic numbers:
|
||||
|
||||
int open(const char *pathname, int flags, mode_t mode);
|
||||
octal 102 for flags is O_RDRW | O_CREAT
|
||||
octal 600 for mode is rw------- i.e. read and write for
|
||||
the owner but no permissions for anyone else.
|
||||
*/
|
||||
|
||||
.equ O_FLAGS, 0102
|
||||
.equ O_MODE, 0600
|
||||
|
||||
open_file:
|
||||
stp x29, x30, [sp, -16]!
|
||||
ldr x0, =fname
|
||||
mov w1, 0102
|
||||
mov w2, 0600
|
||||
bl open
|
||||
mov fd, w0
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
stp x29, x30, [sp, -16]!
|
||||
ldr x0, =fname
|
||||
mov w1, O_FLAGS
|
||||
mov w2, O_MODE
|
||||
bl open
|
||||
mov fd, w0
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
|
||||
|
||||
/* This function uses perror to print a meaningful error
|
||||
message in the event of an open failure.
|
||||
message in the event of a failure. The string value
|
||||
passed to perror arrives to us as a pointer in x0.
|
||||
*/
|
||||
|
||||
open_fail:
|
||||
fail:
|
||||
stp x29, x30, [sp, -16]!
|
||||
ldr x0, =fname
|
||||
bl perror
|
||||
mov retval, 1
|
||||
bl perror
|
||||
mov retval, 1
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
|
||||
/* ssize_t write(int fd, const void *buf, size_t count);
|
||||
*/
|
||||
|
||||
write_data:
|
||||
stp x29, x30, [sp, -16]!
|
||||
str x20, [sp, -16]!
|
||||
mov w0, fd // file descriptor
|
||||
ldr x1, =txt // address to print from
|
||||
ldr x2, =txt_s // load pointer to size
|
||||
ldr x2, [x2] // dereference the pointer
|
||||
mov w20, w2 // need this value for error check.
|
||||
bl write
|
||||
cmp x0, x20 // Did we write the expected amount?
|
||||
bne 90f
|
||||
// successful write - return 0
|
||||
mov x0, xzr
|
||||
b 99f
|
||||
90: // failure - ensure we return non-zero!
|
||||
mov x0, 1
|
||||
99: ldr x20, [sp], 16
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
|
||||
.data
|
||||
/* off_t lseek(int fd, off_t offset, int whence);
|
||||
*/
|
||||
seek_zero:
|
||||
stp x29, x30, [sp, -16]!
|
||||
mov w0, fd // file descriptor
|
||||
mov x1, xzr // beginning of file
|
||||
mov w2, wzr // SEEK_SET - absolute offset
|
||||
bl lseek
|
||||
ldp x29, x30, [sp], 16
|
||||
ret
|
||||
|
||||
.data
|
||||
prog: .asciz "file_ops"
|
||||
wf: .asciz "write failed"
|
||||
sf: .asciz "lseek failed"
|
||||
fname: .asciz "test.txt"
|
||||
txt: .asciz "some data\n"
|
||||
txt_s: .word txt_s - txt - 1 // strlen(txt)
|
||||
.end
|
||||
.end
|
||||
|
|
|
|||
Loading…
Reference in a new issue