amd64-postfix/postfix.s
2024-11-08 18:00:34 +00:00

175 lines
2.6 KiB
ArmAsm

### Copyright (c) Camden Dixie O'Brien
### SPDX-License-Identifier: AGPL-3.0-or-later
.text
.global _start
_start:
mov $buf, %rsi
readloop:
## Read character in.
mov $0, %rax
mov $0, %rdi
mov $1, %rdx
syscall
## Check return value; exit if not equal to one.
cmp $1, %rax
jne exit
## Move read character into RAX and increment buffer position.
movzx (%rsi), %rax
inc %rsi
## Loop if read character wasn't a line feed.
cmp $0x0a, %rax
jne readloop
## Start reading words at start of buffer with zero length
mov $buf, %rsi
mov $0, %rdx
wordloop:
## Copy character into R8
movzx (%rsi, %rdx), %r8
## Print the word if the character is a space or a newline
cmp $0x20, %r8
je doword
cmp $0x0a, %r8
je doword
## Increment word length and loop
inc %rdx
jmp wordloop
doword:
## Skip operator checks if word length is greater than 1
cmp $1,%rdx
jg donum
## Check for operators and jump to appropriate procedure
movzx (%rsi),%rax
cmp $0x2b,%rax
je doplus
cmp $0x2d,%rax
je dominus
cmp $0x2a,%rax
je domultiply
cmp $0x2f,%rax
je dodivide
donum:
mov $0, %rax
mov $0, %rcx
numloop:
## Multiply current value by ten
imul $10, %rax
## Add numeric value of digit
movzx (%rsi, %rcx), %rbx
sub $0x30, %rbx
add %rbx, %rax
## Increment index and loop if not at end of word
inc %rcx
cmp %rcx, %rdx
jg numloop
push %rax
jmp endword
doplus:
pop %rbx
pop %rax
add %rbx,%rax
push %rax
jmp endword
dominus:
pop %rbx
pop %rax
sub %rbx,%rax
push %rax
jmp endword
domultiply:
pop %rbx
pop %rax
imul %rbx,%rax
push %rax
jmp endword
dodivide:
pop %rbx
pop %rax
mov $0,%rdx
idiv %rbx
push %rax
## Restore RDX
mov $1,%rdx
endword:
## Handle end of line
cmp $0x0a, %r8
je endline
## Add the word length to RSI and increment until non-space is
## found
add %rdx, %rsi
spaceloop:
inc %rsi
mov (%rsi), %rax
cmp $0x20, %rax
je spaceloop
## Zero the word length then return to the word loop.
mov $0, %rdx
jmp wordloop
endline:
mov $buf,%rsi
add $100,%rsi
mov $1,%rcx
## Add line feed at end of buffer
movb $0x0a,(%rsi)
## Set base and pop value
mov $10,%r8
pop %rax
formatloop:
dec %rsi
inc %rcx
## Divide RAX by ten to get unformatted value (RAX) and current
## digit value (RDX)
mov $0,%rdx
idiv %r8
## Write character for digit into buffer
add $0x30,%rdx
movb %dl,(%rsi)
## Loop if the unformatted value is non-zero
cmp $0,%rax
jne formatloop
## Print value
mov $1,%rax
mov $1,%rdi
mov %rcx,%rdx
syscall
## Return to top
jmp _start
exit:
## Exit with code 0
mov $60, %rax
mov $0, %rdi
syscall
.bss
buf:
.skip 100