ls.s 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. .text # Section for machine istructions to be executed
  2. .global _start # Needed by ld to find his default entry point
  3. _start: # _start symbol
  4. mov $257, %rax # sys_openat call
  5. mov $-100, %rdi # Set dir file descriptor. -100 is special for
  6. # AT_FDCWD (fd of current dir)
  7. mov $cwd, %rsi # Set filename
  8. xor %rdx, %rdx # Call kernel
  9. syscall # Set file status flag. 0 = O_RDONLY
  10. test %rax, %rax # Test return value. Negative is failure.
  11. # Anithing else is dir file descriptor
  12. js exit_error # If signed jump to error
  13. mov %rax, %rdi # Set dir file descriptor
  14. mov $217, %rax # sys_getdents64 call
  15. mov $buf, %rsi # Set pointer to buffer for storing dir entries
  16. mov $ 16777216, %rdx # Set buffer length
  17. syscall # Call kernel
  18. test %rax, %rax # Negative is error. Anything else is number of
  19. # bytes read
  20. js exit_error
  21. mov %rax, %r12 # Save number of bytes read
  22. mov %rsi, %r13 # Save buffer pointer
  23. dirent_loop: # Loop over directory entries
  24. lea 19(%r13), %r15 # Save pointer to filename
  25. mov %r15, %rdi # Set pointer to filename
  26. xor %rcx, %rcx # Set %rdx to zero
  27. xor %al, %al # Set %al to zero
  28. not %rcx # Set %rdx to max integer (not of 0)
  29. cld # Set direction flag to zero.
  30. # When direction flag is set to zero all string istructions
  31. # run ahead (from low to high adresses)
  32. repne scasb # repne = repeat argument operation %rcx times unless
  33. # confronted areas are equal, decrementing %rcx each time.
  34. # scasb = compare %al with byte at %rdi then set status flags.
  35. # In other words: search zero byte at the and of the string.
  36. not %rcx # Now %rcx is max int - filename_length - 1 (zero byte).
  37. # But max int = -1 so %rcx = -2 - filename_length and
  38. # Note that not number is abs(number) - 1,
  39. # so %rcx = filename_length + 2 -1 = filename_length + 1
  40. dec %rcx # Decrease %rcx so that now %rcx = filename_length
  41. mov $1, %rax # Print filename to stdout
  42. mov $1, %rdi
  43. mov %r15, %rsi
  44. mov %rcx, %rdx
  45. syscall
  46. mov $1, %rax # Print endline to stdout
  47. mov $endl, %rsi
  48. mov $1, %rdx
  49. syscall
  50. movw 16(%r13), %r14w # Save size of current entry in low word of %r14
  51. add %r14, %r13 # Add size to buffer pointer to shift to next entry
  52. sub %r14, %r12 # Subtract size from buffer size
  53. test %r12, %r12 # Test if left buffer size is zero
  54. jnz dirent_loop # Loop if nonzero
  55. exit: # Exit success
  56. mov $60, %rax
  57. xor %rdi, %rdi
  58. syscall
  59. exit_error: # Exit failure
  60. mov $60, %rax
  61. mov $1, %rdi
  62. syscall
  63. .section .rodata
  64. cwd: # Variable for current dir (.)
  65. .asciz "."
  66. endl: # Variable for endline
  67. .byte '\n'
  68. .section .bss
  69. buf: # Dir entries buffer.
  70. # Attention! This sets a limit to entries
  71. # read from dir.
  72. .skip 16777216 # 16 MiB