实验 汇编程序编写与汇编调试

一、实验任务1

ex1.asm源代码如下:

复制代码
;ex1.asm
assume cs:code  ;将有特定用途的段和相关的段寄存器关联起来:将code当做代码段来用,将code和cs关联起来
code segment                ;段名 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                  ;段名 ends
end        ;汇编程序的结束标记
复制代码

上图中有注释行的代码为伪指令;

1)创建代码文件,并写入代码:

注意点:十六进制数的表示;

edit ex1.asm

结果:产生了一个存储源程序的文本文件;

源程序:包括伪指令(由编译器来处理)和指令(有对应的机器码指令,可被编译为机器指令);

程序:最终由计算机执行、处理的指令或数据,现阶段以汇编指令形式存储在源程序中。

 2)对源程序进行编译:(以分号结尾跳过中间文件的生成过程)

amsm ex1.asm;

结果:得到了目标文件ex1.obj

3)连接:

link ex1.obj;

结果:程序经过编译、连接转变为机器码,存储在可执行文件ex1.exe中。

4)执行:直接执行ex1

ex1

执行结果有图案显示在屏幕上,猜测是向显存写入了内容;下面进行跟踪调试:

5)程序执行过程的跟踪:

debug ex1.exe

①利用反汇编指令查看汇编程序代码:

已知寄存器CX中存储的是程序的长度,一共31字节;

代码段的起始段地址存储在寄存器CS中,偏移量为IP的值:

用以下命令进行精确反汇编:(指定偏移地址,段地址使用默认的CS)

u 0 30

u 0 L31

与写入的代码进行比较:内容一致;

②查看程序段前缀PSP:

DS中存储程序所在内存区的段地址;

观察上图:CS:IP指向第一条指令,而CS = DS + 10H;可相互印证;

③使用g命令执行:

g cs:2d

运行结果与直接运行结果一致;

由实验可印证:g  段地址:偏移地址 指令是指定程序执行到所给定的地址之前;

二、实验任务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
复制代码

1)同实验任务一编译、连接并执行:

代码依次为:

masm ex2.asm;

link ex2.obj;

ex2

运行结果:与实验任务一结果相同

2)跟踪调试:

①CX=001C

精确反汇编,指令如下:

u 0 1b

u 0 L1c

与源代码对比可知:loop:标号:   loop s  –> loop  000E

标号的本质为地址;

②用t / p / g命令执行:

mov ax,B810
mov DS, AX
mov BX,0000

将数据段段地址设置为显存所在地址;BX寄存器置0:

设定寄存器AX = 0101;指定循环次数CX=0004 ;

mov AX,0101
mov CX,0004
MOV [BX],AX
ADD BX,+02
ADD AX,0101
LOOP 000E

将0101赋给B810:0 1,BX –>  BX + 2

AX = 0101  –> AX = 0202

在执行跳转指令之前,CX = (CX)- 1,判断CX不为0则跳转;

执行结果与之相符:

持续执行,中间步骤类似,略;

直到将AX=0404 –> B810:6 7 中后,CX=0001;

执行到loop 000E判定时:CX = CX – 1 = 0000 不再跳转,

实验结果如下,一致:

直接使用g命令,有输出显示:

③ex2.asm与ex1.asm对比分析:

实现了相同的功效,在具体实现上:

实验任务1中采用的是通过8次mov指令,将直接数移入指定内存单元;

实验任务2中采用[BX]和loop指令相结合,通过move [BX],AX改变指定内存单元内容;

对比之下,实验一中程序的长度为0031H ,实验二中程序的长度为001CH,程序长度明显减少。

内存单元信息包含 内存单元地址,内存单元长度(类型),[BX]:偏移地址在bx中,段地址默认在ds中,数据类型长度由具体指令中其他操作对象决定;

这样的特性可以使得代码段更为精简。

三、实验任务3

ex3.exe源代码如下:

复制代码
;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
复制代码

运行结果如下:

改变代码如下:

 mov ax,0239h ;mov ax,0237h

运行结果:

改变代码如下:

 mov ax,0437h ;mov ax,0237h

运行结果:

实验结果:

0237 –>  0239  低位字节改变,图案改变;

0237 –>  0437  高位字节改变,颜色改变;

 猜测分析:低字节数据控制图案,高字节数据控制颜色。

四、实验任务4

 使用[bx] 和 loop指令实现向0:200~0:23f写入0~64:,源代码如下:

复制代码
;ex4.asm
assume cs:code
code segment
        mov ax,0h
        mov ds,ax

        mov bx,200h
        mov ax,0000h
        mov cx,40h      ;写入0~3f共40h个数据
s:      mov [bx],al
        add bx,1
        add al,01h
        loop s
        mov ah,4ch
        int 21h
code ends
end
复制代码

①编译连接:

②运行,并查看运行前后内存情况:

;用到的指令如下

d 0:200 23f

g 001b

目标数据已成功写入指定内存;

 五、实验任务5

最终代码如下:

复制代码
;ex5.asm
assume cs:code
code segment
        mov  ax,cs
        mov  ds,ax
        mov  ax,0020h
        mov  es,ax   ;es保存目标内存段的段地址
        mov  bx,0
        mov  cx,23
s:      mov  al,[bx]
        mov  es:[bx],al
        inc  bx    ;偏移地址内存单元每次+1
        loop s
        mov  ax,4c00h
        int  21h
code ends
end
复制代码

1)填空分析:

①第一处填空:目标空 — 》  AX –》DS 也即填空要复制的内容的段地址,也即当前代码段的段地址;

通过 assume cs:code可知,已将代码段与cs关联起来;所以代码段的段地址保存在了cs中,第一个空处填 CS

②在原始代码文件中给CX赋一个随机值,如下图:确定要复制的目标代码段长度为:17H = 23

修改EX5.ASM文件,确定 mov cx,21;

2)编译连接修改后的文件:

3)跟踪运行:

程序执行前目标内存:

①DS确定被复制的目标代码的段地址:

②ES确定目标内存段地址:

确定循环次数CX=0017H

③一次循环:DS:0 –> ES:0

④执行完后后,查看目标内存:

反汇编结果也一致:

代码复制成功。

类似文章