Added collatz homework assignment
This commit is contained in:
125
x86_64/4_collatz.asm
Normal file
125
x86_64/4_collatz.asm
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
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
|
||||||
Reference in New Issue
Block a user