实验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 未使用
posted @ 2021-12-12 11:29  chhh312  阅读(112)  评论(3)    收藏  举报