四、实验结论
1、实验任务1
task1.asm源码:
1 assume cs:code, ds:data 2 3 data segment 4 x db 1, 9, 3 5 len1 equ $ - x ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是3 6 7 y dw 1, 9, 3 8 len2 equ $ - y ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是9 9 data ends 10 11 code segment 12 start: 13 mov ax, data 14 mov ds, ax 15 16 mov si, offset x ; 取符号x对应的偏移地址0 -> si 17 mov cx, len1 ; 从符号x开始的连续字节数据项个数 -> cx 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 ; 取符号y对应的偏移地址3 -> si 34 mov cx, len2/2 ; 从符号y开始的连续字数据项个数 -> cx 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
运行结果:
回答问题
问题1:line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s1其后指令的偏移地址的。
回答:
debug反汇编结果:
标号s1偏移量为000DH,当前正在执行指令偏移量加上本指令所占空间为001BH,则位移量为001BH - 000DH = 000EH,即为十进制数14。
CPU通过计算LOOP指令下一指令地址-s1标号地址得到位移量。
问题2:line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明是如何计算得到跳转后标号s2其后指令的偏移地址的。
回答:
debug反汇编结果:
标号s2偏移量为0029H,当前正在执行指令偏移量加上本指令所占空间为0039H,则位移量为0039H - 0029H = 0010H,即为十进制数16。
CPU通过计算LOOP指令下一指令地址-s2标号地址得到位移量。
问题3:附上上述分析时,在debug中进行调试观察的反汇编截图。
*已在回答中附上。
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
根据call指令跳转原理,从理论上分析,程序执行到退出(Line31)前,寄存器ax = 0021h, bx = 0026h,cx = 076ch。
在debug中使用u命令反汇编得到退出指令偏移地址,并使用g命令调试到退出指令执行之前,观察到ax = 0021h, bx = 0026h,cx = 076ch。
3、实验任务3
task3.asm源码:
assume cs:code, ds:data data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $- x data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov cx, len mov si, offset x s: mov ah, 0 mov al, ds:[si] call printNumber call printSpace inc si loop s mov ah, 4ch int 21h printNumber: mov bl, 10 div bl mov dl, al mov dh, ah or dl, 30H ;数值转字符 mov ah, 2 int 21h ;输出高位 mov dl, dh or dl, 30H ;数值转字符 int 21h ;输出低位 ret printSpace: mov ah, 2 mov dl, ' ' int 21h ;输出空格 ret code ends end start
运行测试截图:
4、实验任务4
task4.asm源码:
assume cs:code, ds:data data segment str db 'try' len equ $ - str data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax mov cx, len mov si, 0 mov bl, 2 ;green mov bh, 0 ;第一行 mov di, bh ;行首地址 call printStr mov bh, 24 ;最后一行 ;每行占用空间为00A0H mov bl, bh mov bh, 0 mov cx, bx mov ax, 0 findLastRow: add ax, 00A0H loop findLastRow mov di, ax mov cx, len mov si, 0 mov bl, 4 ;red call printStr mov ah, 4ch int 21h printStr: s: mov al, ds:[si] mov ah, bl mov es:[di], ax inc si inc di inc di loop s ret code ends end start
运行测试截图:
5、实验任务5
task5.asm源码:
assume cs:code, ds:data data segment stu_no db '201983290068' len = $ - stu_no data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax mov bl, 17H ;蓝底白字 mov si, 0 call setBgColor mov bh, 24 ;最后一行 ;每行占用空间为00A0H mov bl, bh mov bh, 0 mov cx, bx mov ax, 0 findLastRow: add ax, 00A0H loop findLastRow mov di, ax ;前白色线长34 mov al, '-' mov cx, 34 mov bl, 17H ;蓝底白字 call printLine mov cx, len mov si, 0 mov bl, 17H ;蓝底白字 call printStr ;后白色线长34 mov al, '-' mov cx, 34 mov bl, 17H ;蓝底白字 call printLine mov ah, 4ch int 21h printStr: s: mov al, ds:[si] mov ah, bl mov es:[di], ax inc si inc di inc di loop s ret printLine: s1: mov al, '-' mov ah, bl mov es:[di], ax inc di inc di loop s1 ret setBgColor: mov cx, 2000 ;80*25 s2: mov al, ' ' mov ah, bl mov es:[si], ax inc si inc si loop s2 ret code ends end start
运行测试截图:
五、实验总结
通过本次实验,我熟悉了80×25彩色字符模式显示原理。每行为160字节,每页25行,若想在指定位置进行输出,则需要据此进行计算。
数字无法直接显示,需要先将其转为字符,可以采用or 30h的方式快速转换。