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 + -
显示快捷键?