实验3
实验任务1
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
运行截图
在debug中进行调试观察的反汇编截图
问题1:line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s1其后指令的偏移地址的。
答:(F2)h = 242 因为执行完LOOP 000D后 IP指针此时的值为001B 而 001B+F2=(01)0D (01)溢出被舍弃 最终IP的值即为000D 符合LOOP指令应当跳转的地址值
问题2:line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s2其后指令的偏移地址的。
答:(F0)h = 240 因为执行完LOOP 0029后 IP指针此时的值为0039 而 0039+F0=(01)29 (01)溢出被舍弃 最终IP的值即为0029 符合LOOP指令应当跳转的地址值
实验任务2
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) = s1 寄存器(bx) = s2 寄存器(cx) = cs
因为call word ptr ds:[0]是短转移 此时call指令先把当前ip值压栈(也就是s1对应的ip),然后进行跳转 call dword ptr ds:[2] 是长转移, 此时先把当前cs:ip值(也就是cs:s2)压栈,然后进行跳转
对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论 分析结果是否一致,如下图:
可见分析正确
实验任务3
代码
1 assume cs:code, ds:data 2 3 data segment 4 x db 99, 72, 85, 63, 89, 97, 55 5 ;0 1 2 3 4 5 6 6 len equ $- x ;符号常量, $指下一个数据项的偏移地址,这个示例中,是7 7 data ends 8 9 code segment 10 start: 11 mov ax, data 12 mov ds, ax 13 14 mov si, offset x ; 取符号x对应的偏移地址0 -> si 15 mov cx, len 16 mov bl, 10 17 s1: 18 mov ah, 0 19 mov al, [si] 20 call printNumber 21 call printSpace 22 inc si 23 loop s1 24 25 mov ax, 4c00h 26 int 21h 27 28 printNumber: 29 div bl 30 mov dl, al;商在al 31 or dl, 30H;将数字转换为字符 32 mov bh, ah;余数在ah 33 34 mov ah, 2 35 int 21h;打印十位数 36 37 mov dl, bh 38 or dl, 30H 39 int 21h;打印个位数 40 ;mov ah, 2 41 ;mov dl, ×× xx是待输出的字符,或其ASCⅡ码值 42 ;int 21h 43 ret 44 45 printSpace: 46 mov ah, 2 47 mov dl, ' ' 48 int 21h ;输出空格 49 ret 50 51 code ends 52 end start
结果
实验任务4
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 13 mov ax, 0b800h 14 mov es, ax 15 16 ;在屏幕最上方以黑底绿字显示字符串 17 mov si, offset str ; 取符号x对应的偏移地址0 -> si 18 mov bh, 0; 指定行 19 call getHeadAdrOfRow 20 mov bl, 02h;指定颜色 21 mov cx, len 22 call printStr 23 24 ;在屏幕最下方以黑底红色显示字符串 25 mov si, offset str ; 取符号x对应的偏移地址0 -> si 26 mov bh, 24; 指定行 HeadAdrOfRow = 00A0H * n 27 call getHeadAdrOfRow 28 mov bl, 4;指定颜色 29 mov cx, len 30 call printStr 31 32 mov ax, 4c00h 33 int 21h 34 35 printStr: 36 s1: 37 mov ah, bl 38 mov al, [si] 39 mov es:[di], ax 40 inc si 41 add di, 2 42 loop s1 43 ret 44 45 getHeadAdrOfRow:;返回第bh行的首地址di 46 mov ax, 0 47 mov bl, bh 48 mov bh, 0 49 mov cx, bx 50 s3: 51 add ax, 00A0H 52 loop s3 53 mov di, ax 54 ret 55 56 code ends 57 end start
结果截图
实验任务5
1 assume cs:code, ds:data 2 3 data segment 4 stu_no db '201983290096' 5 len = $ - stu_no 6 data ends 7 8 code segment 9 start: 10 mov ax, data 11 mov ds, ax 12 13 mov ax, 0b800h 14 mov es, ax 15 16 ;将背景设为蓝色 17 mov bh, 0; 指定从第几行开始设置背景色 18 call getHeadAdrOfRow 19 mov bl, 17h;指定背景颜色 20 call setBackground 21 22 ;在屏幕最下方输出指定内容 23 mov si, offset stu_no ; 取符号x对应的偏移地址0 -> si 24 mov bh, 24; 指定行 HeadAdrOfRow = 00A0H * n 25 call getHeadAdrOfRow 26 mov bl, 17h;指定字体颜色 27 call printStr 28 29 30 mov bx, 0 31 32 mov ax, 4c00h 33 int 21h 34 35 setBackground: 36 ;mov cx, 1920 37 mov cx, 2000 38 s2: 39 mov al, ' ' 40 mov ah, bl 41 mov es:[di], ax 42 add di, 2 43 loop s2 44 ret 45 46 printStr: 47 call print 48 49 mov cx, len 50 s1: 51 mov ah, bl 52 mov al, [si] 53 ;or al, 30H 54 ;mov al, 49 55 mov es:[di], ax 56 inc si 57 add di, 2 58 loop s1 59 60 call print 61 ret 62 63 getHeadAdrOfRow:;返回第bh行的首地址di 64 mov ax, 0 65 mov bl, bh 66 mov bh, 0 67 mov cx, bx 68 s3: 69 add ax, 00A0H 70 loop s3 71 mov di, ax 72 ret 73 74 print:;输出--- 75 mov cx, 34 76 s4: 77 mov ah, bl 78 mov al, 45;'-' 79 mov es:[di], ax 80 add di, 2 81 loop s4 82 ret 83 84 code ends 85 end start
结果截图
这里要注意在设置背景色时如果希望前景色为透明,可以把字符设置为' '(空格),这样就不用担心填充时前景色字符覆盖背景的问题
同时,如果设置背景时把前景色也设为蓝色,那么这里的F:\>就看不见了 但实际还是存在的 感兴趣的同学可以试试