ITEEDU

10.5 动态数据的编程

动态数据结构是一种常用的数据结构,在事先不知道所处理数据容量的情况,用动态数据是一种行之有效的方法,也为许多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