|
1 |
| -section .data |
2 |
| - msg db "%d", 10, 0 ;return string for printf (just the result) |
3 |
| - |
4 |
| -section .text |
5 |
| - extern printf |
6 |
| - global main |
7 |
| - |
8 |
| -main: |
9 |
| - xor ebx, ebx ;r in Dickson's method |
10 |
| - xor r10d, r10d ;cuboids |
11 |
| - |
12 |
| -next: |
13 |
| - add ebx, 2 ;the next even r (odd values not allowed) |
14 |
| - mov eax, ebx ;put number in eax for multiplication |
15 |
| - mul ebx ;square |
16 |
| - shr eax, 1 ;half |
17 |
| - mov ecx, eax ;put r^2 / 2 in ecx |
18 |
| - xor edi, edi ;for divisors of r^2 / 2 |
19 |
| - |
20 |
| -triplets: |
21 |
| - inc edi ;next divisor candidate |
22 |
| - mov eax, edi ;candidate in eax |
23 |
| - mul edi ;square |
24 |
| - cmp eax, ecx ;check if square of candidate is less than r^2 / 2 |
25 |
| - jg next ;if not, go to next higher r |
26 |
| - xor edx, edx ;prepare remainder |
27 |
| - mov eax, ecx ;r^2 / 2 in eax for division |
28 |
| - div edi ;divide by current divisor |
29 |
| - test edx, edx ;check if remainder is zero |
30 |
| - jnz triplets ;if not, continue with next divisor |
31 |
| - inc r10d |
32 |
| - cmp r10d, 1975 |
33 |
| - jl triplets |
34 |
| - |
35 |
| -print: ;printing routine, differs slightly from OS to OS |
36 |
| - push rbp |
37 |
| - mov edi, msg |
| 1 | +format ELF64 executable 9 |
| 2 | + |
| 3 | +segment readable writable |
| 4 | + result: times 10 db 0 ;empty string for printing the result later |
| 5 | + db 10, 0 |
| 6 | + |
| 7 | +segment readable executable |
| 8 | + entry start |
| 9 | + |
| 10 | +start: |
| 11 | + mov eax, 1 ;length |
| 12 | + xor ecx, ecx ;counter |
| 13 | + |
| 14 | +next_l: |
| 15 | + cmp ecx, 1000000 ;count > 1e6? |
| 16 | + jg finished ;if yes, we are finished |
| 17 | + inc eax ;next length |
| 18 | + mov edx, eax ;in edx |
| 19 | + shl edx, 1 ;2 * l as limit of next loop |
| 20 | + mov ebx, 3 ;init width + height |
| 21 | + |
| 22 | +next_wh: |
| 23 | + mov edi, eax |
| 24 | + imul edi, eax ;l^2 |
38 | 25 | mov esi, ebx
|
39 |
| - call printf |
40 |
| - pop rbp |
| 26 | + imul esi, ebx ;(w + h)^2 |
| 27 | + add edi, esi ;l^2 + (w + h)^2 |
| 28 | + test edi, 1 ;is result even (last bit 0)? |
| 29 | + jz even ;if yes, jump directly to even |
| 30 | + |
| 31 | +mod_8: |
| 32 | + mov esi, edi ;any odd perfect square must be 1 (mod 8) |
| 33 | + and esi, 7 |
| 34 | + cmp esi, 1 |
| 35 | + jne skip_count |
| 36 | + jmp even |
| 37 | + |
| 38 | +even: |
| 39 | + mov esi, edi ;while n is a power of 4, shift right 2 bits |
| 40 | + and esi, 3 |
| 41 | + test esi, esi |
| 42 | + jnz and_7 |
| 43 | + shr edi, 2 |
| 44 | + jmp even |
| 45 | + |
| 46 | +and_7: ;if result & 7 != 1, n is not a perfect square |
| 47 | + mov esi, edi |
| 48 | + and esi, 7 |
| 49 | + cmp esi, 1 |
| 50 | + jne skip_count |
| 51 | + |
| 52 | + mov esi, 1 ;prepare for squaretest |
| 53 | + mov r8d, 1 |
41 | 54 |
|
42 |
| -exit: ;exit routine, dito |
| 55 | +squaretest: |
| 56 | + add r8d, 2 |
| 57 | + add esi, r8d |
| 58 | + cmp esi, edi |
| 59 | + jl squaretest |
| 60 | + jg skip_count |
| 61 | + |
| 62 | +is_square: |
| 63 | + cmp ebx, eax ;is w + h <= l? |
| 64 | + jle not_greater ;if yes, jump to not_greater |
| 65 | + mov edi, ebx ;else calclulate (l - ((w + h + 1) / 2)) + 1 |
| 66 | + mov esi, eax |
| 67 | + inc edi |
| 68 | + shr edi, 1 |
| 69 | + sub esi, edi |
| 70 | + inc esi |
| 71 | + add ecx, esi ;add result to count and continue |
| 72 | + jmp skip_count |
| 73 | + |
| 74 | +not_greater: |
| 75 | + mov edi, ebx ;calculate (w + h) / 2 |
| 76 | + shr edi, 1 |
| 77 | + add ecx, edi ;and add to count |
| 78 | + |
| 79 | +skip_count: |
| 80 | + inc ebx ;next width + height |
| 81 | + cmp ebx, edx ;<= 2 * l? |
| 82 | + jle next_wh ;if yes, repeat |
| 83 | + jmp next_l ;else take next l |
| 84 | + |
| 85 | +finished: |
| 86 | + mov ebx, 10 |
| 87 | + mov ecx, 9 |
| 88 | + |
| 89 | +convert_result: |
| 90 | + xor edx, edx |
| 91 | + div ebx |
| 92 | + add edx, '0' |
| 93 | + mov [result + ecx], dl |
| 94 | + dec ecx |
| 95 | + test eax, eax |
| 96 | + jnz convert_result |
| 97 | + |
| 98 | +print: |
| 99 | + mov eax, 4 |
| 100 | + mov edi, 1 |
| 101 | + mov esi, result |
| 102 | + mov edx, 12 |
| 103 | + syscall |
| 104 | + |
| 105 | +exit: |
43 | 106 | mov eax, 1
|
44 | 107 | xor edi, edi
|
45 | 108 | syscall
|
46 |
| - |
47 |
| -section .note.GNU-stack ;just for gcc |
|
0 commit comments