remove.asm
来自「汇编编程艺术」· 汇编 代码 · 共 261 行
ASM
261 行
; Need to include "lists.a" in order to get list structure definition.
include lists.a
wp equ <word ptr> ;I'm a lazy typist
; Special case to handle MASM 6.0 vs. all other assemblers:
; If not MASM 5.1 or MASM 6.0, set the version to 5.00:
ifndef @version
@version equ 500
endif
StdGrp group stdlib,stddata
stddata segment para public 'sldata'
stddata ends
stdlib segment para public 'slcode'
assume cs:stdgrp
; sl_Remove - ES:DI points at a list.
; CX contains an index into that list.
; Removes the specified node from the list and returns a
; pointer to this item in DX:SI. Returns the carry
; flag set if the list was empty.
;
; Randall Hyde 3/24/94
;
public sl_Remove
sl_Remove proc far
push ds
push ax
push es
push di
if @version ge 600
; MASM 6.0 version goes here
cmp wp es:[di].List.Tail+2, 0 ;Empty list?
jne HasAList
; At this point, the Tail pointer is zero. This only occurs if the
; list is empty.
;
; Note: Technically, the NIL pointer is 32-bits of zero. However, this
; package assumes that if the segment is zero, the whole thing is zero.
; So don't put any nodes into segment zero!
NotThere: xor dx, dx ;Set DX:SI to NIL.
mov si, dx
pop di
pop es
stc
jmp RemoveDone
; If the HEAD pointer is NON-NIL, remove the specified node here.
HasAList: lds si, es:[di].List.Head ;Get node to delete.
jmp short FNentry
FindNode: lds si, ds:[si].Node.Next
FNEntry: cmp wp ds:[si+2].Node.Next, 0 ;NIL ptr?
je NotThere
loop FindNode
; Remove this guy by doing the following:
;
; +----------+ +----------+ +----------+
; | | --> | | --> | |
; +----------+ +----------+ +----------+
;
; First, set the next field of the previous node to point at the next field
; of the current node:
;
; +----------+ +----------+ +----------+
; | | -+ | | +-> | |
; +----------+ | +----------+ | +----------+
; +-------------------+
FoundIt: cmp wp ds:[si].Node.Prev+2, 0 ;No previous node?
je CurrentIs1st
les di, ds:[si].Node.Prev
mov dx, wp ds:[si].Node.Next
mov wp es:[di].Node.Next, dx
mov dx, wp ds:[si].Node.Next+2
mov wp es:[di].Node.Next+2, dx
jmp short FixNextNode
; If there was no first node, then the current node is the first node in
; the list. We need to patch the HEAD pointer in this case.
CurrentIs1st: pop di ;Get ptr to list
pop es
push es
push di
mov dx, wp ds:[si].Node.Next
mov wp es:[di].List.Head, dx
mov dx, wp ds:[si].Node.Next+2
mov wp es:[di].List.Head+2, dx
; Next, set the previous field of the next node to point at the previous
; node:
;
; +----------+ +----------+ +----------+
; | | <-- | | <-- | |
; +----------+ +----------+ +----------+
;
; +----------+ +----------+ +----------+
; | | <-+ | | +- | |
; +----------+ | +----------+ | +----------+
; +-------------------+
FixNextNode: cmp wp ds:[si].Node.Next+2, 0 ;No next node?
je CurrentIsLast
les di, ds:[si].Node.Next
mov dx, wp ds:[si].Node.Prev
mov wp es:[di].Node.Prev, dx
mov ax, wp ds:[si].Node.Prev+2
mov wp es:[di].Node.Prev+2, dx
mov dx, es ;Save ptr to new
mov ax, di ; current node
pop di
pop es
mov wp es:[di].List.CurrentNode, ax
mov wp es:[di].List.CurrentNode+2, dx
jmp GoodRemove
; If the current node was the last node in the list, we've got to patch the
; TAIL pointer in the list structure.
CurrentIsLast: cmp wp ds:[si].Node.Prev+2, 0 ;Was this the only
je OnlyNodeInList ; node?
pop di
pop es
mov dx, wp ds:[si].Node.Prev
mov wp es:[di].List.Tail, dx
mov wp es:[di].List.CurrentNode, dx
mov dx, wp ds:[si].Node.Prev+2
mov wp es:[di].List.Tail+2, dx
mov wp es:[di].List.CurrentNode+2, dx
jmp GoodRemove
; If the current node was the only node in the list, set the TAIL and
; CurrentNode fields to NIL. Note that HEAD was already set to NIL.
OnlyNodeInList: pop di
pop es
xor dx, dx
mov wp es:[di].List.Tail, dx
mov wp es:[di].List.Tail+2, dx
mov wp es:[di].List.CurrentNode, dx
mov wp es:[di].List.CurrentNode+2, dx
else
; Other assemblers' version goes here
cmp wp es:[di].Tail+2, 0
jne HasAList
NotThere: xor dx, dx
mov si, dx
pop di
pop es
stc
jmp RemoveDone
HasAList: lds si, es:[di].Head
jmp short FNEntry
FindNode: lds si, ds:[si].Next
FNEntry: cmp wp ds:[si+2].Next, 0
je NotThere
loop FindNode
FoundIt: cmp wp ds:[si].Prev+2, 0
je CurrentIs1st
les di, ds:[si].Prev
mov dx, wp ds:[si].Next
mov wp es:[di].Next, dx
mov dx, wp ds:[si].Next+2
mov wp es:[di].Next+2, dx
jmp short FixNextNode
CurrentIs1st: pop di
pop es
push es
push di
mov dx, wp ds:[si].Next
mov wp es:[di].Head, dx
mov dx, wp ds:[si].Next+2
mov wp es:[di].Head+2, dx
FixNextNode: cmp wp ds:[si].Next+2, 0
je CurrentIsLast
les di, ds:[si].Next
mov dx, wp ds:[si].Prev
mov wp es:[di].Prev, dx
mov ax, wp ds:[si].Prev+2
mov wp es:[di].Prev+2, dx
mov dx, es
mov ax, di
pop di
pop es
mov wp es:[di].CurrentNode, ax
mov wp es:[di].CurrentNode+2, dx
jmp GoodRemove
CurrentIsLast: cmp wp ds:[si].Prev+2, 0
je OnlyNodeInList
pop di
pop es
mov dx, wp ds:[si].Prev
mov wp es:[di].Tail, dx
mov wp es:[di].CurrentNode, dx
mov dx, wp ds:[si].Prev+2
mov wp es:[di].Tail+2, dx
mov wp es:[di].CurrentNode+2, dx
jmp GoodRemove
OnlyNodeInList: pop di
pop es
xor dx, dx
mov wp es:[di].Tail, dx
mov wp es:[di].Tail+2, dx
mov wp es:[di].CurrentNode, dx
mov wp es:[di].CurrentNode+2, dx
endif
GoodRemove: clc
mov dx, ds
RemoveDone: pop ax
pop ds
ret
sl_Remove endp
stdlib ends
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?