实验一
判断字符串是否相等
编写程序,比较两个字符串STRING1和STRING2是否相同,若字符串相同则显示"Match!",否则显示"No Match!"
DATA SEGMENT ;定义数据段
STRING1 DB 'HAPPY ASM' ;定义字符串1
LEN EQU $-STRING1 ;定义常量LEN的值为字符串一的长度
STRING2 DB 'HAPPY ASM' ;定义字符串2
MSG1 DB 'Match!', 0DH, 0AH, '$' ;定义输出信息字符串
MSG2 DB 'No match!', 0DH, 0AH, '$' ;定义输出信息字符串
DATA ENDS ;数据段定义结束
CODE SEGMENT ;定义代码段
ASSUME CS:CODE, DS:DATA, ES:DATA ;关联段名与段寄存器
START: MOV AX, DATA
MOV DS, AX ;数据段段地址初始化
MOV ES, AX ;附加段段地址初始化
LEA SI, STRING1 ;获取两个字符串的偏移地址
LEA DI, STRING2
MOV CX, LEN ;将字符串长度写入计数寄存器
COMPARE:MOV AL, [SI] ;根据获取的偏移地址依次对比两个字符串的内容
MOV BL, [DI]
CMP AL, BL
JNE DISMATCH ;根据对比结果跳转是否匹配
INC SI
INC DI
LOOP COMPARE ;依次增加偏移地址并继续比较
MATCH: LEA DX, MSG1 ;若比较结束仍未跳转不匹配,说明相同
JMP DISP ;跳转display显示输出
DISMATCH:LEA DX, MSG2 ;若不匹配则将偏移地址送到DX数据寄存器
DISP: MOV AH, 09H
INT 21H ;根据对比结果显示DX内容
MOV AH, 4CH
INT 21H ;结束
CODE ENDS
END START
实验二
大小写转换
编写程序,从键盘输入一串字符,将其中的小写字母转变为大写字母,其他字符不作转换原样输出,结果在屏幕上显示
DATA SEGMENT ;定义数据段
SINPUT DB 0DH, 0AH, 'PLEASE INPUT A STRING:','$' ;定义输入提示字符串
SOUTPUT DB 0DH, 0AH, 'END:','$' ;定义结束提示字符串
BUF DB 30 ;定义缓冲区,第一个字节为缓冲区的最大容量,可认为是入口参数
DB ? ;第二个字节为实际输入的字符数(不包括回车键),可看作出口参数
DB 30 DUP(24H) ;24H是 '$' 从第三个字节开始存放实际输入的字符串
;若输入的字符数超过缓冲区的最大容量,则多出的部分被丢弃,系统并发出响铃,直到输入“回车”键才结束输入
DATA ENDS ;数据段定义结束
CODE SEGMENT ;定义代码段
ASSUME CS:CODE, DS:DATA ;关联段名与段寄存器
START:
MOV AX, DATA ;数据段段地址初始化(代码段不用初始化,会自动初始化)
MOV DS, AX
MOV AH, 09H
LEA DX, SINPUT
INT 21H ;使用DOS中断指令,显示输入提示字符串
LEA DX, BUF
MOV AH, 0AH ;键盘缓冲输入中断指令,将从键盘输入的字符串存在BUF,回车结束
INT 21H
MOV AH, 09H
LEA DX, SOUTPUT
INT 21H ;使用DOS中断指令,显示结束提示字符串
LEA SI, BUF+1 ;取字符串长度送至CL
MOV CL, [SI]
MOV CH, 00H ;将高位设为0,是为了接下来LOOP使用CX循环
LEA SI, BUF+2 ;取第一个字符的地址
X2: MOV AL, [SI] ;将第一个字符送至AL
CMP AL, 0DH ;是否为回车,是则跳转FINAL
JE FINAL
CMP AL, 61H ;小于'a',则跳转X1
JB X1
CMP AL, 7AH ;大于'z',则跳转X1
JA X1
SUB AL, 20H ;确定在a~z区间之后,进行加20H的操作转换为大写
X1: MOV [SI], AL ;将字符从AL送回原缓存区
INC SI
LOOP X2 ;偏移地址指针加一,继续比较
FINAL:
LEA DX, BUF+2 ;取字符串首地址
MOV AH, 09H
INT 21H ;将转换后的字符串输出
MOV AH, 4CH
INT 21H
CODE ENDS
END START
实验三
子程序设计
利用子程序的方法编写程序,设有10个无符号数的字节序列,查找该序列中的最大值和最小值,并把结果在屏幕上显示
DATA SEGMENT
ARRAY DB 4,5,9,12,12,10,9,5,7,8
LEN DB $-ARRAY
CRLF DB 0AH, 0DH, '$'
STR1 DB 'THE MAX NUMBER IS:$'
STR2 DB 'THE MIN NUMBER IS:$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
CALL FIND ;调用查找函数,找到最大值存入BH,最小值存入BL
LEA DX, STR1
MOV AH, 09H
INT 21H ;显示THE MAX NUMBER IS:
MOV DL, BH
CALL PRINTF ;显示最大值
LEA DX, CRLF
MOV AH, 09H
INT 21H ;输出回车换行
LEA DX, STR2
MOV AH, 09H
INT 21H ;显示THE MIN NUMBER IS:
MOV DL, BL
CALL PRINTF ;显示最小值
MOV AH, 4CH ;结束程序
INT 21H
FIND PROC ;定义查找函数
MOV CL, LEN
SUB CL, 1
LEA SI, ARRAY
MOV BH, [SI] ;BH负责存大数
MOV BL, [SI] ;BL负责存小数
X: INC SI
MOV AL, [SI] ;存下一个数
CMP AL, BL
JB MIN ;无符号小于则跳转
CMP AL, BH
JBE NEXT ;无符号小于等于则跳转,此时也就是判断是否等于
MOV BH, AL ;排除小于和等于,只剩大于,将更大的AL存入BH
JMP NEXT
MIN: MOV BL, AL ;将更小的AL存入BL
NEXT: LOOP X ;继续比较下一个
RET
FIND ENDP
PRINTF PROC ;定义输出函数
AND DL, 0FH ;将DL高四位清零,低四位保留
CMP DL, 9
JBE L1 ;如果DL小于等于9,则加30H转换输出
ADD DL, 37H ;否则加37H转换输出
;这里转换输出是因为调用的是02H功能,是单字符输出功能,而DL里面保存的是数值而非字符,需要转换为字符输出,也就是对应的ASCII码值,这样才能输出正确结果,否则会出现输出乱码,其中大于9的对应的是字母
JMP NEXT1 ;跳转到NEXT1输出
L1: ADD DL, 30H
NEXT1: MOV AH,02H
INT 21H
RET
PRINTF ENDP
CODE ENDS
END START
实验四
8259内部中断
用手动产生单脉冲作为中断请求信号,要求每按一次开关产生一次中断,在屏幕上显示一次"TPCA Interrupt!",中断十次后程序退出
DATA SEGMENT
MESS DB 'TPCA INTERUPT!',0DH,0AH,'$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, CS
MOV DS, AX
LEA DX, INT3 ;等效MOV DX, OFFSET INT3
MOV AX, 250BH ;设置IRQ3的中断向量,设置完后,识别到有0BH的中断类型号,会根据DS:DX的中断向量执行相应的中断服务程序
INT 21H ;中断,输出
IN AL, 21H ;从主片端口地址21H读入中断屏蔽器的当前屏蔽字
AND AL, 0F7H ;取消屏蔽D3的中断,1111 0111
OUT 21H, AL ;写回主片改变后的屏蔽字
MOV CX, 10 ;设置中断循环次数为10次,由CX储存
STI ;Set Interupt,允许中断发生,恢复中断,设置中断标志位
STOP: JMP STOP ;等待脉冲
INT3:
MOV AX, DATA ;将DATA数据段送入AX寄存器中暂存
MOV DS, AX ;将AX寄存器中的数据送入DS中
LEA DX, MESS ;取得MESS数据存储区的首地址并送入DX寄存器中
MOV AH, 09H ;调用DOS的9号功能,显示每次中断的提示信息
INT 21H ;中断,输出中断提示信息
MOV AL, 20H ;从端口地址20H读入ISR内容送入AL
OUT 20H, AL ;主片发出EOI结束命令
LOOP NEXT ;循环执行NEXT,直到中断程序的远返回
IN AL, 21H ;从主片端口地址21H读入中断屏蔽器的当前屏蔽字
OR AL, 08H ;屏蔽D3的中断,0000 1000
OUT 21H, AL ;写回主片改变后的屏蔽字
STI ;恢复中断,设置中断标志位
MOV AH, 4CH ;返回DOS
INT 21H
NEXT: IRET ;指令执行到中断程序的远返回
CODE ENDS
END START
连线图暂略
实验五
8255并行接口与交通灯控制
编写程序,模拟交通信号灯工作状态,利用实验台上的8255并行接口芯片的三个端口中的任意一端口,控制两组红、黄、绿六个发光二极管按照十字路口交通灯的规律交替亮、灭变化,当按下任意键则停止运行,并返回DOS
CODE SEGMENT
ASSUME CS:CODE
START:
MOV AL,80H ;1000 0000控制字
MOV DX,28BH ;段码地址
OUT DX,AL ;写入控制字
MOV AL,00100100B ;亮灯输出
MOV DX,28AH
OUT DX,AL
CALL LDELAY ;调用长延时
MOV CX,3
L1:MOV AL,01000100B ;亮灯输出
MOV DX,28AH
OUT DX,AL
CALL SDELAY ;调用短延时
MOV AL,00000100B ;亮灯输出
MOV DX,28AH
OUT DX,AL
CALL SDELAY ;调用短延时
LOOP L1 ;三次闪烁转到下一个亮灯模式
MOV AL,10000001B ;亮灯模式
MOV DX,28AH
OUT DX,AL
CALL LDELAY ;调用长延时
MOV CX,3
L2:MOV AL,10000010B ;以下同理
MOV DX,28AH
OUT DX,AL
CALL SDELAY
MOV AL,10000000B
MOV DX,28AH
OUT DX,AL
CALL SDELAY
LOOP L2
MOV AH,01H ;查询键盘缓冲区,对键盘扫描但不等待,并设置ZF标志
INT 16H ;若有按键操作(即键盘缓冲区不空),则ZF=0,AL中存放的是输入的ASCII码
JZ START ;AH中存放输入字符的扩展码。若无键按下,则标志位ZF=1,重复执行
MOV AH, 4CH
INT 21H
LDELAY PROC ;长延时子程序定义
PUSH CX
PUSH DI
MOV CX,2000H
Y1: MOV DI,2000H
X1: DEC DI
JNZ X1
LOOP Y1
POP DI
POP CX
RET
LDELAY ENDP
SDELAY PROC ;短延时子程序定义
PUSH CX
PUSH DI
MOV CX,500H
Y2:MOV DI,1000H
X2:DEC DI
JNZ X2
LOOP Y2
POP DI
POP CX
RET
SDELAY ENDP
CODE ENDS
END START
连线图暂略
实验六
8254可编程定时/计数器
编写程序,利用实验台上的8254定时器对1MHz的时钟脉冲进行分频,产生频率为1HZ的方波信号,并用逻辑笔(或示波器)观察
CODE SEGMENT
ASSUME CS:CODE
START:
MOV AL, 36H ;0011 0110
MOV DX, 283H ;设置计数器0-先读写低,再读写高-工作方式3-二进制
OUT DX, AL
MOV AX, 1000 ;设置计数初值
MOV DX, 280H ;将计数初值传入计数器0
OUT DX, AL ;先低位后高位
MOV AL, AH
OUT DX, AL
MOV AL, 76H ;0111 0110
MOV DX, 283H ;设置计数器1-先读写低,再读写高-工作方式3-二进制
OUT DX, AL
MOV AX, 1000 ;设置计数初值
MOV DX, 281H ;将计数初值传入计数器1
OUT DX, AL ;先低位后高位
MOV AL, AH
OUT DX, AL
MOV AH, 4CH
INT 21H
CODE ENDS
END START
连线图暂略
实验七
模/数(A/D)转换器
编写程序,从ADC0809通道采集电位器0~5V的直流电压,调节电位器,以改变模拟电压值,屏幕上不断地显示当前电压值A/D转换结果(用16进制数表示)
;电源接Y3(298H~29FH),IN0接电位器直流信号0~+5V.
DATA SEGMENT
DATA ENDS
CODE SEGMENT
ASSUME DS:DATA,CS:CODE
START:
MOV AX,DATA
MOV DS,AX
BEG:
MOV DX,298H
OUT DX,AL ;启动端口,无所谓AL里面的值
MOV CX,0FFH ;进行一个长延时DELAY
LL:LOOP LL
MOV DX,298H
IN AL,DX ;读取端口的值到AL
MOV BL,AL ;获取AL高四位,并存入低四位
SHR BL,4 ;SHR(右移)指令使目的操作数逻辑右移一位,最高位用 0 填充
;最低位复制到进位标志位(CF),而进位标志位中原来的数值被丢弃
MOV DL,BL ;把高四位存DL
CALL DISPLAY ;调用子函数显示
MOV BL,AL ;同理低四位
AND BL,0FH ;0000 1111将高四位清零,保留低四位
MOV DL,BL ;把低四位存DL
CALL DISPLAY ;调用子函数显示
MOV DL,0DH ;将回车的ASCII码存入DL
MOV AH,02H ;输出回车
INT 21H
MOV DL,0AH ;将换行的ASCII码存入DL
MOV AH,02H ;输出换行
INT 21H
MOV AH,01H ;用来查询键盘缓冲区,对键盘扫描但不等待,并设置ZF标志。
INT 16H ;AL中存放的是输入的ASCII码,AH中存放输入字符的扩展码。
;若有按键操作(即键盘缓冲区不空),则ZF=0,若无键按下,则标志位ZF=1。
JZ BEG ;无按键按下则持续执行扫描,有则退出
EXIT:
MOV AH,4CH
INT 21H
MOV AH,01H ;输入的字符就被存储在AL中
INT 21H
DISPLAY PROC
CMP DL,9 ;将数字值转换为对应十六进制字符的ASCII码值
JBE ADD30
ADD DL,07H
ADD30:
ADD DL,30H
MOV AH,02H ;单字符输出
INT 21H
RET
DISPLAY ENDP
CODE ENDS
END START
连线图暂略