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

📄 汇010.txt

📁 会变语言实现的一些程序
💻 TXT
📖 第 1 页 / 共 3 页
字号:
 ORG 100H   ;空出前256个字节 
start: LEA DX, MSG 
MOV AH, 09H 
INT 21H 
MOV AX, 4C00H 
INT 21H 
MSG DB "Hello$" ;定义字符串 
CSEG ENDS 
END start 

对上面程序,其生成的COM文件只有23个字节,而其EXE文件的字节数会超过1K。 

在PWB编程环境下,可在Option→Project Templates→Set Project Template→在列表框中选DOS COM来指定生成COM文件。在Turbo Assember系统中,可用TASM、TLINK /T来指定生成COM文件。

 10.7 驻留程序
驻留程序TSR(Terminate but Stay Resident)是一种特殊应用程序,它在装入内存运行后,其部分代码仍然驻留在内存,当该段代码被激活时,它又进入运行状态。常用的驻留程序是作为某个中断处理程序的一部分,其激活条件就是系统产生了此中断的中断请求。 

虽然驻留程序可根据具体的需要有不同的编写方式,但其典型结构包括以下几部分: 

1、 保存、修改中断向量表; 
2、 程序第一次运行时的初始化部分:
◆用自己定义的地址来取代中断向量表中的原地址
◆确定驻留代码部分的字节数
◆用中断21H之功能31H把需要驻留代码部分驻留在内存 
3、 驻留内存的代码部分。 

例10.15 在NumLock处于“开状态”时,每按小键盘(Numeric Keypad)上的数字键,给出“啪啪”响声。

例10.15 在NumLock处于“开状态”时,每按小键盘(Numeric Keypad)上的数字键,给出“啪啪”响声。 

解: 
 CSEG SEGMENT 'CODE' 
ORG 100H 
start: 
 JMP init 
INT9 DD ? 
TSR: 
 PUSH AX 
PUSH CX 
PUSH DS ;保存寄存器 
MOV AH, 2 
INT 16H ;读取键盘当前状态 
TEST AL, 00100000B ;检测NumLock的状态 
JZ TSRExit 
IN AL, 60H 
CMP AL, 71 
JL TSRExit 
CMP AL, 83 
JG TSRExit 
MOV AL, 10110110B 
OUT 43H, AL ;向端口43H送特定的数0B6H 
MOV AX, 1000 
OUT 42H, AL 
MOV AL, AH 
OUT 42H, AL ;向端口42H送声音频率 
IN AL, 61H ;读取扬声器的当前状态 
MOV AH, AL ;把扬声器的状态保存在AH中 
OR AL, 03 
OUT 61H, AL ;开声音 
MOV CX, 9000 
delay: 
 LOOP delay ;声音延迟 
MOV AL, AH 
OUT 61H, AL ;恢复扬声器原来的状态,即关声音 
TSRExit: 
 POP DS 
POP CX 
POP AX  ;恢复寄存器 
JMP CS:INT9 ;转向中断9H原来的处理程序 
init: 
 CLI ;关中断 
MOV AH, 35H 
MOV AL, 09H 
INT 21H 
MOV WORD PTR INT9, BX 
MOV WORD PTR INT9+2, ES ;保存中断9H原处理程序入口地址 
MOV  AH, 25H 
MOV AL, 09H 
LEA DX, TSR 
INT 21H ;设置中断9H新的处理程序入口地址 
STI  ;开中断 
LEA DX, init 
ADD DX, 15 
MOV CL, 4 ;把init的偏移量转换成“节数” 
SHR DX, CL ;每节内有16个字节 
MOV AX, 3100H 
INT 21H 
CSEG ENDS 
END start 
例10.16 编写一个驻留程序,它可显示当前时间的秒数。 
例10.16 编写一个驻留程序,它可显示当前时间的秒数。

解: 
 CSEG SEGMENT 'CODE' 
  ORG 100H 
start: 
 JMP init 
INT1C DD ? 
SEC DW ? 
TSR: 
 PUSH AX 
PUSH BX 
PUSH  CX 
PUSH  DX 
PUSH  BP 
PUSH  DS 
PUSH  ES ;保存所用到的寄存器 
MOV AX, CS 
MOV DS, AX 
MOV  ES, AX ;把CS的值赋给DS和ES 
MOV  AH, 2H 
INT 1AH ;读取当前时间 
MOV  DL, DH 
AND  DH, 0FH 
MOV CL, 4 
SHR  DL, CL 
ADD  DX, 3030H 
MOV  SEC, DX ;把当前秒数转化成字符串 
MOV  AH, 13H 
MOV  AL, 0 
MOV BH, 0 
MOV  BL, 7 
MOV CX, 2 
MOV DX, 004EH  ;指定显示位置为(0,78) 
LEA  BP, SEC 
INT  10H ;在指定位置显示秒数 
POP ES ;恢复所用寄存器的值 
POP  DS 
POP  BP 
POP DX 
POP CX 
POP BX 
POP AX 
JMP CS:INT1C ;转向中断1CH原服务程序 
init: 
 CLI 
MOV AX, 351CH 
INT  21H 
MOV  word ptr INT1C, BX 
MOV word ptr INT1C+2, ES 
MOV  AX, 251CH 
LEA DX, TSR 
INT  21H 
STI 
LEA  DX, init 
ADD DX, 15 
MOV CL, 4 ;把init的偏移量转换成“节数” 
SHR DX, CL ;每节内有16个字节 
MOV AX, 3100H 
INT  21H 
CSEG  ENDS 
END  start 
10.8 程序段前缀及其应用
程序段前缀PSP(Program Segment Prefix)是一个具有256个字节的信息区,是可执行文件(EXE和COM)所特有的,其内容在操作系统装入该文件运行时存入。 

10.8.1 程序段前缀的字段含义
PSP信息区的字段分布如下表10.1所列。

表10.1 PSP信息区的字段分布表

偏移量 内容含义 偏移量 内容含义 
00~01H 程序结束指令中断20H 2E~31H 保留 
02~03H 分配给该程序的最后段的段地址 32~33H 文件句柄表的长度 
04~09H 保留 34~37H 指向文件句柄表的远指针 
0A~0DH 中断22H的地址(处理终止程序) 38~4FH 保留 
0E~11H 中断23H的地址(处理^Break) 50~51H 中断21H的功能调用 
12~15H 中断24H的地址(处理严重错误) 52~5BH 保留 
16~17H 保留 5C~6BH 参数区1 
18~2BH 缺省的文件句柄表 6C~7FH 参数区2 
2C~2DH 程序环境块的段地址 80~FFH 存储缺省DTA的缓冲区 

PSP信息区的字段说明: 

◆18~2BH字段:
 该字段内共有20个字节,每个字节存储一个文件句柄,所以,系统允许应用程序在某一时刻最多只能打开20个文件。 
前5个字节存储系统标准设备的句柄,可参阅8.3.6节——系统标准设备的句柄。

若某文件需要同时打开更多的文件,则需要调整文件句柄数。即:先用中断21H之功能4AH释放内存,再用其功能67H来设置新的文件句柄数。

MOV BX, NewNum         ;新的文件句柄最大数(20~65535)
MOV AH, 67H
INT 21H
 
◆ 2C~2DH字段: 该字段存放程序运行环境的段地址,程序的缺省运行环境有160个字节,最多可达32K。该环境含有系统命令,如:COMSPEC、PATH、PROMPT和SET。 
◆  5C~6BH字段: 该字段存放命令行的第一个参数。假设要执行下列命令:  
Masm D:test.asm
 
这时,04H(驱动器D)、8个字符的文件名和3个字符的后缀存放在该区域,没有存放字符的单元用空格(20H)来填充。若省缺驱动器和文件名,则第一个字节为00H,其它单元为20H。 
 
◆  6C~7FH字段: 该字段存放命令行的第二个参数。假设要执行下列命令: 
 
Masm D:test.asm, test.obj 
 
这时,test.obj作为第二参数存入该字段,存储方式如上字段。 
 
◆  80~FFH字段: 该字段的第一个字节存放命令行参数的字符数,第二个字节为空格,从第三个字节开始存放命令行参数字符。 
10.8.2 程序段前缀的应用
了解和掌握PSP中的信息分布就是为了利用其信息。对于EXE文件,可用中断21H之功能51H获取其段地址。如:

 MOV AH, 51H 
INT 21H ;BX=PSP的段地址 
MOV  ES, BX 
CMP  byte ptr ES:[80H], 0 ;检查PSP的长度 
JE next 

对于COM文件,因为其只有一个段,所以,可用更简单的方式来检查PSP的内容。

 MOV  BX, 80H 
CMP byte ptr [BX], 0 ;检查PSP的长度 
JE next 

例10.17 利用PSP中的信息来终止当前程序的运行。

解:显示解答

例10.18 编写程序,显示其命令行参数信息。 

解:在使用命令行时,操作系统通常允许在被装入的程序名之后附加多达127个字符(包括最后的回车符)作为其命令的参数。 

本例子的目的就是要了解命令行参数的存储方法,为以后使用命令行参数作准备。 

显示解答

例10.19 编写一个类型于DOS内部命令TYPE的程序,该命令的使用方法如下: 

……>type 文件1,文件2,… 

其功能是分别显示其参数文件1、文件2等内容,在显示文件内容前先显示文件名。显示完内容后,暂停,等待用户按任意键。若某文件不存在,则显示相应的提示信息。 

解:为了较好地解答本题,我们可以对该问题按以下步骤来解决: 

1、若命令行参数中的字符数为0,则结束本程序的运行;
2、从命令行参数中分离出一个文件名;
3、调用子程序,显示当前文件名、文件内容和等待用户按键;
4、重复步骤1~3,直到所有参数被处理完。 
例10.19 编写一个类型于DOS内部命令TYPE的程序,该命令的使用方法如下: 

……>type 文件1,文件2,… 

其功能是分别显示其参数文件1、文件2等内容,在显示文件内容前先显示文件名。显示完内容后,暂停,等待用户按任意键。若某文件不存在,则显示相应的提示信息。 

解:为了较好地解答本题,我们可以对该问题按以下步骤来解决:
1、若命令行参数中的字符数为0,则结束本程序的运行;
2、从命令行参数中分离出一个文件名;
3、调用子程序,显示当前文件名、文件内容和等待用户按键;
4、重复步骤1~3,直到所有参数被处理完。 

 .MODEL SMALL, C 
.DATA 
File
 DB 14 DUP(' ') 
Buff 
 DB 128 DUP(0) 
Msg1
 DB 0DH, 0AH, "$" 
Msg2
 DB "Not Found$" 
Msg3
 DB "Press any key...$" 
.CODE 
;显示字符串MSG后,再进行回车、换行 
DispStr PROC USES AX DX, MSG:PTR BYTE 
 MOV DX, MSG ;显示指定的信息  
MOV AH, 09H 
INT 21H 
LEA DX, Msg1 ;显示回车、换行 
MOV AH, 09H 
INT 21H 
RET 
DispStr ENDP 
;文件名的长度为传递参数Len。若文件不存在,则显示提示信息,否则,显示文件内容;
;完成上述操作后,等待用户按键 
Disp PROC USES AX BX CX DX, Len:BYTE 
XOR BX, BX 
MOV BL, Len 
MOV File[BX], '$' 
INVOKE DispStr, ADDR File ;显示文件名 
MOV File[BX],0 
LEA DX, File 
MOV AL, 0H 
MOV AH, 3DH 
INT 21H 
.IF CARRY? ;若创建失败,则显示失败信息 
INVOKE DispStr, ADDR Msg2
 
JMP
 over1 
.ENDIF 
MOV BX, AX ;参见例8.14中的有关说明 
read: 
 LEA DX, Buff 
MOV CX, 128 
MOV AH, 3FH 
INT 21H 
.IF CARRY? || AX==0 
JZ
 close 
.ENDIF 
PUSH BX 
LEA DX, Buff 
MOV CX, AX 
MOV BX, 1 
MOV AH, 40H 
INT 21H 
POP BX 
JMP read 
close: 
 MOV AH, 3EH ;关闭已打开的文件 
INT 21H 
over1:  
INVOKE DispStr, ADDR Msg3 ;显示等待用户按键提示信息 
MOV AH, 07H 
INT 21H ;等待用户按键 
RET 
Disp ENDP 
.STARTUP 
MOV AH, 51H 
INT 21H 
MOV ES, BX 
MOV BX, 80H 
MOV CL, ES:[BX] 
DEC CL 
INC BX 
.WHILE CL>0 ;CL=未被处理的参数字符数 
XOR
 AL, AL ;记录文件名的长度 
LEA
 DI, File 
.REPEAT
 
INC
 BX 
MOV
 AH, ES:[BX] 
DEC
 CL 
.BREAK .IF AH==','
 
MOV
 [DI], AH ;从参数中分离出字符,存入文件名中 
INC
 DI 
INC
 AL 
.UNTIL
 CL==0 
INVOKE
 Disp, AL ;处理当前分离出来的文件名 
.ENDW 
.EXIT 0 
END 
10.9 习题
10.1、编写一个子程序,实现字符串的逆转。如:ABCD ==> DCBA。
 
10.2、编写一段程序,接收4位十六进制数,然后用移位的方法把它转换成8进制数并输出在屏幕上。
 
10.3、编写一段程序,以十六进制显示内存0400H:1000H开始的100字,要求每行显示16个字,每字之间有空格。
 
10.4、简述COM文件的主要特点,它与EXE文件有哪些差异?
 
10.5、编写一个显示"Hello"的程序,试比较它的COM格式文件和EXE格式文件的大小。
 
10.6、编写一个在屏幕上连续显示"Welcome…"的信息,要求显示颜色和显示位置都是随机的。在新位置显示时,原位置的信息抹去。当按任意键时,程序结束运行。
 
10.7、从键盘输入一个表示年份的正整数(1~65535),然后判断其是否为闰年。若是,则输出"Yes",否则,输出"No"。
 
10.8、编写一个带命令行参数的程序Words,输出指定正文文件中的单词,假设单词为连续的字母串。
比如:words file.txt,显示文件file.txt中的每个单词
 
10.9、编写一个建立双向链表的程序,每接受一个整数,链表增加一个结点,当遇到负数时,结束链表结点的增加,然后从表尾向前输出各结点中的数值。
 
10.10、编写一个带命令行参数的程序Calc,其命令行参数是一些整数,程序输出它们之和。如果某参数为非法整数,则忽略之。
比如:Calc 120 +34 -56,则程序显示98。
 
10.11、在10.10的基础上,在不考虑运算符优先级的情况下,实现一个可进行算术四则运算(只有加、减、乘和除,没有括号等)的计数器,并显示其计算结果。
 
10.12、编写一个简单的加密程序,它把一个文件中的所有字母字符按下列规律进行转换,非字母的字符保持不变。
转换规律:'A'→'Z','B'→'Y',……。
 
10.13、编写一个程序,它可显示BMP的图形文件。
 
10.14、编写一个程序,它可显示JPG的图形文件。
 

⌨️ 快捷键说明

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