实验4 8086标志寄存器及中断

实验4

task 1

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

add 指令对 零标志位ZF(Zero Flag) 位有影响,对进位标志位CF(Carry Flag)也有影响。

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

inc指令只会对零标志位ZF(Zero Flag) 位产生影响, 对进位标志位CF(Carry Flag)不会产生影响。

使用任意文本编辑器,录入8086汇编源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 si, 2、add di, 2指令会对进位标志位CF产生影响,导致影响最后结果,而原文的inc指令不会影响CF的值。但是在此题中没有涉及到影响。
② 在debug中调试,观察数据段中做128位加之前和加之后,数据段的值的变化。

前:实验4 8086标志寄存器及中断

 后:

实验4 8086标志寄存器及中断

 task2

使用任意文本编辑器,录入8086汇编源码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#),观察结果。

实验4 8086标志寄存器及中断

 

结合运行结果,理解代码并回答问题:
① 汇编指令代码line11-18,实现的功能是:

读入一个字符,判断输入字符是否等于 #,若不等于则存入DS偏移地址为si的位置, si 计数,并继续读入;若等于#,则条件指令je,跳转到标记next处。

② 汇编指令代码line20-22,实现的功能是?

输出换行符(ASCII码中换行符即为0AH),在下一行开始输出字符串。

③汇编指令代码line24-30,实现的功能是?

将读入字符串长度,使用 loop 输出先前数据段中的字符串,从而实现记录输入语句的功能。

说明:task2.asm中用到的两个DOS系统功能调用:     DOS系统功能调用int 21h的1号子功能     功能:从键盘上输入单个字符     入口参数:(ah) = 1     出口参数: (al)存放输入字符的ASCⅡ码     即:
1 mov ah, 1 
2 int 21h     ; (al) <-- 输入字符的ascⅡ码
    DOS系统功能调用int 21h的2号子功能     功能:输出单个字符到屏幕上     入口参数:(ah) = 2, (dl) = 待输出的字符或其ascⅡ码     出口参数:无     即:
1 mov ah, 2 
2 mov dl, ×× ; ××是待输出的字符,或,其ascⅡ码 
3 int 21h

3. 实验任务 3

  针对8086CPU,已知逻辑段定义如下:
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 
 3 data segment
 4     x dw 91, 792, 8536, 65521, 2021
 5     len equ $ - x
 6 data ends
 7 
 8 code segment
 9 
10 printNumber:
11     push bx
12     push di
13     push cx
14     mov cx,0  ; 计数器,控制输出循环次数
15     mov di,0
16 s1:mov dx,0
17     mov bx,10
18     div bx  ; 除数(十进制),每次除以10得到单独数位上的数字
19     or dl,30h
20     push dx ;得到余数进栈
21     inc di
22     cmp ax,0 ; 被除数为0时结束计算,跳出循环
23     jne s1
24     mov cx,di
25 s2:pop dx
26     mov ah,2
27     int 21h
28     loop s2
29 
30     pop cx
31     pop di
32     pop bx
33     ret  
34       
35 printSpace:
36     mov ah,2
37      mov dl,20h ;转为ASCII值打印
38      int 21h
39      ret
40 
41 start: 
42     mov ax, data
43     mov ds, ax
44 
45     mov cx, len
46     mov di, offset x
47 s:  mov ax, [di]
48     call printNumber
49     call printSpace
50     add di, 2
51     sub cx, 1
52     loop s
53 
54     mov ax, 4c00h
55     int 21h
56 
57 code ends
58 
59 end main

 

 运行结果: 实验4 8086标志寄存器及中断

 

4. 实验任务4

  针对8086CPU,已知逻辑段定义如下:
1 data segment 
2     str db "assembly language, it's not difficult but tedious" 
3     len equ $ - str 
4 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 ax,data
10     mov ds,ax
11      
12     mov cx,len
13     mov si,offset str
14 s1:
15     call strupr
16     inc si
17     loop s1
18     
19     mov ah,4ch
20     int 21h
21     
22 strupr:
23     mov al,[si]
24     cmp al,'a'
25     jb  s2    ; jump below 小于“a”
26     cmp al,'z'
27     ja s2    ; jump above 大于“z”
28     and byte ptr [si],11011111b
29 s2:
30     ret
31     
32 code ends
33 end start

测试结果:

实验4 8086标志寄存器及中断

 

5. 实验任务5

  使用任意文本编辑器,录入8086汇编源码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,观察结果。输入其他字符,观察结果。结合运行结果和注释,理解代码实现的功能。     说明:task5.asm中,使用用到的DOS系统功能调用和BIOS中断例程     DOS系统功能调用int 21h的1号子功能     功能:从键盘上输入单个字符     入口参数:(ah) = 1     出口参数: (al)存放输入字符的ASCⅡ码     即:
1 mov ah, 1 
2 int 21h     ; (al) <-- 输入字符的ascⅡ码
    DOS系统功能调用int 21h的9号子功能     功能:显示字符串     入口参数:(ah) = 9,(ds:dx) = 字符串的首地址的段地址和偏移地址     出口参数: 无     其它要求:字符串必须以$结束     即:
1 mov ah, 9 
2 mov ds, ××     ; ××是待输出字符串所在段的段地址 
3 mov dx, ××     ; ××是待输出字符串第一个字符的偏移地址 
4 int 21h
    BIOS中断例程int 10h的2号子功能     功能:设置光标位置     入口参数:(ah) = 2, (bh) = 页号(默认取0), (dh) = 行号, (dl) = 列号     出口参数:无     即:
1 mov ah, 2 
2 mov bh, ××     ; ××是页号 
3 mov dh, ×× 
4 mov dl, ××      ; ××是列号 
5 int 10h
实验:输入“7”,观察结果 ,发现屏幕上输出“yes”字符串; 实验4 8086标志寄存器及中断

输入其他字符,如“1”、“2”,观察都只能得到屏幕上输出的字符串“no”:

实验4 8086标志寄存器及中断

 实验4 8086标志寄存器及中断

 分析源码,得到task5的功能为:分析输入的字符,如果为“7”,则在屏幕上输出“yes”字符串;如果不为“7”而是其他任何数字,都只能得到屏幕上输出字符串“no”。

 

实验6

实验任务1、2、3、5中使用了不少系统提供的中断例程。本实验任务中,要求自行实现一个42号软中断例程,使得通过 int 42 或 int 2ah 软中断调用,实现在屏幕最下方中间以黑底绿字打印"welcome to 2049!"。  

 

 1 ; task6_1.asm
 2 assume cs:code
 3 
 4 code segment
 5 start:
 6     ; 42 interrupt routine install code
 7     mov ax, cs
 8     mov ds, ax
 9     mov si, offset int42  ; set ds:si
10 
11     mov ax, 0
12     mov es, ax
13     mov di, 200h        ; set es:di
14 
15     mov cx, offset int42_end - offset int42
16     cld
17     rep movsb
18 
19     ; set IVT(Interrupt Vector Table)
20     mov ax, 0
21     mov es, ax
22     mov word ptr es:[42*4], 200h
23     mov word ptr es:[42*4+2], 0
24 
25     mov ah, 4ch
26     int 21h
27 
28 int42:
29     jmp short int42_start
30     str db "welcome to 2049!"
31     len equ $ - str
32 
33     ; display string "welcome to 2049!"
34 int42_start:
35     mov ax, cs
36     mov ds, ax
37     mov si, 202h
38 
39     mov ax, 0b800h
40     mov es, ax
41     mov di, 24*160 + 32*2
42 
43     mov cx, len
44 s:  mov al, [si]
45     mov es:[di], al
46     mov byte ptr es:[di+1], 2
47     inc si
48     add di, 2
49     loop s
50 
51     iret
52 int42_end:
53    nop
54 code ends
55 end start

 

 1 ; task6_2.asm
 2 assume cs:code
 3 
 4 code segment
 5 start:
 6     int 42
 7 
 8     mov ah, 4ch
 9     int 21h
10 code ends
11 end start

运行结果:输出“welcom to 2049!”

实验4 8086标志寄存器及中断

 程序功能:实现软中断:软中断是由程序中的int指令引起的。如果设置了中断程序,则必须将其添加到中断向量表中,即程序的输入地址。如果在程序执行过程中int指令导致中断,CPU将接收中断号,获得中断段条目的段地址和偏移地址,继续中断程序。

上一篇:32位x86处理器架构


下一篇:实验4 8086标志寄存器及中断