ich hab neulich ein wenig experimentiert, und zwar mit dem Versuch, größere Zahlen zu "behandeln", als sie eigentlich in die Variablen passen. Das Ganze mit dem NASM, unter Linux (Debian) 64 bit. Dazu bietet sich am einfachsten die Fibonacci-Serie an.
Ich hab auch überlegt, ob ich das dann in euren Fibonacci-Benchmark-Thread stelle, aber ich war mir nicht sicher, ob das wirklich vergleichbar ist. Daher hier einzeln, "zur Inspiration".
Ich habe drei Arrays mit einzelnen Bytes gemacht, mit jeweils 10.000 Stellen. Dh. so viele Stellen kann die Zahl eigentlich haben.
Der unten aufgeführte Quellcode berechnet die ersten 5000 Fibonacci-Zahlen, und gibt davon (wenn ich mich noch recht erinnere) die letzten 10 aus. Beides ist natürlich im Sourcecode änderbar. Assemblier- und Linkanweisung im Code.
Code: Alles auswählen
; fiborgr.asm
;
; errechnet RICHTIG GROSSE Fibonacci's und gibt jene aus.
; nasm -f elf64 fiborgr.asm
; ld -s -o fiborgr fiborgr.o "warum -s ? -s "strippt" die Debug-Infos weg. Wenn man debuggen will, lieber ohne -s"
[bits 64]
SECTION .data
_overflow_msg db '*** Series overflown.',0ah
len_overflow_msg equ $-_overflow_msg
_one db '1 '
_endl db 10
_leerz db 0
ziffer db 0
SECTION .bss
f1array : resb 10000 ; drei arrays, aus einzelnen Bytes (Ziffern).
f2array : resb 10000
f3array : resb 10000
global _start ; global entry point export for ld
SECTION .text
_start:
start:
mov rax, 0
.nochmal1:
mov byte [f1array+rax],0 ; alles Array-Elemente zu Null machen.
mov byte [f2array+rax],0
mov byte [f3array+rax],0
inc rax
cmp rax, 10001
jne .nochmal1
mov byte [f1array],1
mov byte [f2array],1
mov r15, 5000 ; HARDCODED : 5000 fib-Zahlen machen.
; soviele fib() sollen errechnet werden...
cmp eax, 0
jz .done
dec r15
jz .done ; wenn fertig, ganz runter, Ende
call .ausgabe_f2
call .crlf
.calc_fibo:
call .kill_f3
mov r14, 0 ; r14 ist Index, wo im Array wir sind.
mov cl, 0
.alle_ziffern:
mov rax, 0
mov rbx, 0
mov r13, 0
mov al, byte [f1array+r14]
add [f3array+r14], al
mov bl, byte [f2array+r14]
add [f3array+r14], bl
mov bl, byte [f3array+r14]
jo .overflow ; Ergebnis zu groß für Datentyp?
nop
nop
inc r14
cmp r14, 10000
jne .alle_ziffern
; ***** hier fertig mit rechnen *******
call .adjust_f3
call .shift_arrays
cmp r15, 10 ; erst ausgeben, wenn es die letzten 10 fibs sind.
jg .keine_ausgabe ; ansonsten Ausgabe ueberspringen.
call .ausgabe_f3 ; hier Ausgabe als Text
call .crlf
call .crlf
.keine_ausgabe:
.done:
; call .crlf
dec r15
jnz .calc_fibo ; alle Fibos berechnet ?
mov eax, 1 ; Programmende
mov ebx, 0
int 80h
.overflow:
mov eax, 4
mov ebx, 1
mov ecx, _overflow_msg
mov edx, len_overflow_msg
int 80h
mov eax, 1
mov ebx, 1
int 80h
; *******************************************************************
; *********************** ab hier proceduren ************************
; *******************************************************************
.shift_arrays:
push rax
push rbx
push rcx
push rdx
mov rax, 0
.nochmal3:
mov ch, byte [f2array+rax]
mov byte [f1array+rax], ch
mov ch, byte [f3array+rax]
mov byte [f2array+rax], ch
inc rax
cmp rax, 10000
jne .nochmal3
pop rdx
pop rcx
pop rbx
pop rax
ret
.crlf:
push rax
push rbx
push rcx
push rdx
mov eax, 4 ; schreiben
mov ebx, 1
mov ecx, _endl
mov edx, 1
int 80h
pop rdx
pop rcx
pop rbx
pop rax
ret
.ausgabe_f2:
push rax
push rbx
push rcx
push rdx
mov r12, 10000 ; Zur Ausgabe des Arrays r12 als Index
.noch_ein_array_teil2:
dec r12
mov rcx, 0
mov cl, byte [f2array+r12]
add ecx, "0"
mov byte[ziffer], cl
mov eax, 4 ; fertige "Zahl" ausgeben
mov ebx, 1
mov edx, 1 ; Länge, hier bei uns immer 1
mov ecx, ziffer
int 80h
cmp r12, 0
jne .noch_ein_array_teil2
pop rdx
pop rcx
pop rbx
pop rax
ret
.ausgabe_f3:
push rax
push rbx
push rcx
push rdx
mov r13, 0 ; solange führende Nullen, später dann 1
mov r12, 10000 ; Zur Ausgabe des Arrays r12 als Index
.noch_ein_array_teil3:
dec r12
mov rcx, 0
mov cl, byte [f3array+r12]
cmp r13, 0
jne .write_it ; wenn schon richtige Ziffern waren, dann hüpfen
cmp cl, 0
jne .write_it_vor ; wenn ab jetzt richtige Zahlen kommen, dann hüpfen
push ax
mov al, [_leerz]
mov byte[ziffer], al
pop ax ; führende Null soll Leerzeichen werden
jmp .ausgabe_leerz
.write_it_vor:
mov r13,1
.write_it:
add cl, "0"
mov byte[ziffer], cl
.ausgabe_leerz:
mov eax, 4 ; fertige "Zahl" ausgeben
mov ebx, 1
mov edx, 1 ; Länge, hier bei uns immer 1
mov ecx, ziffer
int 80h
cmp r12, 0
jne .noch_ein_array_teil3
pop rdx
pop rcx
pop rbx
pop rax
ret
.kill_f3:
push rax
mov rax, 0
.nochmal2:
mov byte [f3array+rax],0
inc rax
cmp rax, 10000
jne .nochmal2
pop rax
ret
.adjust_f3:
push rax
push rbx ; Indexzähler
push rcx ; einzelner Wert
push rdx
mov rcx, 0
.nochmal4:
mov bx, 0
mov bl, byte [f3array+rcx]
cmp bl, 10 ; größer als 9 ?
jl .good
xor ax, ax
mov ax, bx
add byte [f3array+rcx+1], 1
xor rdx, rdx
mov bx, 10
div bx
; Zehner in eax, Einer in rdx
mov byte [f3array+rcx], dl
.good:
inc rcx
cmp rcx, 9999
jne .nochmal4
pop rdx
pop rcx
pop rbx
pop rax
ret