DoxBox环境汇编的Debug调试以及相关知识
DoxBox中使用Debug程序进行汇编调试以及编码
Debug基本功能介绍
R命令,查看改变CPU寄存器的内容
点击查看
-r ax //修改ax寄存器内容
ax 0000 //自动显示当前ax寄存器内容为0000
:1111 //将ax寄存器修改为1111
D命令,查看内存中的内容
点击查看
-d 1000:0 //格式为 段地址:偏移地址
-d 1000:0 f //查看偏移地址0到f中的内存内容
E命令,改写内存中的内容
点击查看
-e 1000:0 0 1 2 3 4 5 6 7 8 9 //修改1000:0 为 0;修改1000:1 为 1,以此类推。
-e 1000:10
1000:10 原始数据.待写入数据 原始数据.待写入数据 原始数据.待写入数据 原始数据.待写入数据......
U命令,将内存单元中的内容翻译为汇编指令,并显示出来
点击查看
-u 1000:0
T命令,执行一条机器指令
A命令,以汇编指令的格式在内存中写入一条机器指令
点击查看
-a 1000:0
1000:0000 要写入的指令
1000:0003 要写入的指令
1000:0006 mov cx,3
编译,链接
先编译,后链接。
masm 源程序文件名.asm; //注意,分号打一下,直接跳过一些选择
masm源程序后会生成OBJ文件,我们需要将OBJ文件链接成为EXE文件
link 源程序文件名.obj; //分号打一下
link之后就会生成EXE文件,我们直接使用debug 文件名.exe 或者直接在命令行中输入 文件名 即可运行
尝试修改ROM内容
PC机主板上的ROM中有一个生产时期,在内存FFF00H~FFFFFH的某几个单元中,请找到这个时期,并试图修改它
- 第一步使用debug程序中的D命令找出时期
可以看到时间是1992年1月1日,30年前。
- 尝试修改ROM内存单元的内容
可以看到执行修改命令后并没有变化。这是因为ROM(Read-Only Memory)内存是只读内存,不能修改。
使用E命令向内存单元填写数据
在debug中,使用E命令,向内存单元填写数据。
结果如下
-e b800:0 03 04 03 04 03 04 03 04 03 04
在debug中,使用F命令,向内存单元批量填写数据。
-f b800:0f00 0f9f 03 04
结果如下
栈的使用
已知内存单元00201H ~ 00207H分别存放数据(如下图所示),00220H ~ 0022fH用作栈空间。
在debug环境中,按顺序录入以下内容,单步跟踪调试,观察寄存器和内存空间00200H~00207H,以及,栈空间00220 ~ 0022fH内容变化情况。记录实验结果。回答问题,验证和你的理论分析结果是否一致。
分析:
首先将内存20:0 - 20:7 的内存置为 10 20 30 40 50 60 70 80
然后写入汇编指令
将20用作内存段地址,将20也用作栈内存段地址
栈顶处于20:30处
push [0],将20:0 处的值放入栈中,sp-2,然后放入,所以20:2E处为10 20
push [2],将20:0 处的值放入栈中,sp-2,然后放入,所以20:2C处为30 40
以此类推
pop [6]将栈顶元素放入内存单元0处,先放入,后sp+2,所以20:6处为70 80
以此类推
20:04 50 60
20:02 30 40
20:00 10 20
接下来进行实际操作,查看情况
可以看到符合分析
如果把最后四条指令改成截图中的顺序, pop [6] 指令执行结束后,使用d命令 d 20:0 7 查看此时数据空间内的数据是否有变化。
分析:会变成70 80 50 60 30 40 10 20
可以看到符合分析
栈段和栈顶指针
在debug环境中,实践以下内容。
先使用f命令,把00220H ~ 0022fH区间的16个字节内存单元值全部修改为0。并使用d命令查看确认。
然后,使用a命令、r命令、t命令写入汇编指令并单步调试。
观察并思考:
问题1:使用t命令单步执行 mov ss, ax 时,是单步执行完这一条指令就暂停了吗?后面的指令 mov
sp, 30 是什么时候执行的?
问题2:根据汇编指令,前三条指令执行后,00220H ~ 0022fH被设置为栈空间。并且,初始时,已通
过f命令将初始栈空间全部填充为0。观察单步调试时,栈空间00220H ~ 0022fH内存单元值的变化,特
别是图示中黄色下划线表示出的数据值。根据实验观察,尝试思考和分析原因。
对于问题1的解答:mov ss,ax和mov sp,30 连续执行。在此期间CPU不响应其他中断,debug的单步调试就是一种中断,由于CPU在执行期间不响应中断请求,所以debug显示的是CPU执行完栈段和栈顶指针分配后的情况。
对于问题2的解答:08 01 是IP地址,即偏移地址。3F 07 是CS地址,即程序段地址,是暂存地址,因为存在中断,所以需要暂存原来程序的入口,所以存了下来。
程序段前缀
使用任何一款文本编辑器,编写8086汇编程序源码。
assume cs:code
code segment
start:
mov cx, 10
mov dl, '0'
s: mov ah, 2
int 21h
add dl, 1
loop s
mov ah, 4ch
int 21h
code ends
end start
使用masm、link,汇编、链接,得到可执行文件task5.exe。运行程序。结合程序运行结果,理解程序功能。使用debug工具,调试task5.exe。根据第4章所学知识,任何可执行程序在执行时,都有一个引导程序负责将其加载到内存,并将CPU控制权移交给它,也即将CS:IP指向可执行程序中第一条机器指令。在加载可执行程序时,可执行前面512字节是程序段前缀PSP(Program Segment Prefix),用于记录程序一些相关信息。在debug中,使用d命令,查看task5.exe的程序段前缀,观察这256个字节的内容,验证前两个字节是否是CD 20。
程序运行结果如下:
可以看到在shell中输出了1234567890
调用int 21h系统中断,执行shell输出操作。中断参数放在ax寄存器中,参数为0002。
查看程序段前缀
可以看到CD 20以及程序名
程序复制
可以看到完美复制。
具体代码如下
assume cs:code
code segment
mov ax,cs
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,cx
s:mov al,ds:[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
分析:cs是程序入口段地址。cx是程序长度