Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Utility / LIST / Podpůrné funkce

Zdrojový kód: INCLUDE\UTIL\LIST.INC, UTIL\LIST.ASM


Podpůrné funkce

Následující funkce jsou použity jako doplňkové operace prováděné nad seznamem prvků.


; -----------------------------------------------------------------------------
;                       Replace old entry with new one
; -----------------------------------------------------------------------------
; INPUT:	EAX = new entry
;		EBX = old entry
; -----------------------------------------------------------------------------

; ------------- Push registers

ListReplace:	push	ecx		; push ECX
		push	edx		; push EDX

; ------------- Replace entry

		mov	ecx,[ebx+LIST_Prev] ; ECX <- get previous entry
		mov	edx,[ebx+LIST_Next] ; EDX <- get next entry
		LINKLINK ecx,eax	; link new entry to previous entry
		LINKLINK eax,edx	; link next entry to new entry

; ------------- Pop registers

		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret

Funkce ListReplace zajistí náhradu prvku seznamu jiným prvkem (který není součástí žádného seznamu). V registru EAX je funkci předán ukazatel na nový prvek seznamu (který nahradí starý prvek), v registru EBX ukazatel na starý prvek seznamu (který bude nahrazen novým prvkem).

Registry ECX a EDX jsou použity jako přechodné, jejich obsahy jsou proto uchovány instrukcemi PUSH/POP. Do přechodných registrů je ze staré položky seznamu načten ukazatel na předcházející položku (registr ECX) a ukazatel na následující položku (registr EDX). Poté je předcházející položka propojena s nově vkládanou položkou seznamu a dále je nově vkládaná položka propojena s následující položkou seznamu.


; -----------------------------------------------------------------------------
;                    Exchange entry with next entry
; -----------------------------------------------------------------------------
; INPUT:	EBX = current entry
; -----------------------------------------------------------------------------

; ------------- Push registers

ListXchgNext:	push	eax		; push EAX
		push	ecx		; push ECX

; ------------- Exchange entries

		mov	eax,[ebx+LIST_Prev] ; EAX <- previous entry
		mov	ecx,[ebx+LIST_Next] ; ECX <- next entry
		LINKLINK eax,ecx	; link next entry to previous entry
		mov	eax,[ecx+LIST_Next] ; EAX <- next next entry
		LINKLINK ecx,ebx	; link current entry to next entry
		LINKLINK ebx,eax	; link next entry to current entry

; ------------- Pop registers

		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Funkce ListXchgNext zajistí prohození dvou za sebou následujících prvků. V registru EBX je funkci předán ukazatel na aktuální prvek, tento prvek bude zaměněn s následujícím prvkem. Může se přitom jednat o jediný prvek seznamu.

Jako přechodné registry se použijí registry EAX a ECX, jejich obsahy jsou uchovány instrukcemi PUSH/POP. Do registru EAX je z aktuální položky načten ukazatel na předcházející položku, do registru ECX ukazatel na následující položku (tedy na položku, s níž má být provedena záměna). Následující položka je propojena s předcházející položkou pomocí makra LINKLINK. Dále již není ukazatel na předcházející položku potřeba a proto je do registru EAX z následující položky načten ukazatel na příští následující položku (tj. následující položka následující položky). Nakonec je aktuální položka připojena za původní následující položku a před původní příští následující položku.


; -----------------------------------------------------------------------------
;                 Detach list chain and splice it with other list
; -----------------------------------------------------------------------------
; INPUT:	EAX = source list head (it will become empty)
;		EBX = destination list head
; -----------------------------------------------------------------------------

; ------------- Push registers

ListSplice:	push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI

; ------------- Check if source list is already empty

		LISTTEST eax		; is source list empty?
		je	ListSplice2	; source list is empty

; ------------- Detach list chain from source list

		mov	ecx,[eax+LIST_Next] ; ECX <- first entry of source list
		mov	edx,[eax+LIST_Prev] ; EDX <- last entry of source list
		LISTINIT eax		; close source list

; ------------- Atach list chain to destination list

		mov	esi,[ebx+LIST_Next] ; ESI <- first entry of destination
		LINKLINK ebx,ecx	; link first entry to destination
		LINKLINK edx,esi	; link 1st entry 2 to last entry 1

; ------------- Pop registers

ListSplice2:	pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		ret

Poslední funkcí je funkce ListSplice, která odpojí část seznamu a nahradí ho jiným seznamem. Vstupními parametry jsou ukazatel na záhlaví zdrojového seznamu v registru EAX a ukazatel na záhlaví cílového seznamu v registru EBX. Zdrojový seznam bude po operaci prázdný a jeho obsah bude začleněn na začátek cílového seznamu.

Registry ECX, EDX a ESI jsou použity jako přechodné registry, jejich obsahy jsou proto uchovány instrukcemi PUSH/POP. Zdrojový seznam je nejdříve ověřen, zda není prázdný, v tom případě funkce nepokračuje. Dále je nutno odpojit řetězec prvků ze zdrojového seznamu. Do registru ECX se načte ukazatel na první položku zdrojového seznamu, do registru EDX ukazatel na poslední položku zdrojového seznamu. Zdrojový seznam je inicializován na prázdný seznam pomocí makra LISTINIT.

Zdrojový seznam je nyní nutné připojit k cílovému seznamu. Do registru ESI je načten ukazatel na první položku cílového seznamu. První položka zdrojového seznamu je připojena k záhlaví cílového seznamu jako jeho první položka a poslední položka zdrojového seznamu je připojena před původní první položku cílového seznamu.


Obsah / Utility / LIST / Podpůrné funkce