Mark homework file appropiately in its name
This commit is contained in:
125
x86_64/4_homework_collatz.asm
Normal file
125
x86_64/4_homework_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