Sortowanie przez scalanie/kod: Różnice pomiędzy wersjami

[wersja przejrzana][wersja przejrzana]
Usunięta treść Dodana treść
DrJolo (dyskusja | edycje)
→‎Asembler x86: kilka słów komentarza
DrJolo (dyskusja | edycje)
→‎Asembler x86: rozmiar tablicy nie musi być już potęgą liczby 2
Linia 8:
== Asembler x86 ==
Poniższy kod jest prostą iteracyjną implementacją algorytmu sortowania przez scalanie. Sortowane są w kolejności rosnącej elementy tablicy znaków zgodnie z ich kodem ASCII.
 
<source lang="asm">
section .data
; ciąg znaków do posortowania
msg1 db '9876543210yzxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBzzA'
msg1 db '9876543210ZYXQVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba543210'
msg2 db ' '
; tablica pustych znaków
src dd 0
msg2 db ' '
dst dd 0
src dd 0 ; wskaźnik do aktualnej źródłowej tablicy
cnt dd 64
dst dd 0 ; wskaźnik do aktualnej tablicy wynikowej
cnt dd 68 ; rozmiar tablicy wpisany na stałe, znajdujący się także
; wpisany na stałe w linii 115 tego kodu źródłowego
 
bufor dd 0 ; offsetofset kolejnego znaku tablicy dst
skok dd 2 ; skok do początku następnej pary podciągów
offsetofset dd 0 ;
indeks dd 0 ;
 
esiend dd 0 ; graniczne indeksy scalanych podciągów
esiend dd 0
ediend dd 0 ;
srcend dd 0 ;
 
endl db 0x0a ; znak końca linii
 
section .text
Linia 30 ⟶ 35:
 
_start:
mov [src],dword msg1 ; początkowy wskaźnik do tablicy źródłowej
 
mov [srcdst],dword msg1msg2 ; i docelowej
mov [dst],dword msg2
 
petla2:
mov [bufor],dword 0 ; reset wartości indeksowych na początku
 
mov [buforofset],dword 0 ; każdego obiegu pętli głównej
mov [offset],dword 0
mov [indeks],dword 0
 
mov edx,[src] ; ustawienie granicznych indeksów podciągu drugiego
add edx,[cnt] ; na koniec tablicy źródłowej
dec edx ; podciągów
mov [srcend],edx ;
petla1:
mov ecx,[skok] ; ecx zawiera liczbę znaków w obu podciągach do
Linia 47 ⟶ 55:
; instrukcji
mov esi,[src] ; esi ustawione na początek podciągu pierwszego
add esi,[offsetofset]
mov edi,esi ;
Linia 60 ⟶ 68:
mov edx,esi ; ustawienie granicznych indeksów podciągu pierwszego
add edx,ecx ; na koniec podciągu pierwszego
mov [esiend],edx ;
 
mov edx,edi ; ustawienie granicznych indeksów podciągu drugiego
add edx,ecx ; na koniec podciągu drugiego zwiększając wartość o CF
mov [ediend],edx ;
 
inc ecx ; przywrócenie pierwotnej wartości ecxECX, który
shl ecx,1 ; będzie wykorzystywany w petli 'loop porownaj'
 
mov edx,[dst] ; wyznaczenie pierwszego indeksu ciągu wynikowego
add edx,[offsetofset] ;
mov [bufor],edx ; kolejny indeks przechowywany jest w zmiennej bufor
 
add [offsetofset],ecx ; zwiększenie offsetofsetu o wartość skoku na potrzeby kolejnego obiegu pętli
; obiegu pętli
 
porownaj:
mov edx,[bufor]
 
cmp esi,[srcend] ; jeżeli pierwszy podciąg doszedł do końca tablicy źródłowej
jg koniec ; rozpoczyna sie nowy obieg petli
cmp edi,[ediendsrcend] ; jeżeli doszliśmydrugi podciąg doszedł do końca drugiegotablicy podciąguźródłowej
jg pierwszy ; do tablicy wynikowej wpisywane są pozostałe
; elementy z drugiegopierwszego podciągu
 
cmp esi,[esiend] ; jeżeli doszliśmy do końca pierwszego podciągu
jg drugi ; do tablicy wynikowej wpisywane są pozostałe
; elementy z drugiego podciągu
 
cmp edi,[ediend] ; jeżeli doszliśmy do końca drugiego podciągu
jg pierwszy ; do tablicy wynikowej wpisywane są pozostałe
; elementy z pierwszego podciągu
 
jl pierwszy cmp al,bl ; porównuje kolejne elementy ze scalanych podciągów
cmp esi,[esiend] ; jeżeli doszliśmy do końca pierwszego podciągu
jg drugijl pierwszy ; kopiuje mniejszy z ; nich do tablicy wynikowej wpisywane są pozostałe
; elementy z drugiego podciągu
cmp edi,[ediend] ; jeżeli doszliśmy do końca drugiego podciągu
jg pierwszy ; do tablicy wynikowej wpisywane są pozostałe
; elementy z drugiego podciągu
cmp al,bl ;
jl pierwszy ; porównuje kolejne elementy ze scalanych podciągów
 
drugi:
mov [edx],bl ; jeżeli ebxBL<=eaxAL, wstawiamy ebxBL do ciągu wynikowego
inc edi ; przechodzimy do następnego znaku podciągu drugiego
mov bl,[edi] ; i ładujemy do rejestru ebxBL
jmp koniec
 
pierwszy:
mov [edx],al ; jeżeli eaxAL<ebxBL, wstawiamy eaxAL do ciągu wynikowego
 
inc esi ; przechodzimy do następnego znaku podciągu pierwszego
mov [edx],al ; jeżeli eax<ebx, wstawiamy eax do ciągu wynikowego
mov al,[esi] ; i ładujemy go do rejestru eaxAL
inc esi ; przechodzimy do następnego znaku podciągu pierwszego
mov al,[esi] ; i ładujemy go do rejestru eax
 
koniec:
inc edx
mov [bufor],edx
inc dword [indeks];
loop porownaj ; skok do kolejnego porównania
 
cmp [indeks], dword 6468 ; dopóki nie przeszliśmy końcowego elementu ciągu
jl petla1 ; wynikowego, to porównujemy elementy kolejnych par podciągów
; podciągów
 
; wyświetla pośrednie tablice wynikowe
mov eax, 4 ; eax=4, write() syscall
mov ebx, 1 ; ebx=1, stdout
mov ecx, [dst] ; adres tekstu do ecx
mov edx, [cnt] ; długość tekstu do edx
int 0x80 ; wywołanie funkcji systemowej
 
mov eax, 4 ; eax=4, write() syscall
mov ebx, 1 ; ebx=1, stdout
mov ecx, endl ; adres tekstu do ecx
mov edx, 1 ; długość tekstu do edx
int 0x80 ; wywołanie funkcji systemowej
 
mov ecx,[skok]
shl ecx,1 ; mnożymy skok przez 2
mov [skok],ecx
cmp ecx,dword 64
 
; wyświetla znak końca linii
mov eax,[src] ; tablica wynikowa staje się teraz źródłową,
mov eax, 4 ; eax=4, write() syscall
mov ebx,[dst] ; a aktualna źródłowa będzie nadpisana zawartością
mov [src] ebx,ebx 1 ; nowej tablicyebx=1, wynikowejstdout
mov ecx, endl ; adres tekstu do ecx
mov [dst],eax
mov edx, 1 ; długość tekstu do edx
int 0x80 ; wywołanie funkcji systemowej
 
mov eax,[src] ; w celu oszczędności pamięci
jle petla2
mov eaxebx,[srcdst] ; tablica wynikowa staje się teraz źródłową,
mov ebx,[dstsrc],ebx ; a aktualna źródłowa będzie nadpisana zawartością
mov [dst],eax ; nowej tablicy wynikowej
shlmov ecx,1 [skok] ; mnożymy skok przez 2, jeżeli nowy skok
shl ecx,1 ; jest mniejszy od dwukrotności rozmiaru
mov [skok],ecx ; tablicy, wykonujemy skok do początku pętli głównej
cmpshr alecx,bl1 ;
cmp ecx,[cnt] ; rozpoczynając scalanie od pierwszego znaku
jlejl petla2 ;
 
; kończy program
mov eax, 1 ; exit() syscall
mov ebx, 5 ; kod wyjścia
int 0x80 ;
</source>