175 lines
2.6 KiB
ArmAsm
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
|