动态数据结构是一种常用的数据结构,在事先不知道所处理数据容量的情况,用动态数据是一种行之有效的方法,也为许多C语言程序员所采用。在汇编语言中,我们也可以采用动态数据的方式来存储数据,并进行链表的遍历。
为了使读者尽快理解本例的功能,我们把与之相似功能的C语言程序书写如下:
#include#include struct link { int data ; struct link *next ; }; void main( ) {struct link *head=NULL, *temp, *pt; int i ; for (i = 20 ; i > 0; i--) {?? ;生成20个结点的链表 temp = (struct link *)calloc(1,sizeof(struct link)) ; ;申请一个结点的空间 if (temp == NULL) break ;?;若分配内存失败 temp->data = i ; temp->next = NULL ; if (head == NULL) head = temp ; else pt->next = temp ; pt = temp ; } while (head != NULL) {?;遍历结点并输出其数据字段 printf("%d ",head->data); pt = head ;?head = head->next;?free(pt); } }
例10.13 编写一个程序用动态链表存储20,19,……,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