实验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 文件类型代码的写法方式
posted @ 2020-11-01 10:17  maranlll  阅读(90)  评论(3)    收藏  举报