[Assembly Language] 实验2 汇编源程序编写与汇编、调试
Task1 编写8086汇编源程序并进行汇编、链接、调试
ex1.asm 文件的内容如下:
;ex1.asm assume cs:code code segment mov ax, 0b810h mov ds, ax mov byte ptr ds:[0], 1 mov byte ptr ds:[1], 1 mov byte ptr ds:[2], 2 mov byte ptr ds:[3], 2 mov byte ptr ds:[4], 3 mov byte ptr ds:[5], 3 mov byte ptr ds:[6], 4 mov byte ptr ds:[7], 4 mov ah, 4ch int 21h code ends end
在DOSBox中使用masm命令对ex1.asm文件进行汇编,再对生成的.obj文件使用link命令生成.exe文件,具体指令为:
- masm ex1.asm;
- link ex1.obj;
(指令后面加分号可以略过一些细节参数的设置)
输入ex1.exe运行,发现窗口上方出现蜜汁字符,出现的原因参考实验1中相关内容。
在debug模式下,使用d命令查看程序段前缀PSP所占的256个字节。
根据寄存器CX中的值(CX=0031),得知汇编指令占32字节,使用命令-u 0 31,对exe文件进行反汇编。
使用g命令执行该汇编程序,得到结果如下(与直接运行exe文件效果相同):
(注:这里可能会出现蜜汁字符不显示的问题。原因是把字符打到指定位置后,由于-g命令的反馈信息,界面向下滚动了3行,导致原来的字符也向上滚了3行,正好在界面外。通过查看这些地址的值,发现已经被改变了,实际上这些值与界面中原字符对应位置的显示内容有关。因此只要让界面不滚动,就能完美地在指定位置输出蜜汁字符。)
Task2 编写8086汇编源程序并进行汇编、链接、调试(使用loop)
ex2.asm 文件的内容如下:
; ex2.asm assume cs:code code segment mov ax, 0b810h mov ds, ax mov bx, 0 mov ax, 101h mov cx, 4 s: mov [bx], ax add bx, 2 add ax, 101h loop s mov ah, 4ch int 21h code endss end
使用masm、link命令汇编链接,运行ex2.exe,与ex1.exe的运行效果相同。
对ex2.exe使用debug工具,输入u命令进行精确反汇编。
loop指令的地址为0016,输入-g 16,显示循环体第一次运行结果。 之后每个步骤的显示由于界面上滚,无法显示,因此对原代码修改内存的位置做出一点改动(初始DS改成B840),重新生成ex2.exe.
交替使用 -t 和 -g 16,显示出每一步打印在屏幕上的字符(不对齐的原因 task1 中已经说了)。
排除调试时屏幕滚动刷新的原因,直接执行ex1.asm和ex2.asm所产生的exe的效果是一致的。
代码书写上,ex1.asm采用顺序结构,ex2.asm采用循环结构。后者对于开发者而言书写的效率更高,但同时也让机器执行了更多的指令,时间上并不优于前者。
Task3 综合使用loop, [bx],实现向内存b800:07b8开始的连续16个字单元重复填充字数据 0237H
编写程序 ex3.asm 如下:
assume cs:code code segment mov ax, 0b800h mov ds, ax mov bx, 07b8h mov ax, 0237h mov cx, 16 m: mov [bx], ax add bx, 2 loop m mov ah, 4ch int 21h code ends end
使用 masm 和 link 对 ex3 进行汇编、链接,运行生成的exe文件。
分别将填充的字数据改为 0239h 和 0437h,重新汇编链接过后,运行的结果如下:
猜测字数据的高位存储的是字符的颜色,低位存储的为字符的ASCII码。
共256种颜色,其中后128种有闪烁效果。
共256种字符样式,其中后128种为扩展ASCII码。
Task4 编写完整汇编源程序,实现向内存0:200~0:23F依次传送数据0~63(3FH)
(1)使用loop,[bx]实现
代码如下:
assume cs:code code segment mov ax, 0020h mov ds, ax mov bx, 0h mov cx, 40h m: mov [bx], bl add bx, 0001h loop m mov ah, 4ch int 21h code ends end
运行结果如下:
Task5 补全代码并调试
该程序的功能是将 "mov ax, 4c00h" 之前的指令复制到 0:200 处,待补全代码如下:
1 assume cs:code 2 code segment 3 mov ax, _____ 4 mov ds, ax 5 6 mov ax, 0020h 7 mov es, ax 8 mov bx, 0 9 mov cs, _____ 10 s: mov al, [bx] 11 mov es:[bx], al 12 inc bx 13 loop s 14 15 mov ax, 4c00h 16 int 21h 17 code ends 18 end
填入代码为:
(1)mov ax, cs
(2)mov cx, 17h
填入后在 debug 模式下运行,使用 -d 命令分别查看 0:200 和 076A:0 开始的数据。
该程序的功能是把从 076A:0 开始的若干字节数据放入 0:200 开始的若干地址,写入数据的量与具体填入的空有关。
如果一开始填入 mov ax, 076A,则有18h个字节数据;填入 mov ax, cs,则有17h个字节数据。原因是,mov 指令后如果是两个寄存器占用 2 个字节,如果是一个寄存器和一个立即数占用 3 个字节。(通过观察 -u 指令后每条指令所占空间可以推断出)
得知字节数量最简单的方法是,根据 CX 的值减去最后两条指令占的 5 个字节(再填入到第二个空中)。