四、实验结论
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
运行截图:
- 回答问题①
读取汇编指令loop s1时,IP指向001B,执行该指令后IP指向000D。其跳转的位移量是-14。指令对应的机器码E2F2中F2是跳转位移量-14的十六进制补码。CPU将跳转位移量与IP值相加,得到下一条要执行指令的IP,即000D。
- 回答问题②
读取汇编指令loop s2时,IP指向0039,执行该指令后IP指向0029。其跳转的位移量是-16。指令对应的机器码E2F0中F0是跳转位移量-16的十六进制补码。CPU将跳转位移量与IP值相加,得到下一条要执行指令的IP,即0029。
- 问题③
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
- ①CPU在执行call指令时,会将当前ip(或cs和ip)入栈。故ax中存放的应该是line25(pop ax)指令对应的ip,bx中存放的是line28(pop bx)指令对应的IP,cx中存放的是line28指令对应的CS。
由下图可知,寄存器(ax)=0021,(bx)=0026,(cx)=076C
②调试结果界面截图:
调试结果与理论分析结果一致。
3.实验任务3
- 程序源码task3.asm
1 assume cs:code, ds:data 2 3 data segment 4 x db 99, 72, 85, 63, 89, 97, 55 5 len equ $- x 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 13 mov cx, len ;从符号x开始的连续字节数据项个数 14 mov si, 0 15 s: 16 mov ah, 0 17 mov al, ds:[si] ;一个两位数占1个字节 18 call printNumber 19 call printSpace 20 inc si 21 loop s 22 23 mov ah, 4ch 24 int 21h 25 26 ;以十进制形式输出一个两位数 27 printNumber: 28 mov bl, 10 29 div bl 30 mov dl, al ;商:十位数 31 mov dh, ah ;余数:个位数 32 or dl, 30h ;将数字转成对应字符 33 or dh, 30h 34 35 mov ah, 2 36 int 21h 37 mov dl, dh 38 int 21h 39 ret 40 41 ;打印一个空格 42 printSpace: 43 mov ah, 2 44 mov dl, ' ' 45 int 21h 46 ret 47 48 code ends 49 end start
- 运行测试截图
4.实验任务4
由下图可知,
黑底绿字:0000 0010,转换成16进制为2H
黑底红字:0000 0100,转换成16进制为4H
- 程序源码task4.asm
1 assume cs:code, ds:data 2 3 data segment 4 str db 'try' 5 len equ $ - str 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, 0b800h 13 mov es, ax 14 15 mov si, offset str 16 mov bl, 2h ;字符串颜色 17 mov bh, 0 ;指定行 18 call printStr 19 20 mov si, offset str 21 mov bl, 4h 22 mov bh, 24 23 call printStr 24 25 mov ah, 4ch 26 int 21h 27 28 ;在指定行、以指定颜色,在屏幕上显示字符串 29 printStr: 30 ;计算行号对应的首位偏移地址 31 mov al, bh 32 mov dl, 00A0h 33 mul dl 34 35 mov di, ax 36 mov cx, len ;从符号str开始的连续字节数据项个数 37 s: 38 mov al, ds:[si] 39 mov es:[di], al 40 inc di 41 mov es:[di], bl 42 inc si 43 inc di 44 loop s 45 ret 46 47 code ends 48 end start
- 运行测试截图
5.实验任务5
蓝底白字:0001 0111,转换成16进制为17H
80列,'-'34 学号12 '-'34
- 程序源码task5.asm
1 assume cs:code, ds:data 2 3 data segment 4 stu_no db '201983290259' 5 len = $ - stu_no 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 mov ax, 0b800h 13 mov es, ax 14 15 mov si, offset stu_no 16 mov di, 0 17 mov bl, 17h ;蓝底白字 18 call printColor 19 call printLine 20 call printNumber 21 call printLine 22 23 mov ah, 4ch 24 int 21h 25 ;打印背景颜色 26 printColor: 27 mov cx, 1920 ;前24行24*80 28 s0: 29 inc di 30 mov es:[di],bl 31 inc di 32 loop s0 33 ret 34 35 ;打印学号 36 printNumber: 37 mov cx, len ;从符号stu_no开始的连续字节数据项个数 38 s1: 39 mov al, ds:[si] 40 mov es:[di], al 41 inc di 42 mov es:[di], bl 43 inc si 44 inc di 45 loop s1 46 ret 47 48 ;打印34个'-' 49 printLine: 50 mov cx, 34 51 s2: 52 mov word ptr es:[di], '-' 53 inc di 54 mov es:[di], bl 55 inc di 56 loop s2 57 ret 58 59 code ends 60 end start
- 运行测试截图
五、实验总结
运算符offset的用法为 offset 标号 ,作用是在汇编时取标号的偏移地址。
伪指令equ的作用是等值赋值,其格式为 <符号名> equ <表达式> 。
预定义符号$,等价于当前正汇编到的段的当前偏移值。