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

实验任务1

验证性实验:有些汇编指令会影响到标志寄存器中的一个或多个状态标志位。 在debug环境中,分别实践、观察:

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

 

 

 从结果上来看,add指令对ZF与CF有影响。

执行mov al,ff al中值不为0,ZF标记NZ(0),NC标记NC(0),

执行add al,1 即ff+1=100,而al中存放00,此时al为0,ZF标记ZR(1)表示al为0,CF标记CY(1)表示最高位产生进位

 

 

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

 

从结果上看,inc指令只影响了ZF,未影响CF。

 

使用任意文本编辑器,录入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

对于本题的源码,可以。

inc与add指令的区别在于inc不会影响CF,而add会,CF记录的是最高位的进位。

本题数据较少,对于si与di(两个16位寄存器)不会产生最高位的进位,从而不会影响到adc指令中CF的值,

所以可以替换,但数据多了就只能使用inc指令避免对CF的影响。

 

② 在debug中调试,观察数据段中做128位加之前,和,加之后,数据段的值的变化。给出调试观察截图。

已替换add指令,加之前数据段截图:

 

 

 加之后数据段截图:

 

初始的inc指令,加之前数据段截图:

 

 

 加之后数据段截图:

 

 

 前后的数据段数据相等,可以证明问题1的部分结论,读者可以自行验证数据过多的情况。

 

实验任务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。

说明:task2.asm中用到的两个DOS系统功能调用:

 

运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运 行结果,理解代码并回答问题:

运行测试截图:

① 汇编指令代码line11-18,实现的功能是?

保存键盘上输入的字符至数据段,识别到#号跳转至next标号的代码块。

 

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

实现换行功能。

 

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

输出数据段中的数据到屏幕上

 

实验任务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 stack segment
 9     dw 16 dup(0)
10 stack ends
11 
12 code segment
13 start:  
14     mov ax,data
15     mov ds,ax
16     mov ax,stack
17     mov ss,ax
18     mov sp,16
19     mov si,offset x
20     mov cx,len
21     mov di,10
22 
23 s:
24     mov ax,[si]
25     mov sp,16
26     call printNumber
27 s2:
28     ;循环输出
29     mov ah,2
30     pop dx
31     or dl,30h
32     int 21h
33     cmp sp,14
34     je s3
35     jmp s2
36 
37 s3:
38     call printSpace
39     jmp next
40 
41 next:
42     add si,2
43     sub cx,2
44     jcxz over
45     jmp s
46    
47 over:
48     mov ah, 4ch
49     int 21h
50 
51 printNumber:
52     mov dx,0
53     div di
54     push dx;余数入栈
55     cmp ax,0
56     je s2
57     jmp printNumber
58     ret
59 
60 ;打印空格
61 printSpace:
62     mov ah,2
63     mov dl,' '
64     int 21h
65     ret
66 
67 code ends
68 end start

运行截图:

 

实验任务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 
 3 data segment
 4     str db "assembly language, it's not difficult but tedious"
 5     len equ $ - str
 6 data ends
 7 
 8 code segment
 9 start:  
10     mov ax,data
11     mov ds,ax
12     mov si,offset str
13     mov cx,len
14 
15 s:
16     call strupr
17     inc si
18     loop s
19     mov ah, 4ch
20     int 21h
21 ;字母小写转为大写
22 ;入口参数  ds:si  字符串长度  cx
23 strupr:
24     mov al,[si]
25     cmp al,61h
26     jnb s1
27     jb s2
28 s1:
29     sub al,20h
30     ;and al,00dfh
31     mov ds:[si],al
32     ret
33 s2:
34     ret
35 code ends
36 end start

程序退出前,数据段截图:

 

程序退出后,数据段截图:

 

 

本题只需知道a的ASCii码为61h,大写字母前加个判断条件即可。

 

实验任务5

使用任意文本编辑器,录入8086汇编源码task5.asm。

task5.asm

 1 assume cs:code, ds:data
 2 data segment
 3 str1 db "yes", '$'
 4 str2 db "no", '$'
 5 data ends
 6 code segment
 7 start:
 8 mov ax, data
 9 mov ds, ax
10 mov ah, 1
11 int 21h ; 从键盘输入字符
12 mov ah, 2
13 mov bh, 0
14 mov dh, 24 ; 设置光标位置在第24行
15 mov dl, 70 ; 设置光标位置在第70列
16 int 10h ; 设置光标位置
17 cmp al, '7'
18 je s1
19 mov ah, 9
20 mov dx, offset str2
21 int 21h ; 显示标号str2处的字符串
22 jmp over
23 s1: mov ah, 9
24 mov dx, offset str1
25 int 21h ; 显示标号str1处的字符串
26 over:
27 mov ah, 4ch
28 int 21h
29 code ends
30 end start

对源程序task5.asm进行汇编、链接,得到可执行文件task5.exe。

运行程序,输入7,观察结果。输入其他字符,观察结果。结合运行结果和注释,理解代码实现的功能。

说明:task5.asm中,使用用到的DOS系统功能调用和BIOS中断例程

 

 

 

 输入7运行结果截图:

 

输入其他字符,运行结果截图:

 

程序的功能:

首先,给出的源码中第32行的注释有误,应为——显示标号str1处的字符串(已更正)。

其次,程序的功能为:检测输入的字符是否为7,是,在24行70列输出yes;否,在24行70列输出no。

 

实验任务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。

两个程序正确编写、汇编、链接,运行后,预期结果如下:

 

对于已提供的源码,做了一定的修改

task61.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     ; 设置中断向量表
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 
30     ; 输出设置的字符串
31 int42_start:
32     push ax
33     push bx
34     push es
35     push si
36 
37     mov ax, 0b800h
38     mov es, ax
39     mov di, 24*160 + 32*2    ;底部中间显示
40 
41 s:  mov al, [si]
42     mov es:[di], al
43     mov byte ptr es:[di+1], 2    ;设置绿色
44     inc si
45     add di, 2
46     loop s
47     
48     pop si
49     pop es
50     pop bx
51     pop ax
52     iret
53 int42_end:
54    nop
55 code ends
56 end start

task62.asm

 1 assume cs:code
 2 
 3 data segment
 4     str db "welcome to 2049!"
 5     len equ $ - str
 6 data ends
 7 
 8 code segment
 9 start:
10     mov ax,data
11     mov ds,ax
12     mov si,offset str
13     mov cx,len
14     int 42
15 
16     mov ah, 4ch
17     int 21h
18 code ends
19 end start

修改部分:字符串不需要在int42例程中定义,在需要调用的程序中定义,设置ds:si为数据段地址,cx为字符串长度即可。

 

通过此项实现任务,你对中断、软中断的理解

 

中断、软中断其实与call十分类似,都是事先定义好的程序然后在其他地方调用,区别在于中断、软中断需要写在一个独立的文件中,调用前需要安装该例程,

而call调用的子程序需要写在调用者所在的文件中,即同一个文件

 

自己选一个未被使用的中断码,实现一个中断例程,并调用测试。给出源码和运行测试截图。(选做 *)

8086一共提供了256个中断,中断码为0~255,其中,有些保留作为系统用,有些未使用。可以自行挑选一个未被使用的中断码,尝试自己编写中断例程。

28H ~ 2EH DOS保留用(实验任务6中,使用的是42号中断码,即2AH)

30H ~ 3FH DOS保留用

60H ~ 6FH 用户保留

F1 ~ FFH 未使用

 

使用了F1,即241号中断码

int241功能:在屏幕底部连续打印10个al中的字符,字体绿色

test1.asm

 1 assume cs:code
 2 
 3 code segment
 4 start:
 5     ; 241 interrupt routine install code
 6     mov ax, cs
 7     mov ds, ax
 8     mov si, offset int241  ; set ds:si
 9 
10     mov ax, 0
11     mov es, ax
12     mov di, 200h        ; set es:di
13 
14     mov cx, offset int241_end - offset int241
15     cld        ;设置传输方向为正
16     rep movsb
17 
18     ; 设置中断向量表
19     mov ax, 0
20     mov es, ax
21     mov word ptr es:[241*4], 200h
22     mov word ptr es:[241*4+2], 0
23 
24     mov ah, 4ch
25     int 21h
26  
27 int241: 
28     jmp short int241_start
29 
30     ; 在屏幕底部输出10个相同字符,参数al
31 int241_start:
32     push ax
33     push bx
34     push cx
35     push es
36     push si
37 
38     mov cx,10
39     mov bx,0b800h
40     mov es,bx
41     mov si,24*160
42 s:
43     mov es:[si],al
44     mov byte ptr es:[si+1],2
45     add si,2
46     loop s
47 
48     pop si
49     pop es
50     pop cx
51     pop bx
52     pop ax
53     iret
54 int241_end:
55    nop
56 code ends
57 end start

test2.asm

 1 assume cs:code
 2 
 3 code segment
 4 start:   
 5     mov al,'a'
 6     int 241
 7     mov ax,4c00h
 8     int 21h
 9 
10 code ends
11 end start

 

 

实验总结

dos识别不了过长文件名的asm

 

posted @ 2021-12-15 22:13  kanokksk  阅读(233)  评论(3)    收藏  举报