汇编实验四
四、实验结论
1. 实验任务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 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
(2)回答问题:
①ine31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
![]()
答:不能,因为add指令影响进位标志位,若add si, 2或add di, 2 产生了进位,将改变128位加法原有的进位标志位,128加法结果将会错误
②在debug中调试,观察数据段中做128位加之前和加之后,数据段的值的变化。给出调试观察截图
加之前数据段(源数据):

加之后数据段:加运算后的结果,保存在第一个数的存储空间中,即:ds:si开始的连续8个字节空间

2. 实验任务2
(1) 程序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
(2)运行测试截图

(3)回答问题:运行程序,从键盘上输入一串字符,以#结束(比如,输入George Orwell, 1984#),观察结 果。结合运行结果,理解代码并回答问题:

① 汇编指令代码line11-18,实现的功能是?
接收输入的字符,送到ds中偏移地址从0开始的空间中,直到输入#跳转到 next
② 汇编指令代码line20-22,实现的功能是?
(如果输入是#)2号子功能:输出换行符
③ 汇编指令代码line24-30,实现的功能是?
调用2号子功能,将ds段中偏移地址从0开始的长为si的输出
3. 实验任务3

(1) task3.asm代码:
1 assume cs:code, ds:data, ss:stack 2 3 data segment 4 x dw 91, 792, 8536, 65521, 2021 ;没有超出65535,所以被除数高位dx为0 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, stack 15 mov ss, ax 16 mov sp, 16 17 mov ax, data 18 mov ds, ax 19 mov cx, len/2 20 mov si, 0 21 s: 22 mov ax, [si] ; 低16位 23 mov dx, 0 ;高16位 24 mov di, 0 ;计数 25 call printNumber 26 call printSpace 27 inc si ; 下一个数 28 inc si 29 loop s 30 31 mov ah, 4ch 32 int 21h 33 34 printNumber: 35 s1: 36 mov dx, 0 ;高16位始终置为0 37 mov bx, 10 ;除数(16位) 38 div bx ;(ax存商,dx存余数) 39 40 cmp ax, 0 ;将商和0比较 41 je s2 ;商等于0转s2 42 43 add dl, 30h ;商不等于0转s1继续除 44 push dx ;入栈保存余数 45 inc di ;计数 46 jmp s1 47 48 s2: 49 mov bx, cx ;保存cx 50 add dl, 30h ;余数入栈, 将数字转变为数字字符,因为‘0’的ASCII码为30H 51 push dx 52 inc di ;计数 53 mov cx, di ;栈中有多少个余数说明得循环几次 54 printys: 55 mov ah, 2 ;打印余数 56 pop dx ;将栈段中保存余数拿出来 57 int 21h 58 loop printys 59 60 mov cx, bx ;返回cx原来的值 61 ret 62 63 printSpace: 64 mov ah, 2 ;二号子功能 65 mov dl, ' ' 66 int 21h 67 ret 68 69 code ends 70 end start
(2)运行测试截图:

4. 实验任务4

(1) task4.asm代码
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 cx, len 13 mov si, 0 14 s1: 15 call letter 16 inc si 17 loop s1 18 19 mov ax, 4c00h 20 int 21h 21 22 letter: 23 cmp byte ptr [si], 'a' ;比a小不行 24 jb s2 25 cmp byte ptr [si], 'z' ;比z大也不行 26 ja s2 27 sub byte ptr [si], 32 28 s2: 29 ret 30 31 code ends 32 end start
(2)在debug中调试截图
call letter调用之前数据段的值:

call letter调用之后数据段的值:(变为大写)

5. 实验任务5
(1)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 ; 显示标号str2处的字符串 26 over: 27 mov ah, 4ch 28 int 21h 29 code ends 30 end start
(2)程序运行测试截图(输入7,以及输入其他字符,运行结果截图) 程序的功能是?
输入7:

输入其他字符:

功能:输入7则在指定位置打印yes,输入其他字符则在该位置打印no
6. 实验任务6
task6_1.asm:
1 assume cs:code 2 code segment 3 4 task6_2.asm 5 start: 6 ; 42 interrupt routine install code 7 mov ax, cs 8 mov ds, ax 9 mov si, offset int42 ; set ds:si 10 mov ax, 0 11 mov es, ax 12 mov di, 200h ; set es:di 13 mov cx, offset int42_end - offset int42 14 cld 15 rep movsb 16 ; set IVT(Interrupt Vector Table) 17 mov ax, 0 18 mov es, ax 19 mov word ptr es:[42*4], 200h 20 mov word ptr es:[42*4+2], 0 21 mov ah, 4ch 22 int 21h 23 int42: 24 jmp short int42_start 25 str db "welcome to 2049!" 26 len equ $ - str 27 ; display string "welcome to 2049!" 28 int42_start: 29 mov ax, cs 30 mov ds, ax 31 mov si, 202h 32 mov ax, 0b800h 33 mov es, ax 34 mov di, 24*160 + 32*2 35 mov cx, len 36 s: mov al, [si] 37 mov es:[di], al 38 mov byte ptr es:[di+1], 2 39 inc si 40 add di, 2 41 loop s 42 iret 43 int42_end: 44 nop 45 code ends 46 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
对汇编源程序task6_1.asm进行汇编、链接,得到可执行程序task6_1.exe。运行task6_1.exe,实现将 42号中断处理程序安装到0:200开始的连续内存空间,并设置中断向量表,使得将来通过 int 42 ,系统 可以跳转到中断处理程序。
运行结果:

实现在屏幕最下方中间以黑底绿字打印"welcome to 2049!"。
(1)通过此项实现任务,你对中断、软中断实现机制的理解
cpu收到中断信息后,转去执行该中断信息的处理程序。中断类型码用来定位中断处理程序,而中断类型码通过中断向量表找到相应的中断处理程序的入口地址(中断向量就是中断处理程序的入口地址)对于8086PC机,中断向量表指定存放在内存地址0处,0000:0000-0000:03FF的1024个单元中存放着中断向量表,且不能放在别处。
(2)自己选一个未被使用的中断码,实现一个中断例程,并调用测试。给出源码和运行测试截图。如选做,请说明你使用的中断码,并描述你实现的这个中断例程的功能。
实验总结
movsb可以理解为 move string byte,即字节传送指令,movsw的意思是mov string word ,字传送指令。执行完movsw或者rep movsw指令,si和di的值会增加2,或者减少2,这取决于DF标志位的值是1还是0。
浙公网安备 33010602011771号