实验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 @   kanokksk  阅读(202)  评论(3编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示