# ;; ls.s # # # #include .file "ls.s" .data dirname: .string "/usr/lib" open_flags: .quad 00200000 # .quad O_DIRECTORY | O_RDONLY eoln: .string "\n" separator: .string " " .align 4 direntries: .space 4096,0 .text .global ls ls: # walk through arglist, see if you can open files... nop pop %r13 # %r8 keeps the argc pop %rsi # remove command dec %r8 jz _finish _nextarg: pop %rdi # load directory name into %rdi mov open_flags,%rsi mov $__NR_open,%rax syscall cmp $0,%rax jl _next # save the file descriptor in %r15 mov %rax,%r15 lea direntries,%r14 # clear %r8 - %r9 xor %r8,%r8 # going to use this to walk direntries xor %r9,%r9 # going to calculate offset to next dirent xor %r10,%r10 # going to use save how many bytes did we receive from getdents _read_entries: mov %r15,%rdi # recover file descriptor from %r15 mov %r14,%rsi # point %rsi at direntries mov $4096,%rdx mov $__NR_getdents,%rax syscall cmp $0,%rax jle _finish mov %rax,%r10 call _process_entries # close the file descriptor... mov %r15,%rdi mov $__NR_close,%rax syscall _next: dec %r13 jnz _nextarg _finish: mov $0,%rdi # and exit with a zero status mov $__NR_exit,%rax # syscall = 60 is exit syscall # # process_entries # # # we have been handed a block of entries in 'direntries' # # step through each one, and call appropriate handler for # each individual one... # _process_entries: lea direntries,%r8 # %r8 has the current dirent _around: call _entry_raw # is there a next? mov 16(%r8),%r9w # okay, %r9w has distance to next add %r9,%r8 mov %r8,%r12 # check to see if we have processed all bytes... sub %r14,%r12 # %r14 should have value of direntries cmp %r10,%r12 jl _around ret # # entry_raw # # this is the most basic handler --> all that it does is send an # entry out to stdout # _entry_raw: mov $1,%rdi lea 18(%r8),%rsi call writestr mov $1,%rdi lea eoln,%rsi call writestr ret