一、实验目的
1. 理解标志寄存器用途,理解常用标志位CF, ZF, OF, SF, TF, IF的用途和意义。
2. 理解条件转移指令je, jz, ja, jb, jg, jl等的跳转原理,掌握组合使用汇编指令cmp和条件转移指令实现 分支和循环的用法
3. 了解软中断指令的用法,体验和理解中断原理
4. 综合应用寻址方式和汇编指令完成简单应用编程
二、实验准备
复习教材「第10章 call和ret指令」、「第11章 标志寄存器」 学习教材「第12章 内中断 」、「第13章 int指令」
三、实验内容
1. 实验任务1
Add指令
由图可以看出add指令对标志寄存器中的零标志位ZF和进位标志位CF都有影响,图中ZF零标志位由NZ转变成了ZR,即从0变成了1,CF进位标志位从NC转变成了CY,即从0变成了1。
由于al中本身值为ff,再加1得100超过al的两位限制,所以1被舍弃,结果就是零,所以零标志位ZF置1。
Inc指令
由图可以看出inc指令对零标志位ZF有影响,因为计算出结果100,舍去1后结果是0,所以ZF从NZ变成了ZR,即从0变成1。而对进位标志位CF没有影响,依然是NC。
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
Task1.asm汇编链接后,task1.exe执行结果如下:
可以看到两个128位数相加后结果存放在x开始的连续16个字节中。
若将line31~line34的4条inc指令替换成如下
执行结果如下:
可以看到结果依然正确,并且存放在x开始的连续16个字节中。
这里我认为是可以替换的,因为add指令和inc指令对进位标志位的影响不同,当add指令计算完产生进位时会对CF产生影响,而inc则无论如何不会对CF产生影响,在本题中,si的范围是从0000到000f,di的范围是从0010到001f,二者都没有发生进位,所以add指令不会对CF产生影响,就不会影响最终的结果。
实验任务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 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.exe运行截图如下:
问题1:line11-18实现的功能是从键盘上读取字符并保存到data段str开始的位置,直到‘#’为止,如果读入了‘#’,就跳转到next开始的位置执行代码,否则继续读取字符。
问题2:line20-22实现的功能是输出一个换行符,因为换行符的ascii码是10,所以将0ah移入dl中,再输出。
问题3:line24-30实现的功能是将存放在数据段str开始的字符输出到屏幕上。
整个程序的功能是从键盘上读取字符直到‘#’结束,并在下一行将读取的字符输出(不包括‘#’)。
实验任务3:
task3.asm代码如下:
1 assume cs:code, ds:data 2 data segment 3 x dw 91, 792, 8536, 65521, 2021 4 len equ $ - x 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov si, offset x 12 mov cx, 5 13 14 s: push cx 15 mov cx, 0 16 mov al, ds:[si] 17 mov ah, ds:[si + 1] 18 call printNumber 19 call printSpace 20 pop cx 21 loop s 22 23 mov ah, 4ch 24 int 21h 25 26 printNumber: 27 mov bx, 10 28 mov dx, 0 29 div bx 30 inc cx 31 push dx 32 cmp ax, 0 33 jne printNumber 34 35 s1: mov ah, 2 36 pop dx 37 or dl, 30h 38 int 21h 39 loop s1 40 inc si 41 inc si 42 ret 43 44 printSpace: 45 mov ah, 2 46 mov dl, ' ' 47 int 21h 48 ret 49 50 code ends 51 end start
task3.exe运行截图如下:
实验任务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 si, offset str 12 mov cx, len 13 14 s: mov al, ds:[si] 15 call strupr 16 inc si 17 loop s 18 19 mov ah, 4ch 20 int 21h 21 strupr: cmp al, 97 22 jb s1 23 cmp al, 122 24 ja s1 25 and al, 11011111B 26 jmp s1 27 28 s1: mov ah, 2 29 mov dl, al 30 int 21h 31 ret 32 33 34 35 code ends 36 end start
task4.exe运行截图如下:
执行之前数据段内容如下:
执行后截图如下:
实验任务5:
该程序功能是判断从键盘输入的字符是否是7,若是则在右下角打印yes,不是则打印no。
实验任务6:
下为使用255中断码:
task6_3代码:
1 assume cs:code 2 3 code segment 4 start: 5 ; 255 interrupt routine install code 6 mov ax, cs 7 mov ds, ax 8 mov si, offset int255 ; set ds:si 9 10 mov ax, 0 11 mov es, ax 12 mov di, 200h ; set es:di 13 14 mov cx, offset int255_end - offset int255 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:[255*4], 200h 22 mov word ptr es:[255*4+2], 0 23 24 mov ah, 4ch 25 int 21h 26 27 int255: 28 jmp short int255_start 29 str db "welcome to 201983290205!" 30 len equ $ - str 31 32 ; display string "welcome to 201983290205!" 33 int255_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, 22*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 int255_end: 52 nop 53 code ends 54 end start
task6_4.asm代码:
1 assume cs:code 2 3 code segment 4 start: 5 int 255 6 7 mov ah, 4ch 8 int 21h 9 code ends 10 end start
运行截图如下:
我学习到关于中断的知识有如下:由于程序运行过程中会产生异常,CPU会自动识别出异常,并将它定位到异常向量表中的一个位置吗,通过异常向量表来实现对不同异常的处理。中断又分为软中断和硬中断,软中断是由程序执行的中断,硬中断是由硬件执行的中断。软中断执行后,硬件先复位,然后PC指向异常向量表中的第一个位置:0x00,然后执行跳转rest函数,通过swi触发软中断。
四、实验总结
通过本次实验我学习到了关于标志寄存器和一些跳转指令的知识,知道了如何在Dosbox里使用标志寄存器和跳转指令来达到自己的目的。也学习了关于中断和软中断相关的知识,了解了软中断在程序中是如何触发的,以及相关的汇编中默认和空闲的中断码等等,希望以后可以更深入地学习这一方面。