# bedir t karaabalı # 2025 # collatz problem .text # void collatz_len_and_peak(uint64_t x, uint64_t *steps, uint64_t *peak) .global collatz_len_and_peak .global scan_upto # bu makrolar yukardaki belirlediğim stack'e çok bağlı yani %rbp relative # bu demek oluyor ki stack değişirse bu makrolar da değişmek zorunda # daha esnek bir tasarım offset eklemek olurdu .macro save_registers base movq %rax, -96(%\base) movq %rcx, -88(%\base) movq %rdx, -80(%\base) movq %rsi, -72(%\base) movq %rdi, -64(%\base) movq %r8, -56(%\base) movq %r9, -48(%\base) movq %r10, -40(%\base) movq %r11, -32(%\base) .endm .macro restore_registers base movq -96(%\base), %rax movq -88(%\base), %rcx movq -80(%\base), %rdx movq -72(%\base), %rsi movq -64(%\base), %rdi movq -56(%\base), %r8 movq -48(%\base), %r9 movq -40(%\base), %r10 movq -32(%\base), %r11 .endm collatz_len_and_peak: # Collatz problem implementation # x -> rdi, steps -> rsi, peak -> rdx movq $0, (%rsi) # *steps=0 movq %rdi, (%rdx) # *peak = x movq %rdi, %r8 # r8(n) (caller-saved) = x .loop: cmpq $1, %r8 # while (n != 1) je .done testq $1, %r8 # 1 and n jz .even # odd case leaq 1(%r8, %r8, 2), %r8 # n *= 3 -> lea ( base + index * scale ) jmp .next_step .even: shrq $1, %r8 # n /= 2 .next_step: cmpq (%rdx), %r8 # if (n > *peak) n - *peak jle .next movq %r8, (%rdx) # *peak = n .next: addq $1, (%rsi) # (*steps)++ jmp .loop .done: ret # void scan_upto(uint64_t N, uint64_t *best_n, uint64_t *best_steps, uint64_t *best_peak, uint64_t *xor_steps) scan_upto: pushq %rbp movq %rsp, %rbp subq $104, %rsp # burda stack de local değişkenler tutulcak makro için 80 byte + 16 byte local değişkenler ama # hizalamak da gerekiyor # başlatma initialize # rdi rsi rdx rcx r8 movq $1, (%rsi) # *best_n = 1 movq $0, (%rdx) # *best_steps = 0 movq $1, (%rcx) # *best_peak = 1 movq $0, (%r8) # *xor_steps = 0 movq $1, %r9 # n = 1 .loop_scan: cmpq %rdi, %r9 # if (n <= N) jg .done_scan # local değişkenler movq $0, -8(%rbp) # steps = 0 movq $0, -16(%rbp) # peak = 0 # şimdi fonksiyon çağırcam ama register sırasını korumam lazım bunlar # caller-saved olduğu için diper fonksiyonda korunmazlar ve değişiler bu yüzden # hali hazırda kullandığım registerları stack e vermem lazım # ama bunu makro olarak yazmak istiyorum bir daha kullanmıycak olsamda save_registers rbp movq %r9, %rdi # n leaq -8(%rbp), %rsi # steps leaq -16(%rbp), %rdx # peak call collatz_len_and_peak restore_registers rbp movq (%r8), %r11 # r11 = *xor_steps xorq -8(%rbp), %r11 # *xor_steps ^= steps movq %r11, (%r8) # *xor_steps = r11 movq (%rdx), %r11 # r11 = *best_steps movq -8(%rbp), %r10 # r10 = steps cmpq %r11, %r10 # if (steps > *best_steps) jle .incr movq %r9,(%rsi) # *best_n = n movq %r10, (%rdx) # *best_steps = r10 movq -16(%rbp), %r11 # r11 = peak movq %r11, (%rcx) # *best_peak = r11 .incr: incq %r9 jmp .loop_scan .done_scan: leave ret