实验4 8086标志寄存器及中断
实验结论
1.实验任务1
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 ;ax置零 25 26 mov cx, 8 ;循环次数为8 27 s: mov ax, [si] ;赋x里的值 28 adc ax, [di] ;加上[di]×16+CF 29 mov [si], ax ;将x里的值和y里的值相加并存到x里 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
回答问题 line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
add si, 2 add di, 2
答:能。因为adc命令的功能是 ax 加上 [di]×16+CF ,si和di一共循环8次,每次加二,最终结果不会产生进位,因此CF的值不会改变,所以可以替换。
在debug中调试,观察数据段中做128位加之前和加之后,数据段的值的变化。给出调试观察截图。
答:通过u命令查看数据段地址,根据数据段地址查看相加之前数据段的值,截图如下:

运行程序至退出前,再次查看数据段的值,截图如下:

可以看到实现了x和y的8位数据相加并存到x处的空间内。
2.实验任务2
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 ;相等则跳到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 ;s2输出str里的符号 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
运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运行结果,理解代码并回答问题:
运行截图为:

① 汇编指令代码line11-18,实现的功能是?
答:line11-18的功能是实现字符串的输入,直到遇到字符 ‘#’ 停止。
② 汇编指令代码line20-22,实现的功能是?
答:0aH是换行符的ASCII码,因此line20-22实现的是换行功能。
③ 汇编指令代码line24-30,实现的功能是?
答:si表示前面输入字符的个数,将其付给cx作为循环次数,因此line24-30的功能是输出x空间内的字符,即输出前面输入的字符串。
3.实验任务3
task3.asm源码为:
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 db 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 es,ax 18 mov si,offset x ;x的初始偏移量:0 19 mov cx,5 ;从符号x开始的连续字节数据项个数,即循环次数 20 21 s: 22 call s1 23 add si,2 24 call s5 25 loop s 26 27 mov ah, 4ch 28 int 21h 29 30 s1: ;printNumber子程序 31 push cx 32 mov ax,ds:[si] 33 mov dx,0 34 mov bx,10 35 mov cx,0 36 37 s2: 38 div bx ;除数为16为,被除数为32位,高位放在dx, 低位放在ax,结果ax保存商, dx保存余数 39 mov es:[di],dx 40 inc di 41 inc cx 42 cmp ax,0 43 je s3 ;商为0则跳到输出 44 mov dx,0 45 jmp s2 ;商不为0则继续 46 47 s3: 48 sub di,1 49 mov dx,es:[di] 50 or dl,30h ;数值变为对应ascii码 51 mov ah,2 52 int 21h 53 loop s3 54 55 pop cx 56 ret 57 58 s5: mov ah,2 ;printSpace子程序 59 mov dl,' ' 60 int 21h 61 ret 62 code ends 63 end start
运行截图如下:

4.实验任务4
task4.asm源码为:
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 mov cx,len 12 mov si,0 13 call strupr 14 15 mov ah, 4ch 16 int 21h 17 18 strupr: 19 mov al,[si] 20 cmp al,20h 21 je s1 ;如果是空格就跳过 22 cmp al,2ch 23 je s1 ;如果是逗号就跳过 24 cmp al,27h 25 je s1 ;如果是单引号就跳过 26 and al,0dfh ;都不是则转换为大写存入内存 27 s1: 28 mov [si],al 29 inc si 30 loop strupr 31 ret 32 33 code ends 34 end start
运行后查看调用strupr前的数据段:

调用strupr后再次查看:

发现已经成功将字符串里的小写字符转换成大写。
5.实验任务5
task5.asm源码为:
1 assume cs:code, ds:data 2 data segment 3 str1 db "yes", '$' 4 str2 db "no", '$' 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 12 mov ah, 1 13 int 21h ; 从键盘输入字符 14 15 mov ah, 2 16 mov bh, 0 17 mov dh, 24 ; 设置光标位置在第24行 18 mov dl, 70 ; 设置光标位置在第70列 19 int 10h ; 设置光标位置 20 21 cmp al, '7' 22 je s1 23 mov ah, 9 24 mov dx, offset str2 25 int 21h ; 显示标号str2处的字符串 26 27 jmp over 28 29 s1: mov ah, 9 30 mov dx, offset str1 31 int 21h ; 显示标号str2处的字符串 32 over: 33 mov ah, 4ch 34 int 21h 35 code ends 36 end start
运行task5.exe后输入7的结果为:

输入别的符号的结果为:

源程序task5.asm功能是:先从键盘读取用户输入的一个字符,接着判断是不是’7’ ,如果是则在第24行70列输出“yes”,否则在第24行70列输出“no”。
6.实验任务6
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 ;调用自己实现的42号软中断 6 7 mov ah, 4ch 8 int 21h 9 code ends 10 end start
运行两个程序的结果为:
中断分为硬中断和软中断。硬中断通常通过硬件如鼠标键盘来触发中断。
软中断是通过程序来实现中断,它可以使CPU暂停当前程序的执行,转而执行处理紧急事务,并在该事务处理完后能自动恢复执行原先程序的过程,实验6中就是通过int 42触发软中断立即转到输出字符串。
实验总结
通过本次实验,我对常用标志寄存器用途、条件转移指令以及软中断指令的用法有了进一步了解和掌握。
在实验中收获了以下知识点:
(1).inc指令对标志寄存器中的零标志位ZF不会有影响,而add指令有影响。
(2).当ah为1时,int 21h的功能是从键盘上输入单个字符存到al中;当ah为9时,int 21h的功能是显示字符串,且字符串必须以$结束。
(3).通过cmp命令和je命令的组合可以实现类似C语言中if语句的功能,在任务2,3,4,5中都有用到。

浙公网安备 33010602011771号