diff --git a/collatz.S b/collatz.S index 6f3f76d..62f8d54 100644 --- a/collatz.S +++ b/collatz.S @@ -3,9 +3,42 @@ # collatz problem .text -# void collatz_len_and_peek(uint64_t x, uint64_t *steps, uint64_t *peek) -.global collatz_len_and_peek -collatz_len_and_peek: +# 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 @@ -19,17 +52,70 @@ collatz_len_and_peek: testq $1, %r8 # 1 and n jz .even # odd case - leaq (%r8, %r8, 2), %r8 # n *= 3 -> lea base + index * scale - addq $1,%r8 # n += 1 + 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 > *peek) n - *peek + cmpq (%rdx), %r8 # if (n > *peak) n - *peak jle .next - movq %r8, (%rdx) # *peek = n + 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 + diff --git a/main.c b/main.c index e2ecc2d..91d4e9c 100644 --- a/main.c +++ b/main.c @@ -1,11 +1,21 @@ #include #include -void collatz_len_and_peek(uint64_t x, uint64_t *steps, uint64_t *peek); +void collatz_len_and_peak(uint64_t x, uint64_t *steps, uint64_t *peak); +void scan_upto(uint64_t N, uint64_t *best_n, uint64_t *best_steps, uint64_t *best_peak, uint64_t *xor_steps); + int main() { - uint64_t steps, peak; - collatz_len_and_peek(13, &steps, &peak); - printf("steps=%lu, peak=%lu\n", steps, peak); + printf("hello world!\n"); + + uint64_t N = 1000000; + uint64_t best_n, best_steps, best_peak, xor_steps; + scan_upto(N, &best_n, &best_steps, &best_peak, &xor_steps); + printf("collatz_longest(1..%lu)\n", N); + printf("n*=%lu\n", best_n); + printf("steps=%lu\n", best_steps); + printf("peak=%lu\n", best_peak); + printf("xor_steps=%lu\n", xor_steps); + return 0; } \ No newline at end of file