125 lines
2.0 KiB
NASM
125 lines
2.0 KiB
NASM
global _start
|
|
|
|
section .bss
|
|
NR_INPUT_BUFFER: resb 4
|
|
NR_INPUT_BUFFER_SIZE: equ 4
|
|
|
|
section .data
|
|
RQ_NR_STR: db 'Please give me a number (0-999): '
|
|
RQ_NR_STR_SIZE: equ $ - RQ_NR_STR
|
|
|
|
NR_STR: db '8'
|
|
NR_STR_SIZE: equ 1
|
|
|
|
ZERO_ASCII_VALUE: equ 48
|
|
NINE_ASCII_VALUE: equ 57
|
|
INPUT_BASE: equ 10
|
|
|
|
STDOUT: equ 1
|
|
|
|
section .text
|
|
_start:
|
|
; Write to STDOUT
|
|
mov rax, 1 ; = write
|
|
mov rdi, STDOUT
|
|
mov rsi, RQ_NR_STR
|
|
mov rdx, RQ_NR_STR_SIZE
|
|
syscall
|
|
|
|
; Read from STDIN
|
|
xor rax, rax ; 0 = read
|
|
xor rdi, rdi ; 0 = stdin
|
|
mov rsi, NR_INPUT_BUFFER
|
|
mov rdx, NR_INPUT_BUFFER_SIZE
|
|
syscall
|
|
|
|
; Parse number
|
|
mov rdi, NR_INPUT_BUFFER ; array to loop
|
|
dec rax
|
|
mov rsi, rax ; loop limit
|
|
call parseNR
|
|
|
|
mov rdi, rax
|
|
call collatz
|
|
|
|
mov rdi, rax
|
|
exit:
|
|
mov rax, 60
|
|
syscall
|
|
|
|
; int ParseNumber(char * p, size_t length)
|
|
; IN
|
|
; - rdi = ptr to byte array
|
|
; - rsi = length of said array (greater than 0)
|
|
; OUT
|
|
; - rax = resulting number => returns 0 if it cannot parse
|
|
parseNR:
|
|
xor r8, r8 ; loop variable
|
|
xor rcx, rcx ; sum
|
|
.loop_body:
|
|
mov rax, rcx
|
|
mov rcx, qword INPUT_BASE
|
|
mul rcx
|
|
mov rcx, rax
|
|
|
|
movzx rax, byte [rdi + r8]
|
|
; Check if the value is within ASCII numeric bounds
|
|
cmp al, byte ZERO_ASCII_VALUE
|
|
jb .exit_failure
|
|
cmp al, byte NINE_ASCII_VALUE
|
|
jnb .exit_failure
|
|
|
|
; Subtract zero to make it a number
|
|
sub al, byte ZERO_ASCII_VALUE
|
|
|
|
; Store the sum
|
|
add rcx, rax
|
|
|
|
inc r8
|
|
|
|
cmp r8, rsi
|
|
jb .loop_body
|
|
|
|
; Return the result
|
|
mov rax, rcx
|
|
jmp .exit
|
|
|
|
.exit_failure:
|
|
xor rax, rax
|
|
.exit:
|
|
ret
|
|
|
|
; int Collatz(int n)
|
|
; IN
|
|
; - rdi = number to "collatz"
|
|
; OUT
|
|
; - rax = number of "collatz" iterations it took to reach 0
|
|
collatz:
|
|
xor r9, r9 ; iteration count
|
|
|
|
.loop_start:
|
|
cmp rdi, qword 1
|
|
jbe .loop_exit
|
|
|
|
inc r9
|
|
|
|
; Is rdi odd?
|
|
mov rax, rdi
|
|
and rax, qword 1
|
|
cmp rax, qword 1
|
|
je .uneven_routine
|
|
|
|
;.even_routine:
|
|
shr rdi, 1 ; divide by two using right shift 1
|
|
jmp .loop_start
|
|
|
|
.uneven_routine:
|
|
mov rax, rdi
|
|
add rdi, rdi ; rdi + rdi
|
|
add rdi, rax ; rdi + rdi + rdi = 3 * rdi
|
|
inc rdi
|
|
jmp .loop_start
|
|
|
|
.loop_exit:
|
|
mov rax, r9
|
|
ret |