Compare commits
2 Commits
0a1d4fbb2e
...
ceb0a94887
| Author | SHA1 | Date | |
|---|---|---|---|
| ceb0a94887 | |||
| 15e539be18 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
-test
|
||||
test
|
||||
main
|
||||
*.o
|
||||
100
collatz.S
100
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
|
||||
|
||||
|
||||
18
main.c
18
main.c
@ -1,11 +1,21 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user