实验结论
1.实验任务1
task1.asm
1 assume cs:code, ds:data 2 3 data segment 4 x db 1, 9, 3 5 len1 equ $ - x 6 7 y dw 1, 9, 3 8 len2 equ $ - y 9 data ends 10 11 code segment 12 start: 13 mov ax, data 14 mov ds, ax 15 16 mov si, offset x 17 mov cx, len1 18 mov ah, 2 19 s1:mov dl, [si] 20 or dl, 30h 21 int 21h 22 23 mov dl, ' ' 24 int 21h 25 26 inc si 27 loop s1 28 29 mov ah, 2 30 mov dl, 0ah 31 int 21h 32 33 mov si, offset y 34 mov cx, len2/2 35 mov ah, 2 36 s2:mov dx, [si] 37 or dl, 30h 38 int 21h 39 40 mov dl, ' ' 41 int 21h 42 43 add si, 2 44 loop s2 45 46 mov ah, 4ch 47 int 21h 48 code ends 49 end start
运行:
回答问题①
① line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机
器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明
是如何计算得到跳转后标号s1其后指令的偏移地址的。
反汇编
loop s1时从 001B跳转到 000D,位移量为-14(F2)字节。此时程序还没有运行,则位移量是由8086CPU在汇编时根据loop 的位置和s1大小计算出来的,向前跳,所以位移为负,在机器码中用补码表示。
回答问题②
② line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机
器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明
是如何计算得到跳转后标号s2其后指令的偏移地址的。
反汇编
loop s2时,从0039到0029,位移量为-16(F0)字节,此时程序未运行,偏移地址是在汇编时计算出来的。
2.实验任务2
task2.asm
1 assume cs:code, ds:data 2 3 data segment 4 dw 200h, 0h, 230h, 0h 5 data ends 6 7 stack segment 8 db 16 dup(0) 9 stack ends 10 11 code segment 12 start: 13 mov ax, data 14 mov ds, ax 15 16 mov word ptr ds:[0], offset s1 17 mov word ptr ds:[2], offset s2 18 mov ds:[4], cs 19 20 mov ax, stack 21 mov ss, ax 22 mov sp, 16 23 24 call word ptr ds:[0] 25 s1: pop ax 26 27 call dword ptr ds:[2] 28 s2: pop bx 29 pop cx 30 31 mov ah, 4ch 32 int 21h 33 code ends 34 end start
反汇编:
可知s1:0021,s2:0026,cs:076C,分别保存在ds:[0],ds[2],ds[4]中。
根据call指令的原理,程序执行到退出(line31)之前,寄存器ax应该存储ds:[0],寄存器cx应该存储ds:[4],寄存器bx应该存储ds:[2],
即寄存器(ax) =0021 寄存器(bx) = 0026 寄存器(cx) = 076C
程序执行到退出前结果:
结果与理论分析符合。
3.实验任务3
编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。
data段数据如下:
data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $- x data ends
要求:
编写子程序printNumber
功能:以十进制形式输出一个两位数
入口参数:寄存器ax(待输出的数据 --> ax)
出口参数:无
编写子程序printSpace
功能:打印一个空格
入口参数:无
出口参数:无
在主体代码中,综合应用寻址方式和循环,调用printNumber和printSpace, 实现题目要求。
task3.asm代码
1 assume cs:code, ds:data 2 data segment 3 x db 99, 72, 85, 63, 89, 97, 55 4 len equ $- x 5 data ends 6 code segment 7 start: 8 mov ax,data 9 mov ds,ax 10 mov si,0 11 mov cx,7 12 s: mov ax,0 13 mov al,ds:[si] 14 call s1 15 call s2 16 add si,1 17 loop s 18 mov ah, 4ch 19 int 21h 20 21 s1: mov bl,10 22 div bl 23 mov di,16 24 mov ds:[di],al;******shiwei 25 mov ds:[di+1],ah;****gwei 26 mov dl,ds:[di] 27 add dl,30h 28 mov ah,2 29 int 21h 30 mov dl,ds:[di+1] 31 add dl,30h 32 int 21h 33 ret 34 35 s2: mov dl," " 36 mov ah,2 37 int 21h 38 ret 39 40 code ends 41 end start
运行:
4.实验任务4
针对8086CPU,已知逻辑段定义如下:
data segment str db 'try' len equ $ - str data ends
编写8086汇编源程序task4.asm,在屏幕上以指定颜色、指定行,在屏幕上输出字符串。
要求:
编写子程序printStr
功能:在指定行、以指定颜色,在屏幕上显示字符串
入口参数
字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏
移地址—> si)
字符串长度 --> cx
字符串颜色 --> bl
指定行 --> bh (取值:0 ~24)
出口参数:无
task4.asm代码:
1 assume cs:code, ds:data 2 data segment 3 str db 'try' 4 len equ $ - str 5 data ends 6 code segment 7 start: 8 mov ax,data 9 mov ds,ax 10 mov si,0 11 mov cx,3 12 mov bl,2;绿色 13 mov bh,0 14 call s1 15 mov si,0 16 mov cx,3 17 mov bl,4;红色 18 mov bh,24 19 call s1 20 mov ah,4ch 21 int 21h 22 23 s1:mov ax,0b800h 24 mov es,ax 25 mov al,bh 26 push bx 27 mov bl,160 28 mul bl 29 pop bx 30 s: mov dl,ds:[si] 31 mov dh,bl 32 mov di,ax 33 mov es:[di],dx 34 add ax,2 35 add si,1 36 loop s 37 ret 38 code ends 39 end start
运行:
5.实验任务5
在80×25彩色字符模式下,在屏幕最后一行正中间显示学号。要求输出窗口蓝底,学号和两侧折线,以白色前景色显示。
1 assume cs:code, ds:data 2 data segment 3 stu_no db '201983290368' 4 len = $ - stu_no 5 data ends 6 code segment 7 start: 8 mov ax,data 9 mov ds,ax 10 mov ax,0b800h 11 mov es,ax 12 mov bl," " 13 mov bh,23 14 mov di,0 15 mov cx,780h 16 s:mov es:[di],bx 17 add di,2 18 loop s 19 20 mov cx,34 21 s1:mov bl,"-" 22 mov es:[di],bx 23 add di,2 24 loop s1 25 26 mov si,0 27 mov cx,12 28 s2:mov bl,ds:[si] 29 mov es:[di],bx 30 add di,2 31 add si,1 32 loop s2 33 mov cx,34 34 s3:mov bl,"-" 35 mov es:[di],bx 36 add di,2 37 loop s3 38 mov ah,4ch 39 int 21h 40 41 code ends 42 end start
运行:
实验总结
借助栈可以解决子程序寄存器冲突问题,对于一些有特殊用法的寄存器,如cx,ax等,在子程序中使用该寄存器前将寄存器入栈,等待使用完毕后在出栈回到相应的寄存器中。