实验4 8086标志寄存器及中断
1.实验内容1
验证性实验:有些汇编指令会影响到标志寄存器中的一个或多个状态标志位。
在debug环境中,分别实践、观察:
① add指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响
有影响

② inc指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?
没有影响

使用任意文本编辑器,录入8086汇编源码task1.asm。
task1.asm
1 assume cs:code, ds:data 2 3 data segment 4 x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h 5 y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h 6 data ends 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov si, offset x 12 mov di, offset y 13 call add128 14 15 mov ah, 4ch 16 int 21h 17 18 add128: 19 push ax 20 push cx 21 push si 22 push di 23 24 sub ax, ax 25 26 mov cx, 8 27 s: mov ax, [si] 28 adc ax, [di] 29 mov [si], ax 30 31 inc si 32 inc si 33 inc di 34 inc di 35 loop s 36 37 pop di 38 pop si 39 pop cx 40 pop ax 41 ret 42 code ends 43 end start
其中:
add128是子程序子程序。
功能:实现计算两位128位数的加法
入口参数:
ds:si指向存储第一个128位数的存储空间(因为一个数128位,需要8个字节的连续空间)
ds:di指向存储第二个128位数的存储空间
出口参数:
加运算后的结果,保存在第一个数的存储空间中,即:ds:si开始的连续8个字节空间
在代码段种,调用add128实现对标号x和y处存储的两个128位数据相加,结果保存在x处的连续128个字
节中。
对程序进行汇编、链接,得到可执行程序task1.exe。在debug中调试程序,并回答问题。
① line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
1 add si,2 2 add di,2
可以,对实验结果不会产生影响,但是使用add会影响标志位,而inc不会影响标志位。
② 在debug中调试,观察数据段中做128位加之前,和,加之后,数据段的值的变化。
做128位加法之前数据段的值:

做128位加法之后数据段的值:
2. 实验任务2
使用任意文本编辑器,录入8086汇编源码task2.asm。
task2.asm
1 assume cs:code, ds:data 2 data segment 3 str db 80 dup(?) 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 mov si, 0 11 s1: 12 mov ah, 1 13 int 21h 14 mov [si], al 15 cmp al, '#' 16 je next 17 inc si 18 jmp s1 19 next: 20 mov ah, 2 21 mov dl, 0ah 22 int 21h 23 24 mov cx, si 25 mov si, 0 26 s2: mov ah, 2 27 mov dl, [si] 28 int 21h 29 inc si 30 loop s2 31 32 mov ah, 4ch 33 int 21h 34 code ends 35 end start
对源程序task2.asm进行汇编、链接,得到可执行文件task2.exe。
运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运行结果,理解代码并回答问题:
① 汇编指令代码line11-18,实现的功能是?
首先,调用int 21h的一号子功能,将键盘上输入的单个字符存放至al中,使用cmp命令判断输入的字符时是否与“#”相同,如果相同则跳转至 next ,如果不是继续获取下一个字符。
② 汇编指令代码line20-22,实现的功能是?
实现的功能为输出一个换行符。
③ 汇编指令代码line24-30,实现的功能是?
实现的功能为清空寄存器,并输出所有从键盘获取的内容
说明:task2.asm中用到的两个DOS系统功能调用:
DOS系统功能调用int 21h的1号子功能
功能:从键盘上输入单个字符
入口参数:(ah) = 1
出口参数: (al)存放输入字符的ASCⅡ码
即:
1 mov ah,1 2 int 21h
DOS系统功能调用int 21h的2号子功能
功能:输出单个字符到屏幕上
入口参数:(ah) = 2, (dl) = 待输出的字符或其ascⅡ码
出口参数:无
即:
1 mov ah, 2 2 mov dl, xx ;xx是待输出的字符或其ascII码 3 int 21h
3. 实验任务3
1 data segment 2 x dw 91, 792, 8536, 65521, 2021 3 len equ $ - x 4 data ends
编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。
要求:
编写子程序printNumber
功能:以十进制形式输出一个任意位数的整数(整数范围0 ~ 65535)
入口参数:寄存器ax(待输出的数据 --> ax)
出口参数:无
编写子程序printSpace
功能:打印一个空格
入口参数:无
出口参数:无
在主体代码中,综合应用寻址方式和循环,调用printNumber和printSpace, 实现题目要求。
1 assume cs:code, ds:data 2 data segment 3 x dw 91,792,8536,65521,2021 4 len equ $ - x 5 data ends 6 7 stack segment 8 db 16 dup(0) 9 stack ends 10 11 code segment 12 start: 13 mov ax,data 14 mov ds,ax 15 16 mov cx,5 17 mov si,0 18 s: 19 mov ax,ds:[si] 20 call printNumber 21 call printSpace 22 inc si 23 inc si 24 loop s 25 26 mov ah,4ch 27 int 21h 28 29 printNumber: 30 mov bx,10 ;数字为32位,多次除以10取余数 31 mov dx,0 32 mov di,0 ;存储取余数次数 33 push cx 34 35 s1: 36 div bx ;除法运算 被除数为32位,ax存储商,dx存储余数 被除数为16位,al存储商,ah存储余数 37 push dx ;余数入栈 38 inc di ;取余数的次数加一 39 mov dx,0 40 cmp ax,0 ;商为0,已全部入栈 ,跳转s2 41 je next 42 jmp s1 ;如果没有进行跳转,继续循环s1 43 44 next: 45 mov ah,2 46 mov cx,di 47 48 s2: 49 pop dx ;数据逐个弹出 50 or dl,30h ;转化为ASCII码 51 int 21h 52 loop s2 53 54 pop cx 55 ret ;结束子程序 56 57 printSpace: 58 mov dl,' ' 59 mov ah,2 60 int 21h 61 ret 62 63 code ends 64 end start
结果截图:

提示:
题目限定了数据范围是0 ~ 65535, 可以借助32÷16位的除法,无需考虑除法溢出问题。具体地:
1. 被除数 -> dx:ax,由于数据不超过65535,所以,每次寻址取数-> ax后,在子程序printNumber中做
除法时,dx设置为0即可。
2. 除以10,得到余数后,入栈并计数。重复这一过程,直至商为0。然后,循环出栈,并借助int 21h中的2号子功能,实现输出。
3. 注意事项:① 数字和数字字符的区别,及,必要转换;② 寄存器使用冲突问题,可借助栈解决。具体
地,如内容不熟悉,请复习第10章。
4. 实验任务4
针对8086CPU,已知逻辑段定义如下:
1 assume cs:code,ds:data 2 data segment 3 str db "assembly language, it's not difficult but tedious" 4 len equ $ - str 5 data ends
编写8086汇编源程序task4.asm,将data段中字符串里的小写字符转换成大写。
要求:
编写子程序strupr
功能:将包含任意字符的字符串中的小写字母变成大写
入口参数
(ds:si ) 字符串首地址的段地址和偏移地址分别送至ds和si
(cx) 字符串的长度
出口参数:无
在主体代码中,设置入口参数,调用strupr, 实现题目要求。
1 assume cs:code,ds:data 2 data segment 3 str db "assembly language, it's not difficult but tedious" 4 len equ $ - str 5 data ends 6 7 code segment 8 start: 9 mov cx,len 10 mov ax,data 11 mov ds,ax 12 mov si, 0 13 call strupr 14 15 mov ah,4ch 16 int 21h 17 strupr: ;判断字符是否是小写字符,如果是将其转化为大写字母 18 mov al,ds:[si]; 19 cmp al, 97 ;小写字母的ASCII码在97-122 20 jb next ;如果小于97则说明不是小写字符,跳转至next 21 cmp al,122 22 ja next ;如果大于122则说明不是小写字符,跳转至next 23 and al, 0dfh ;小写字符转换成大写字符 24 mov ds:[si],al 25 next: 26 inc si ;指向下一个字符 27 loop strupr 28 ret 29 30 code ends 31 end start 32
运行前观察存储内容:
运行结果之后:

5. 实验任务5
使用任意文本编辑器,录入8086汇编源码task5.asm。
task5.asm
1 assume cs:code, ds:data 2 3 data segment 4 str1 db "yes", '$' 5 str2 db "no", '$' 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 13 mov ah, 1 14 int 21h 15 16 mov ah, 2 17 mov bh, 0 18 mov dh, 24 19 mov dl, 70 20 int 10h 21 22 cmp al, '7' 23 je s1 24 mov ah, 9 25 mov dx, offset str2 26 int 21h 27 28 jmp over 29 30 s1: mov ah, 9 31 mov dx, offset str1 32 int 21h 33 over: 34 mov ah, 4ch 35 int 21h 36 code ends 37 end start
对源程序task5.asm进行汇编、链接,得到可执行文件task5.exe。
运行程序,输入7,观察结果。输入其他字符,观察结果。结合运行结果和注释,理解代码实现的功能。

该程序的功能为判断输入的字符是否为7,如果是则在行尾输入yes,如果不是,则输出no
说明:task5.asm中,使用用到的DOS系统功能调用和BIOS中断例程
DOS系统功能调用int 21h的1号子功能
功能:从键盘上输入单个字符
入口参数:(ah) = 1
出口参数: (al)存放输入字符的ASCⅡ码
即:
1 mov ah, 1 2 int 21h ;(a1) <--输入字符的ASCII
DOS系统功能调用int 21h的9号子功能
功能:显示字符串
入口参数:(ah) = 9,(ds:dx) = 字符串的首地址的段地址和偏移地址
出口参数: 无
其它要求:字符串必须以$结束
即:
1 mov ah, 9 2 mov ds, xx ; xx是待输出字符串所在段的段地址 3 mov dx, xx ; xx是待输出字符串第一个字符的偏移地址 4 int 21h
BIOS中断例程int 10h的2号子功能
功能:设置光标位置
入口参数:(ah) = 2, (bh) = 页号(默认取0), (dh) = 行号, (dl) = 列号
出口参数:无
即:
1 mov ah, 2 2 mov bh, xx ; xx是页号 3 mov dh, xx 4 mov dl, xx ; xx是列号 5 int 10h
6. 实验任务6
实验任务1、2、3、5中使用了不少系统提供的中断例程。本实验任务中,要求自行实现一个42号软中断
例程,使得通过 int 42 或 int 2ah 软中断调用,实现在屏幕最下方中间以黑底绿字打印"welcome to 2049!"。
建议配合教材第12章学习理解并实践。
task6_1.asm
1 assume cs:code 2 3 code segment 4 start: 5 ; 42 interrupt routine install code 6 mov ax, cs 7 mov ds, ax 8 mov si, offset int42 ; set ds:si 9 10 mov ax, 0 11 mov es, ax 12 mov di, 200h ; set es:di 13 14 mov cx, offset int42_end - offset int42 15 cld 16 rep movsb 17 18 ; set IVT(Interrupt Vector Table) 19 mov ax, 0 20 mov es, ax 21 mov word ptr es:[42*4], 200h 22 mov word ptr es:[42*4+2], 0 23 24 mov ah, 4ch 25 int 21h 26 27 int42: 28 jmp short int42_start 29 str db "welcome to 2049!" 30 len equ $ - str 31 32 ; display string "welcome to 2049!" 33 int42_start: 34 mov ax, cs 35 mov ds, ax 36 mov si, 202h 37 38 mov ax, 0b800h 39 mov es, ax 40 mov di, 24*160 + 32*2 41 42 mov cx, len 43 s: mov al, [si] 44 mov es:[di], al 45 mov byte ptr es:[di+1], 2 46 inc si 47 add di, 2 48 loop s 49 50 iret 51 int42_end: 52 nop 53 code ends 54 end start
task6_2.asm
1 assume cs:code 2 3 code segment 4 start: 5 int 42 6 7 mov ah, 4ch 8 int 21h 9 code ends 10 end start
对汇编源程序task6_1.asm进行汇编、链接,得到可执行程序task6_1.exe。运行task6_1.exe,实现将
42号中断处理程序安装到0:200开始的连续内存空间,并设置中断向量表,使得将来通过 int 42 ,系统
可以跳转到中断处理程序。
对汇编源程序task6_2.asm进行汇编、链接,得到可执行程序task6_2.exe。运行task6_2.exe。
两个程序正确编写、汇编、链接,运行后,预期结果如下:
通过此项实现任务,你对中断、软中断的理解
自己选一个未被使用的中断码,实现一个中断例程,并调用测试。给出源码和运行测试截图。(选做*)
8086一共提供了256个中断,中断码为0~255,其中,有些保留作为系统用,有些未使用。可以自
行挑选一个未被使用的中断码,程时自己编写中断例程。
28H ~ 2EH DOS保留用(实验任务6中,使用的是42号中断码,即2AH)
30H ~ 3FH DOS保留用
60H ~ 6FH 用户保留
F1 ~ FFH 未使用

浙公网安备 33010602011771号