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 ;将CF置为0 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)回答问题:line31~line34的4条inc指令,能否替换成如下代码?你的结论的依据/理由是什么?
1 add si, 2 2 add di, 2
答:不能。inc指令不会改变进位标志位CF的值;若改成如上代码,adc的运算中CF的实际值将受到影响,加法结果也将受到影响。
但在本题中,第一两组数的相加实际并不会产生进位,第二add si,2 和add di,2也不会产生进位,所以实际结果并不会变。
3)在debug中调试,观察数据段中做128位加之前和加之后,数据段的值的变化。给出调试观察截图。
做128位加之前数据段的值:
做128位加之后数据段的值:
可以看到x+y的结果成功赋值到数据段x中。
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 ;调用int 21h的1号子功能 13 int 21h 14 mov [si], al ;从键盘上输入单个字符到al 15 cmp al, '#' ;判断是否为'#' 16 je next ;是则跳转 17 inc si 18 jmp s1 19 next: 20 mov ah, 2 ;调用int 21h的2号子功能 21 mov dl, 0ah ;输出单个字符到屏幕上,0ah换行符的ASCII码 22 int 21h 23 24 mov cx, si 25 mov si, 0 26 s2: mov ah, 2 ;调用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)回答问题
① 汇编指令代码line11-18,实现的功能是?
答:从键盘一个一个读入字符并判断是否为#,若是,跳转到子程序next;若不是,继续读入并计数。
② 汇编指令代码line20-22,实现的功能是?
答:输出一个换行符。
③ 汇编指令代码line24-30,实现的功能是?
答:输出读入的字符串(不包括#)。
3. 实验任务3
1)task3.asm源码
1 ;借助32÷16的除法,无需考虑溢出 2 assume cs:code,ds:data,ss:stack 3 4 data segment 5 x dw 91, 792, 8536, 65521, 2021 6 len equ $ - x 7 data ends 8 9 stack segment 10 db 10 dup(?) 11 stack ends 12 13 code segment 14 start: 15 mov ax, data 16 mov ds, ax 17 mov cx,len/2 18 mov si,0 19 print: 20 push cx ;保存cx的值 21 mov ax,ds:[si] ;数据放到ax 22 mov dx,0 ;高位为0 23 call printNumber 24 add si,2 25 pop cx 26 loop print 27 28 mov ax, 4c00h 29 int 21h 30 31 printNumber: 32 mov bl,10 ;除数10 33 mov di,0 34 35 s1: div bx 36 push dx ;保存余数 37 mov dx,0 38 inc di 39 cmp ax,0 ;被除数为0结束 40 jne s1 41 42 mov cx,di ;位数 43 mov ah,2 44 s2: pop dx 45 or dl,30h 46 int 21h 47 loop s2 48 call printSpace 49 ret 50 51 printSpace: 52 mov ah, 2 53 mov dl, ' ' 54 int 21h 55 ret 56 57 code ends 58 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 strupr 16 add si,1 17 loop s1 18 19 mov ax, 4c00h 20 int 21h 21 22 strupr: 23 cmp byte ptr ds:[si],'a' ;过滤 24 jb s2 25 cmp byte ptr ds:[si],'z' 26 ja s2 27 mov bl,ds:[si] ;小写转大写 28 sub bl,20H 29 mov ds:[si],bl 30 s2: ret 31 32 code ends 33 end start
2)在debug中调试截图(call strupr调用之前,数据段的值,以及,调用之后,数据段的值)
调用之前:
调用之后:
5. 实验任务5
1)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 ;int 10h的2号子功能 17 mov bh, 0 18 mov dh, 24 ;设置光标位置在第24行 19 mov dl, 70 ;设置光标位置在第70列 20 int 10h ;设置光标位置 21 22 cmp al, '7' 23 je s1 24 mov ah, 9 ;用int 21h的9号子功能,输出字符串,字符串必须以$截止 25 mov dx, offset str2 26 int 21h ;显示标号str2处的字符串 27 28 jmp over 29 30 s1: mov ah, 9 31 mov dx, offset str1 32 int 21h ;显示标号str2处的字符串 33 over: 34 mov ah, 4ch 35 int 21h 36 code ends 37 end start
2)程序运行测试截图(输入7,以及输入其他字符,运行结果截图)
输入7:
其他字符:
3)程序的功能是?
答:从程序读入一个字符并判断是否为'7',若为'7',在第24行70列输出yes并退出;若不为'7',在第24行70列输出no并退出。
6. 实验任务6
编译、运行task6_1.asm和task6_2.asm
通过此项实现任务,你对中断、软中断实现机制的理解
中断分为硬中断与软中断。硬中断主要为硬件触发的中断,软中断主要为内核机制触发事件产生的中断。
中断的过程类似于函数的调用。
内核机制触发事件产生中断,CPU收到对应的中断类型码,通过中断类型码到中断向量表中找到
中断处理程序的段地址(0000:中断类型码*4)和偏移地址(0000:中断类型码*4+2),然后通过修改CS和IP的值定位中断处理程序并执行它
注意和调用函数相似的,要保留中断前的CS和IP,因为执行完中断程序要返回。