例10.13 编写一个程序用动态链表存储20,19,……,1,并用遍历链表的方法来显示每个结点的数值。

解:为了便于理解本例程序的执行过程和所构成的动态链表,我们把该链表的构成过程表示成图10.1所示。

图10.1 动态链表数据结构示意图

.MODEL SMALL, C
.DATA

Head

DW 0 ;链表的头指针,初值为空

PT

DW ? ;临时链表指针:当前的链表尾

Buff

DB ?, ?, "$" ;存放输出结果的缓冲区

CRLF

DB 0DH, 0AH, "$" ;回车、换行信息
.CODE
DispMsg PROC USES AX DX, Msg:PTR BYTE ;显示字符串Msg
…… ;参见例10.7
DispMsg ENDP
.STARTUP
MOV CX, 20
.REPEAT

MOV

BX, 1 ;申请内存的字节数=BX×16

MOV

AH, 48H

INT

21H ;申请内存的空间

.BREAK .IF CARRY?

;申请内存失败

MOV

ES, AX ;AX=申请内存的段地址

MOV

WORD PTR ES:[0], CX ;给第一个字赋值

MOV

WORD PTR ES:[2], 0 ;给第二个字置“空”(NULL)

.IF Head==0

MOV Head, ES

;保存链表的头指针

.ELSE

PUSH DS

MOV DS, PT

MOV WORD PTR DS:[2], ES

;把当前申请到的结点链到链表中

POP DS

.ENDIF

MOV

PT, ES ;当前结点向后移
.UNTILCXZ
MOV BX, Head ;从头开始遍历链表
.WHILE (BX!=0)

MOV

ES, BX ;第一个结点的段地址

MOV

AX, ES:[0] ;取第一个结点的数据字段值

MOV

DL, 10

IDIV

DL

ADD

AX, 3030H ;把结点的值转换成字符

LEA

BX, BUFF

MOV

[BX], 2020H ;把字符缓冲区清空

.IF AL>30H

;若十位有非零值,则存储其字符

MOV [BX], AL

INC BX

.ENDIF

MOV

[BX], AH ;存储个位字符

INVOKE

DispMsg, ADDR Buff ;显示结点数据的字符串

INVOKE

DispMsg, ADDR CRLF ;显示回车、换行

MOV

BX, ES:[2] ;BX=下一个结点的段地址

MOV

AH, 49H ;当前结点的段地址已在ES中

INT

21H ;释放当前结点所占的空间
.ENDW
.EXIT 0
END

关 闭