例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 | ||||