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

Obsah / Utility / LIST / Přidání prvku do seznamu

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


Přidání prvku do seznamu

Přidání prvku do seznamu znamená provázání ukazatelů vkládané položky s ukazateli předcházející a následující položky seznamu. Operace platí i při vložení prvku do prázdného seznamu, kdy oba ukazatele záhlaví seznamu ukazují samy na sebe.


; ------------- Macro - link two entries together (%1=1st entry, %2=2nd entry)

%macro		LINKLINK 2
		mov	[%1+LIST_Next],%2 ; link second entry after first one
		mov	[%2+LIST_Prev],%1 ; link first entry previous second
%endmacro

Makro LINKLINK je pomocné makro pro další operace a zajistí provázání ukazatelů dvou za sebou následujících prvků. Prvním parametrem makra je ukazatel na první (předcházející) položku seznamu, druhým parametrem ukazatel na druhou (následující) položku seznamu. Makro nastaví ukazatel LIST_Next první položky na adresu druhé položky a ukazatel LIST_Prev druhé položky na adresu první položky.


; ------------- Macro - add new entry into begin of list or after current entry
; %1 = list head or current entry, %2 = new entry, %3 = temporary register

%macro		LISTADD	3
		mov	%3,[%1+LIST_Next] ; get next (first) entry
		LINKLINK %1,%2		; link head/current with new entry
		LINKLINK %2,%3		; link new entry with next entry
%endmacro

Druhé makro LISTADD slouží k vložení položky na začátek seznamu (pokud první parametr makra ukazuje na záhlaví seznamu) nebo za jinou položku (pokud první parametr makra ukazuje na jinou položku). Druhým parametrem makra je ukazatel na nově vkládanou položku. Třetím parametrem je pomocný registr, který bude použit k uchování ukazatele na následující položku seznamu. Ten je získán první instrukcí načtením ukazatele LIST_Next ze záhlaví seznamu nebo z jiné položky. Dále následuje makro LINKLINK, které zajistí propojení ukazatelů záhlaví seznamu nebo předcházející položky s ukazateli nově vkládané položky. Druhým makrem LINKLINK se zajistí propojení ukazatelů nově vkládané položky s ukazateli následující položky.


; -----------------------------------------------------------------------------
;          Add new entry into begin of list or after current entry
; -----------------------------------------------------------------------------
; INPUT:	EAX = new entry
;		EBX = list head or current entry
; -----------------------------------------------------------------------------

ListAfter:
ListAdd:	push	ecx		; push ECX
		LISTADD	ebx,eax,ecx	; add new entry into list
		pop	ecx		; pop ECX
		ret

Makro LISTADD je použito ve funkci ListAdd resp. ListAfter, která zajistí vložení nového prvku na začátek seznamu nebo za jiný prvek seznamu. V registru EAX je funkci předán ukazatel na popisovač seznamu nově vkládaného prvku, v registru EBX ukazatel na záhlaví seznamu nebo na předcházející prvek. Registr ECX bude použit jako přechodný registr, jeho obsah je proto uchován instrukcemi PUSH/POP.


; -----------------------------------------------------------------------------
;         Add new safe entry into begin of list or after current entry
; -----------------------------------------------------------------------------
; INPUT:	EAX = new entry
;		EBX = list head or current entry
; NOTES:	Safe list entry is not in list if NEXT points to itself.
; -----------------------------------------------------------------------------

ListSafeAfter:
ListSafeAdd:	LISTTEST eax		; test if list entry is in a list
		jne	ListSafeAdd4	; list entry is already in a list
		push	ecx		; push ECX
		LISTADD	ebx,eax,ecx	; add new entry into list
		pop	ecx		; pop ECX
ListSafeAdd4:	ret

Funkce ListSafeAdd resp. ListSafeAfter je variantou funkcí ListAdd resp. ListAfter pro bezpečný seznam. Před vložením položky do seznamu se nejdříve provede ověření, zda položka není součástí nějakého seznamu. Pokud již je součástí nějakého seznamu, žádná operace se neprovede.


; ------------- Macro - add new entry into end of list or before current entry
; %1 = list head or current entry, %2 = new entry, %3 = temporary register

%macro		LISTLAST 3
		mov	%3,[%1+LIST_Prev] ; get previous (last) entry
		LINKLINK %3,%2		; link new entry with previous entry
		LINKLINK %2,%1		; link head/current with new entry
%endmacro

Makro LISTLAST umožňuje vložení položky na konec seznamu (pokud je prvním parametrem makra ukazatel na záhlaví seznamu) nebo před jinou položku (pokud je prvním parametrem makra ukazatel na jinou položku). Druhým parametrem makra je ukazatel na nově vkládanou položku. Třetím parametrem je pomocný registr, který bude použit k uchování ukazatele na předcházející položku seznamu. Ten je získán první instrukcí načtením ukazatele LIST_Prev ze záhlaví seznamu nebo z jiné položky. Dále následuje makro LINKLINK, které zajístí propojení ukazatelů předcházející položky s ukazateli nově vkládané položky. Druhým makrem LINKLINK se zajistí propojení ukazatelů nově vkládané položky s ukazateli záhlaví seznamu nebo následující položky.


; -----------------------------------------------------------------------------
;           Add new entry into end of list or before current entry
; -----------------------------------------------------------------------------
; INPUT:	EAX = new entry
;		EBX = list head or current entry
; -----------------------------------------------------------------------------

ListBefore:
ListLast:	push	ecx		; push ECX
		LISTLAST ebx,eax,ecx	; add new entry into list
		pop	ecx		; pop ECX
		ret

Makro LISTLAST je použito ve funkci ListLast resp. ListBefore, která zajistí vložení nového prvku na konec seznamu nebo před jiný prvek seznamu. V registru EAX je funkci předán ukazatel na popisovač seznamu nově vkládaného prvku, v registru EBX ukazatel na záhlaví seznamu nebo na následující prvek. Registr ECX bude použit jako přechodný registr, jeho obsah je proto uchován instrukcemi PUSH/POP.


; -----------------------------------------------------------------------------
;         Add new safe entry into end of list or before current entry
; -----------------------------------------------------------------------------
; INPUT:	EAX = new safe entry
;		EBX = list head or current entry
; NOTES:	Safe list entry is not in list if NEXT points to itself.
; -----------------------------------------------------------------------------

ListSafeBefore:
ListSafeLast:	LISTTEST eax		; test if list entry is in a list
		jne	ListSafeLast4	; list entry is already in a list
		push	ecx		; push ECX
		LISTLAST ebx,eax,ecx	; add new entry into list
		pop	ecx		; pop ECX
ListSafeLast4:	ret

Funkce ListSafeLast resp. ListSafeBefore je variantou funkcí ListLast resp. ListBefore pro bezpečný seznam. Před vložením položky do seznamu se nejdříve provede ověření, zda položka není součástí nějakého seznamu. Pokud již je součástí nějakého seznamu, žádná operace se neprovede.


Obsah / Utility / LIST / Přidání prvku do seznamu