Playing around with arm assembly
  • Assembly 95.4%
  • Nix 4.6%
Find a file
2026-03-21 23:26:59 +01:00
.gitignore Init 2026-03-19 02:02:25 +01:00
cat.s Buffers u 2026-03-20 11:14:20 +01:00
fibonacci.s Start from 0 2026-03-21 23:26:59 +01:00
hello.s Init 2026-03-19 02:02:25 +01:00
README.md Start from 0 2026-03-21 23:26:59 +01:00
shell.nix Init 2026-03-19 02:02:25 +01:00

aarch64-hello

I'm programming a bunch of fun stuff in arm64 assembly without libc for funsies, currently included:

  • A btoa printn function for an arbitrary base between 2-64
  • A decently optimised and extremely satisfying Fibonacci sequence
  • A partial reimplementation of GNU cat
    • Printing multiple files passed in as arguments
    • Printing from a pipe when no arguments are provided
    • coreutils-compatible error handling
    • Tested against coreutils
    • Not doing anything egregious...
    • ...but not as optimised as I'd like

...I think I might know how to computer a bit haha

Example

$ as -o target/cat.o cat.s
$ ld -o target/cat target/cat.o
$ target/cat target/example cat.s
Printing my own cat's source with my own cat
Gosh I'm flexing so much today

.global _start

_start:
  # Init return code
  mov  x19, #0

  # Get filenames
  ldr  x20, [sp]         // argc
  add  x21, sp, #16      // argv 8:name 16+:args

  # For each arg (filename) run cat
  for_arg:
    cmp  x20, #2
    blo  for_arg_end

    ldr  x0, [x21]
    bl   cat

    sub  x20, x20, #1
    add  x21, x21, #8
    b    for_arg
  for_arg_end:

exit:
  mov  x0, x19
  mov  w8, #93
  svc  0

.type handle_error, @function
handle_error:
  mov  x19, x0

  mov  x0, #2
  ldr  x1, =err_fallback
  mov  x2, #14
  mov  x8, #64
  svc  0
ret

# x0 address of path string
.type cat, @function
cat:
  # Get fd
  mov  x1, x0            // path
  mov  x0, #-100         // -100: Current directory
  mov  x2, #0            // read-only flag
  mov  x3, #0
  mov  x8, #56           // openat
  svc  0

  cmp  x0, #0            // handle openat error
  blt  handle_error

  mov  x22, x0           // save fd

  # Read and write
  loop:
    mov  x0, x22         // fd
    ldr  x1, =buffer
    mov  x2, #64          // n bytes
    mov  x8, #63         // read
    svc  0

    cmp  x0, #0          // exit loop on eof
    beq  loop_exit
    cmp  x0, #0          // handle read error
    blt  handle_error

    mov  x2, x0          // n bytes = n read bytes
    mov  x0, #1          // stdout
    ldr  x1, =buffer
    mov  x8, #64         // write
    svc  0

    cmp  x0, #0          // handle read error
    blt  handle_error

    b    loop
  loop_exit:

ret

.data
err_fallback:  .ascii  "cat: IO Error\n"
buffer:        .byte   64