📄 list.asm
字号:
;--------------------------------
;-- Define Linked-List objects --
;--------------------------------
MODEL SMALL
LOCALS
;** Define Linked-List object **
INCLUDE list.aso
INCLUDE node.aso
;** Create instance of Linked-List virtual method table **
DATASEG
TBLINST
;** Define some macros for use by the methods **
;** These are used by the methods for storing and loading double registers **
;Load two 16-bit registers from an address in specified segment
loadptr macro r2,r1, addr
mov r2,word ptr [addr+2]
mov r1,word ptr [addr]
endm
;Store two 16-bit registers to an address in specified segment
storeptr macro addr, r2,r1
mov word ptr [addr+2],r2
mov word ptr [addr],r1
endm
;Check to see if two 16-bit registers are both set to 0
;(r1 cannot be ax)
isnullptr macro r2,r1
ifdifi <r1>,<ax>
mov ax,r2
or ax,r1
else
push bx
push r2
pop bx
or bx,ax
pop bx
endif
endm
;** Linked-List methods **
CODESEG
;Construct a Linked-List object
;This is the method "list|construct"
;This must be a static method.
;Returns DX:AX pointing to linked-list object, null if none.
;Object is allocated but not yet initialized.
list_construct PROC PASCAL FAR
USES ds
;-- Allocate the Linked-List object --
mov bx,list_size
mov ah,48h
int 21h
jc @@err
mov dx,ax
sub ax,ax
ret
@@err: sub dx,dx
sub ax,ax
ret
ENDP
;Destroy a Linked-List object.
;This is the method "list|destroy"
list_destroy PROC PASCAL FAR
ARG @@list:dword
;-- deallocate memory for list --
mov es,word ptr @@list+2
mov ah,49h
int 21h
ret
ENDP
;Initialize a Linked-List object.
;This is the method "list|init"
;This must be a static method!
list_init PROC PASCAL FAR
ARG @@list:dword
USES ds,bx
lds bx,@@list
;-- Initialize any virtual method table for the object at ds:bx --
TBLINIT ds:bx
;-- Initialize the object's data --
sub ax,ax
storeptr ds:bx.list_head, ax,ax
storeptr ds:bx.list_tail, ax,ax
ret
ENDP
;Deinitialize a Linked-List object.
;This is the method "list|deinit"
list_deinit PROC PASCAL FAR
ARG @@list:dword
;does nothing.
ret
ENDP
;Insert a node into the Linked-List object.
;This is the method "list|insert".
list_insert PROC PASCAL NEAR
ARG @@list:dword,\ ;Pointer to list object
@@new:dword,\ ;Pointer to new node to insert
@@old:dword ;Pointer to node to insert before
USES ds,es,bx,cx,dx,si,di
les di,@@new ;es:di = new
lds si,@@old ;ds:si = old
;-- First, adjust backward links --
isnullptr ds,si ;old = null?
jz @@a
;-- there is an old node to insert before
loadptr dx,bx,ds:si.node_prev ;prev <- old.prev
storeptr ds:si.node_prev,es,di ;old.prev <- new
jmp short @@b
@@a: ;-- there is no old node to insert before - insert at end
push ds si ;(save old)
lds si,@@list ;(get list object)
loadptr dx,bx,ds:si.list_tail ;prev <- tail
storeptr ds:si.list_tail,es,di ;tail <- new
pop si ds ;(recall old)
@@b: ;-- Next, adjust forward links --
isnullptr dx,bx ;prev = null?
jz @@c
;-- there is a prev node to insert after
push ds ;(save old)
mov ds,dx ;(ds:bx = prev)
storeptr ds:bx.node_next,es,di ;prev.next <- new
pop ds ;(recall old)
jmp short @@d
@@c: ;-- there is no prev node to insert after - insert at start
push ds si ;(save old)
lds si,@@list ;(ds:si = list object)
storeptr ds:si.list_head,es,di ;head <- new
pop si ds ;(recall old)
@@d: ;-- Finally set pointers in this node
storeptr es:di.node_prev,dx,bx ;new.prev <- prev
storeptr es:di.node_next,ds,si ;new.next <- old
ret
ENDP
;Append a node at the end of a Linked-List object.
;This is the virtual method "list|append".
list_append PROC PASCAL NEAR
ARG @@list:dword,\
@@new:dword
USES ds,bx,es,di
mov ax,@Data
mov ds,ax
les di,@@list
sub ax,ax
call es:di method list:insert uses ds:bx pascal,es di,@@new,ax ax
ret
ENDP
;Remove a node from a Linked-List object.
;This is the virtual method "list|remove"
;This simply unlinks the node from the list; the node itself must be
;delete by calling the node|deinit method.
list_delete PROC PASCAL NEAR
ARG @@list:dword,\ ;pointer to linked-list object
@@node:dword ;pointer to node to delete
USES ds,es,si,di
lds si,@@node ;ds:si = node
les di,ds:[si.node_prev] ;es:di = prev
lds si,ds:[si.node_next] ;ds:si = next
;-- First change next node's previous pointer
isnullptr ds,si ;next = 0?
jz @@a ; yes - skip
storeptr ds:si.node_prev,es,di ; no - next.prev <- prev
jmp short @@b ; and skip...
@@a: push ds si ;(save next)
lds si,@@list ;(list object)
storeptr ds:si.list_tail,es,di ;tail <- prev
pop si ds ;(recall next)
@@b: ;-- Now change previous node's next pointer
isnullptr es,di ;prev = 0?
jz @@c ; yes - skip
storeptr es:di.node_next,ds,si ; no - prev.next <- next
jmp short @@d ; and done...
@@c: lds di,@@list ;(list object)
storeptr ds:di.list_head,ds,si ;head <- next
@@d: ret
ENDP
;Return a pointer to the first node in the list
;This is the virtual method "list|first"
;Returns DX:AX pointing to first node in list (null if none)
list_first PROC PASCAL NEAR
ARG @@list:dword ;pointer to linked-list object
USES ds,si
lds si,@@list
loadptr dx,ax, ds:si.list_head
ret
ENDP
;Return a pointer to the last node in the list
;This is the virtual method "list|last"
;Pass: pointer to object
;Ret: DX:AX points to last node in list (null if none)
list_last PROC PASCAL NEAR
ARG @@list:dword ;pointer to linked-list object
USES ds,si
lds si,@@list
loadptr dx,ax, ds:si.list_tail
ret
ENDP
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -