实验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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· 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工具