⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 汇010.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:
 21H 
.UNTILCXZ 
MOV DL, CR ;下面六条指令显示回车、换行 
MOV AH, 2 
INT 21H 
MOV DL, LF 
MOV AH, 2 
INT 21H 
RET 
Display ENDP 
.STARTUP 
INVOKE Display, Data1 
INVOKE Display, -123456789 
.EXIT 0 
END 
例10.8 编写程序,它能把字类型变量的数值以二、八进制或十六进制形式输出出来。若该数值为负数,则需要输出负号"-",否则,不输出符号。 
例10.10 编写一个程序,它能把用键盘输入的字符串转化成相应的数值。具体功能如下: 
1、 输入的数据字符串可以带正、负符号,如:1234、+1234或-1234; 
2、 字符串的最后一个字符表示数据的进制,默认的进制为十进制,如:1234H表示十六进制数1234,1234为十进制数; 
3、 对于任何进制的数据,当遇到一个非进制范围内的字符时,则显示出错信息,并以数值为其转换结果来结束该类型转换过程。 

解:
10.4 文件操作程序
有关目录和顺序文件的操作在第8.3.6节中已有介绍和举例,本节主要介绍对记录文件的读写方法。记录文件是指文件中的每个分量是一个结构的文件,如:Fox系列数据库管理系统中的DBF文件,该文件除了文件头是由记录文件的整体信息和各字段描述信息之外,文件的主体内容就是由同一个结构组成的。 

下面通过二个例子来介绍记录文件的读写方法。 

例10.11 假设有一个简单的学生结构类型student,其包括:学号、姓名和年龄等信息,要求编写一个程序,该程序接受从键盘输入的学生记录信息,并把它们保存在文件students.dat之中。 

解: 
 .MODEL SMALL, C 
.486 
student STRUCT 
id DW ? 
sname DB 10 DUP(?) 
age DB ? 
student ENDS 
.DATA 
fname
 DB "Students.dat",0 
msg1
 DB "Id:$" 
msg2
 DB "Name:$" 
msg3
 DB "Age:$" 
msg4
 DB "Continue?$" 
msg5
 DB "Fail to create file$" 
CRLF
 DB 0AH, 0DH, "$" 
buff
 DB ?, ?, 11 DUP(?) 
peason
 STUDENT <> 
.CODE 
DispMsg PROC USES AX DX, Msg:PTR BYTE ;显示字符串Msg 
…… ;参见例10.7 
DispMsg ENDP 
;程序功能:把字符串Data转化成数值,不考虑负数。当遇到非法字符时,则结束转换操作; 
;入口参数:Data为字符串的首地址,Len为该字符串的长度; 
;出口参数:数值存放在AX中。 
GetData PROC USES BX CX SI, Len:BYTE, Data:PTR BYPE 
XOR CX, CX 
MOV CL, Len 
MOV SI, Data 
XOR AX, AX 
XOR BX, BX 
.REPEAT 
MOV
 BL, [SI] 
SUB
 BL, '0' 
.BREAK .IF BL<0 || BL>9
 ;判断当前数值是否在0~9之间 
IMUL
 AX, 10 
ADD
 AX, BX 
INC
 SI 
.UNTILCXZ 
RET 
GetData ENDP 
;程序功能:读取指定长度的字符串,在输入前,显示有关输入内容的提示信息; 
;入口参数:读入字符串的长度为Len,提示信息的首地址为MSG; 
;出口参数:读入信息(字符串)存放缓冲区buff中。 
GetInfo PROC  USES AX DX, Len:BYTE, Msg:PTR BYTE 
INVOKE DispMsg, Msg ;显示提示信息 
MOV AL, Len 
MOV buff, AL 
MOV AH, 0AH 
LEA DX, buff 
INT 21H 
INVOKE DispMsg, ADDR CRLF ;显示回车、换行 
RET 
GetInfo ENDP 
.STARTUP 
MOV AX, DS 
MOV ES, AX 
LEA DX, fname 
MOV CX, 20H 
MOV AH, 3CH 
INT 21H ;创建文件 
.IF CARRY? ;若创建失败,则显示失败信息 
INVOKE DispMsg, ADDR msg5
 
JMP over
 
.ENDIF 
MOV BX, AX ;把句柄存入BX,为后面使用作准备 
again: 
 INVOKE DispMsg, ADDR CRLF ;显示回车、换行 
INVOKE GetInfo, 5, ADDR msg1 ;读取学号(假定学号为4位整数) 
INVOKE GetData, 4, ADDR buff+2 ;把学号字符串转化成数值 
MOV peason.id, AX ;把数值型学号存入学号字段 
INVOKE GetInfo, 11, ADDR msg2 ;读取姓名(假定姓名为10个字符) 
MOV CX, 10 
MOV AL, ' '   
LEA DI, peason.sname 
REP STOSB ;先置姓名字段为10个空格 
MOV CL, buff+1 
MOV SI, OFFSET buff+2 
LEA DI, peason.sname 
REP MOVSB ;把输入的姓名存入姓名字段 
INVOKE GetInfo, 3, ADDR msg3 ;读取年龄(假定年龄为2位整数)  
INVOKE GetData, 2, ADDR buff+2 ;把年龄字符串转化成数值 
MOV peason.age, AL ;把数值型年龄存入年龄字段 
MOV CX, SIZE peason 
LEA DX, peason 
MOV AH, 40H 
INT 21H ;把学生记录写入文件 
INVOKE DispMsg, ADDR msg4 ;提示是否继续输入 
MOV AH, 1 
INT 21H 
AND AL, 0DFH 
CMP AL, 'Y'  
JZ again ;若按y或Y,则继续输入 
MOV AH, 3EH 
INT 21H 
over: 
 .EXIT 0 
END 
例10.12 编写一个程序显示由例10.11建立的记录文件students.dat中的学生信息。  

解: 
 .MODEL SMALL,C 
student STRUCT 
id DW ? 
sname DB 10 DUP(?) 
age DB ? 
student ENDS 
.DATA 
fname
 DB "Students.dat",0 
id1
 DB "Id:", 4 dup(?), 0dh, 0ah, "$" 
name1
 DB "Name:", 10 dup(' '), 0dh, 0ah, "$" 
age1
 DB "Age:", 2 dup(?), 0dh, 0ah, "$" 
msg1
 DB "Fail to open file$" 
peason
 student <> 
.CODE 
DispMsg PROC USES AX DX, Msg:PTR BYTE ;显示字符串Msg 
…… ;参见例10.7 
DispMsg ENDP 
;程序功能:把数据Data转换成长度为Len的字符串;
;入口参数:待转换数据Data,转换成字符串的长度为Len,存放字符串的首地址为PStr;
;出口参数:读入信息(字符串)存放缓冲区buff中。 
GetStr PROC USES AX CX DX DI, Data:WORD, Len:WORD, PStr:PTR BYTE 
MOV CX, Len 
MOV DI, PStr 
MOV AL, ' ' 
REP STOSB ;把存放字符串的缓冲区填充为空格 
MOV DI, PStr 
ADD DI, Len 
DEC DI ;确定最后一个字符在缓冲区中的位置 
MOV AX, Data 
MOV CX, 10 
.REPEAT 
XOR DX, DX 
IDIV CX ;除10,从低位向高位求得每一位 
ADD DL, '0' ;把余数转变成字符,然后存放目标单元 
MOV [DI], DL 
DEC DI 
.UNTIL AX==0 
RET 
GetStr ENDP 
 .STARTUP 
MOV AX, DS 
MOV ES, AX 
LEA  DX, fname 
MOV AL, 0H 
MOV AH, 3DH 
INT 21H ;以“只读”方式打开指定的文件 
.IF CARRY? ;若创建失败,则显示失败信息 
INVOKE DispMsg, ADDR msg1
 
JMP over
 
.ENDIF 
MOV BX, AX ;把句柄存入BX,为后面使用作准备 
again: 
 MOV CX, SIZE peason 
LEA DX, peason 
MOV AH, 3FH 
INT 21H ;从文件中读出一个记录 
.IF CARRY? || AX==0 ;若读记录出错或遇到文件尾,结束 
JMP
 close 
.ENDIF  
INVOKE GetStr, peason.id, 4, ADDR Id1+3 ;把“学号”转换成字符串 
INVOKE DispMsg, ADDR Id1 ;显示“学号”字符串 
MOV CX, 10 
LEA SI, peason.sname 
LEA DI, Name1+5 
REP MOVSB ;把“姓名”转移到显示区 
INVOKE DispMsg, ADDR Name1 ;显示“姓名”字符串 
INVOKE Getstr, peason.age, 2, ADDR Age1+4 ;把“年龄”转换成字符串 
INVOKE Dispmsg, ADDR Age1 ;显示“年龄”字符串 
JMP again 
close: 
 MOV AH, 3EH 
INT 21H ;关闭当前打开的文件 
over: 
 .EXIT 0 
END 

从例10.11和10.12,我们不难掌握记录文件的读写方法。有兴趣的读者,还可以利用文件指针的定位来指定读写某个具体的记录。
10.5 动态数据的编程
动态数据结构是一种常用的数据结构,在事先不知道所处理数据容量的情况,用动态数据是一种行之有效的方法,也为许多C语言程序员所采用。在汇编语言中,我们也可以采用动态数据的方式来存储数据,并进行链表的遍历。  

为了使读者尽快理解本例的功能,我们把与之相似功能的C语言程序书写如下:

 #include <stdio.h> 
#include <alloc.h> 
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\n",head->data);
 
 pt = head;   head = head->next;   free(pt);
 
}
 
} 

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

例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 
10.6 COM文件的编程
COM文件和EXE文件都是可执行文件,最典型的COM文件是Command.COM。COM文件的主要特点如下: 

1、COM文件只有一个段,其字节数不会超过64K;
2、当操作系统装入COM文件时,四个段寄存器(CS、DS、ES和SS)都 用PSP的段值来初始化;
3、必须用伪指令ORG 100H来说明空出前256个字节。 

例10.14 编写一个显示字符串“Hello”的COM类型的程序。

解:  
CSEG   SEGMENT  'CODE' 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -