实验2 汇编源程序编写与汇编、调试
实验结论
实验任务 1
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
使用 masm、link 对 ex1.asm 进行汇编、连接、运行,观察结果:



查看 PSP:

观察寄存器 CX 的值,使用 u 命令精确反汇编:

使用 g 命令执行到line16 退出执行之前:

观察到屏幕上出现 4 个图案,可知移入操作运行正确。
实验任务 2
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 ends
end
使用 masm、link 对 ex2.asm 进行汇编、连接、运行,观察结果:

观察寄存器 CX 的值,使用 u 命令精确反汇编:

使用 t 命令与 g 命令进行调试:
进行完第一次循环,出现一个图标:

使用 t 命令进入 loop,然后使用 g 命令进行第二次循环,屏幕上出现第二个图标:

后续由于控制台界面的限制,图标所在显存位置将被移出屏幕之外,使用 g 命令运行后无法观察到新的图像出现,但以此类推,可知使用 g 命令直接运行到第 13 行,出现所有图标:

将 ex2.asm 中 line9 mov cs, 4 改成 mov cx, 8,重新汇编、链接、运行:

循环将进行 8 次,显存填入 8 个数,屏幕出现 8 个图标。
对比 ex1.asm 与 ex2.asm,我们可以观察到他们有相同的功能和效果,
但 ex1.asm 是通过 byte ptr 的形式直接填入 8 个数,而 ex2.asm 是通过循环递增 ax,并填入 bx 且移位,来实现数的填入。
实验任务 3
ex3.asm:
; ex3.asm
assume cs:code
code segment
mov ax, 0b800h
mov ds, ax
mov bx, 07b8h
mov ax, 0237h
mov cx, 10h
s: mov [bx], ax
add bx,2
loop s
mov ah, 4ch
int 21h
code ends
end
汇编、链接、运行:

把填充的字数据,从 0237H 改成 0239H,保存后再次汇编、链接、运行:

可以发现显示的图标从 7 变成了 9.
把填充的字数据,从 0237H 改成 0437H,保存后再次汇编、链接、运行:

可以发现颜色从绿色变成了红色。
从这三个实验可知,这个字数据中高字节存放的是颜色,低字节存放的是字型。
实验任务 4
ex4.asm(使用 [bx] 与 loop)
; ex4.asm
assume cs:code
code segment
mov ax, 0h
mov ds, ax
mov bx, 200h
mov al, 0h
mov cx, 40H
s: mov [bx], ax
add bx, 1
add ax, 1
loop s
mov ah, 4ch
int 21h
code ends
end
对 ax 的小端赋值,使用 loop 进行 64 次循环操作,每次循环都对 [bx] 赋值,并对 ax 的小端和 bx 加 1,来实现对内存 0:200~0:23F 的赋值。
首先将 0:200~0:237 所有字数据赋值为 FF。
然后进行第一次循环,使用 t 命令执行loop,再进行第二次循环:

可以看到,我们每次赋值一个数据,低位为所要赋的值,高位为 00.
运行到 line13,结果为:

可知成功地实现了任务的要求。
ex41.asm(使用栈操作)
; ex41.asm
assume cs:code
code segment
mov ax, 0h
mov ss, ax
mov ax, 0240h
mov sp, ax
mov ah, 3Fh
mov al, 3Eh
mov cx, 20h
s: push ax
sub ah, 2h
sub al, 2h
loop s
mov ah, 4ch
int 21h
code ends
end
由于 8086 的入栈操作是由高地址向低地址,所以设置栈的段地址 SS 为 0h,偏移地址为 0240h。由于栈的 push 操作以字为单位,所以需要对每次 push 的字单元,对其高位和低位分别赋值,并在循环中分别进行修改,来实现数据的填入。
第一次循环:

可以观察到 栈顶偏移值 sp 前移,3F3E 填入 0000:023E,同时可以观察到栈顶前存入了部分值。
第二次循环:

可以观察到 栈顶偏移值 sp 前移,3D3C 填入 0000:023C,同时可以观察到栈顶前存入的部分值同步前移。
最终结果:

实验任务 5
此任务要求将 mov ax,4c00h 前的代码复制到内存 0:200 处,所以关键在于确认要复制多少字节,可以先将代码随意补全,使用 debug 观察寄存器 CX 的值,并使用 u 命令精确反汇编,来确认需要复制的字节数。

由此可知,mov ax,4c00h 命令位于 0018h,所以需要复制 0~0017 所有字节。因为使用 al 每次复制一字节,所以应将 0017h 赋给 cx。可由 寄存器 cs 得出要复制的代码原先位于 076A 段,所以,应该将 076Ah 赋给 ax
ex5.asm
assume cs:code
code segment
mov ax, 076Ah
mov ds, ax
mov ax, 0020h
mov es, ax
mov bx, 0
mov cx, 0017h
s:mov al, [bx]
mov es:[bx], al
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end
运行结果:

复制成功。
实验总结
此次实验中,掌握了如下信息:
- 掌握了完整汇编源程序编写、汇编、连接、运行、调试的方法
- 可以使用 mov byte ptr 对字节数据赋值
- 程序段前缀所在段地址为寄存器 DS 中的值,即程序段前 256 个字节
- 掌握了通过使用寄存器 cx 中的值来使用 u 命令精确反汇编的方法:寄存器 cx 存的值为程序段的字节数
- 掌握了使用 [bx] 和 loop 来编写循环程序的方法,此时寄存器 cx 的值用来限制循环次数
- 通过实验任务 1、2、3,明确地认识到了显存中高字节存放颜色,低字节存放字型这一特点
- 了解了 .asm 文件类型代码的写法方式

浙公网安备 33010602011771号