实验4 8086标志寄存器及中断
实验任务1
1.验证实验
① add指令对标志寄存器中的零标志位ZF(Zero Flag)、进位标志位CF(Carry Flag)是否有影响?

add指令会对标志位ZF和CF产生影响:ZF位从NZ变成了ZR,表示运算结果为0,CF位从NC变成了CY,表示运算中最高位向更高位产生了进位。
inc指令只会对ZF位产生影响, 对CF位不会产生影响:ZF位从NZ变为ZR,表示运算结果位0,CF位未发生变化。
2.使用任意文本编辑器,录入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 ;功能:实现计算两位128位数的加法 18 ;入口参数: 19 ;ds:si指向存储第一个128位数的存储空间(因为一个数128位,需要8个字节的连续空间) 20 ;ds:di指向存储第二个128位数的存储空间 21 ;出口参数: 22 ;加运算后的结果,保存在第一个数的存储空间中,即:ds:si开始的连续8个字节空间 23 add128: 24 push ax 25 push cx 26 push si 27 push di 28 29 sub ax, ax 30 31 mov cx, 8 32 s: mov ax, [si] 33 adc ax, [di] 34 mov [si], ax 35 36 inc si 37 inc si 38 inc di 39 inc di 40 loop s 41 42 pop di 43 pop si 44 pop cx 45 pop ax 46 ret 47 code ends 48 end start
回答问题:
① line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
add si, 2 add di, 2
inc不能换成add指令,add指令会影响CF标志位,而inc指令不会影响,而本题中大整数加法,所以进行加法运算时运用的是add指令,会用到CF标志位的数值,若使用了add si,2和add di,2指令, 则会对CF标志位产生影响,进而影响到adc指令的执行结果,最终影响到计算结果,所以不能换成add指令。
② 在debug中调试,观察数据段中做128位加之前,和,加之后,数据段的值的变化。
程序运行前:

程序运行后:

完成了128位二进制数的加法
实验任务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
运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结果。结合运行结果,理解代码并回答问题:

实验任务3
针对8086CPU,已知逻辑段定义如下:
data segment x dw 91, 792, 8536, 65521, 2021 len equ $ - x data ends
编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。
task3.asm
1 assume ds:data, cs:code 2 data segment 3 x dw 91, 792, 8536, 65521, 2021 4 len equ $ - x 5 y db 200 dup(?) ;为栈的使用开辟空间 6 leny equ $ - y 7 data ends 8 9 code segment 10 start: 11 mov ax, offset y 12 mov ss, ax 13 mov sp, leny ;设置栈顶 14 15 mov ax, data ;将x数据段放入ds:[si]中 16 mov ds, ax 17 mov si, 0 18 mov cx, 5 ;一共五个数, 所以循环5次 19 s2: 20 call printNumber 21 call printSpace 22 add si, 2 23 loop s2 24 25 mov ah, 4ch 26 int 21h 27 28 ;功能:以十进制形式输出一个任意位数的整数(整数范围0 ~ 65535) 29 ;入口参数:寄存器ax(待输出的数据 --> ax) 30 ;出口参数:无 31 printNumber: 32 push cx ;将外部循环s2的剩余次数压入栈中 33 mov ax, ds:[si] ;将被除数放入ax中 34 mov dx, 0 ;由于数值最大位65521, 小于8位16进制能表达的最大数6535, 所以被除数的高16位可以设置位0 35 mov bx, 10 ;将除数10放入bx中 36 mov cx, 0h ;cx寄存器用于计数 37 s1: 38 inc cx ;每做一次除法都进行一次计数 39 div bx ;除法操作, 由于除数是16位, 被除数就被解读为dx:ax, 余数在dx中, 商在ax中 40 or dx, 30h ;将余数转为相应的ASCII码 41 push dx ;将结果压入栈中 42 mov dx, 0 ;作用与33行的一样, 同时起到将余数清空为0的作用 43 cmp ax, 0 44 jne s1 45 s3: 46 pop dx ;将栈顶数据放入dx中 47 mov ah, 02h 48 int 21h ;使用int 21h指令输出 49 loop s3 ;循环输出, 次数为做除法的次数 50 pop cx ;将栈底的外部循环次数放入cx中 51 ret 52 53 ;功能:打印一个空格 54 ;入口参数:无 55 ;出口参数:无 56 printSpace: 57 mov dl, ' ' 58 mov ah, 02h 59 int 21h 60 ret 61 62 63 code ends 64 end start

实验任务4
针对8086CPU,已知逻辑段定义如下
data segment str db "assembly language, it's not difficult but tedious" len equ $ - str data ends
编写8086汇编源程序task4.asm,将data段中字符串里的小写字符转换成大写。
task4.asm
1 assume ds:data, cs:code 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 10 mov ax, data 11 mov ds, ax 12 mov si, offset str 13 14 mov cx, len 15 16 s1: 17 call strupr 18 inc si 19 loop s1 20 21 mov ah, 4ch 22 int 21h 23 24 ;功能:将包含任意字符的字符串中的小写字母变成大写 25 ;入口参数 26 ;(ds:si ) 字符串首地址的段地址和偏移地址分别送至ds和si 27 ;(cx) 字符串的长度 28 ;出口参数:无 29 strupr: 30 cmp byte ptr ds:[si], 96 31 jna s2 ;如果当前的字符小于等于96,则直接输出 32 sub byte ptr ds:[si], 32 ;否则转为大写字母 33 s2: 34 mov dx, ds:[si] 35 mov ah, 2 36 int 21h 37 ret 38 39 code ends 40 end start

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

如果输入的是7, 输出yes。如果输入的为非7字符, 则输出no
实验任务6
实验任务1、2、3、5中使用了不少系统提供的中断例程。本实验任务中,要求自行实现一个42号软中断例程,使得通过 int 42 或 int 2ah 软中断调用,实现在屏幕最下方中间以黑底绿字打印"welcome to 2049!"
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

浙公网安备 33010602011771号