学习任何一门语言都不能少的了 debug ,汇编也是。
下面我们就依据这几个功能来跟踪一下程序的执行过程。
debug 对我们来说非常重要,有很多代码细节和问题通过肉眼是观察出来的,我们肉眼可能能够判断一些简单的程序问题,但是对于很多隐藏较深的问题,还是要依据 debug 才能发现。
下面是一段汇编代码,这段汇编代码我之前的文章中也给大家写过。
assume cs:codesg
codesg segment
mov ax,0123h
mov bx,0456h
add ax,bx
add ax,ax
mov ax,4c00h
int 21h
codesg ends
end
新建文本文件,把代码 cv 过去,然后右键保存,使用 dosbox 将其编译为 1.obj 文件,链接为 1.exe 文件后,我们使用 debug 1.exe
命令来分析一下这段程序,并用 -r 命令来看一下初始的寄存器情况。
程序初始状态下,可以看到 CX 中的数据为 000F,这也表示着程序的长度是 000F,1.exe 中共有 15 个字节,CX 中的内容为 000FH。
好,现在我们已经知道程序被成功的载入内存并运行起来了,但是我们现在先不妨想一下,被链接成为 EXE 的程序会被装入内存的哪个地方的呢?我们怎么知道程序被装入在哪里呢?
程序装载的过程分下面几步:
程序被装入内存后,由 DS 段寄存器存放着内存区的段地址,此时内存区域的偏移量为 0 ,所以此时的物理地址为 SA * 16:0,我们并不用知道真实的 DS 是多少,反正都是由操作系统和 DOS 分配的。
然后这个内存区域的前 256 个字节被用于存放 PSP ,所以程序的物理地址为 SA * 16 + 256 : 0 。
SA * 16 + 256 = SA * 16 + 16 * 16 = (SA + 16) * 16 ,转换为 16 进制就是 SA + 10H,所以物理地址就是 SA + 10H : 0。
我们上面 debug 1.exe 之后可以看到,DS 段寄存器的值为 076AH ,而 CS 段寄存器的值为 076BH ,正好符合 076A * 16 + 10 = 076BH (注意这里的 * 16 就是左移 4 位的意思,之前文章中也解释过原因。)
我们使用 -u 指令可以看到完整的汇编源代码。
上图中用红框圈出来的就是我们这段汇编程序的源代码,可以看到这是一个程序段,程序段的段地址始终为 076A,偏移地址在不断变化。
我们使用 -t 命令来单步执行以下这段程序,如下图所示。
(为了连续的观察一下程序的执行结果,我索性直接把主要的程序步骤执行完了。)
这段程序就是 mov 和 add 的基本使用,将 0123 送入 AX 寄存器,将 0456 送入 BX 寄存器,对 AX 寄存器执行 AX = AX + BX ,再对 AX 执行 AX = AX + AX。
程序继续向下执行,当执行到 int 21H 处,程序执行完毕,此时要使用 -p 命令结束程序的执行,如下图所示。
当显示 Program terminated normally 时,表示程序正常结束,这里大家先不用考虑为什么执行到 int 21 处才执行 -p 命令,也不用关心 mov ax,4c00 和 int 21 是什么意思,大家先记住就行。
由于程序装载的过程是 command 将程序装载进入内存,然后 debug 程序对 exe 程序其进行跟踪,所以程序退出后也是先从 exe 程序退出到 debug 程序中,由 debug 程序再退回到 command 程序中。
下面再分析一段程序,汇编原代码
assume cs:codesg
codesg segment
mov ax,2000H
mov ss,ax
mov sp,0
add sp,10
pop ax
pop bx
push ax
push bx
pop ax
pop bx
mov ax,4c00H
int 21H
codesg ends
end
仍然是将其保存为 test.txt,然后执行编译和链接操作,将其生成可执行文件 test.exe,观察其执行过程。
我们先使用 -r 查看一下初始寄存器的内容。
主要观察一下 CX 、DS 、CS 和 IP 的值,是否和我们上面描述的一致,CX 存放程序长度,DS 存放程序段地址,CS 存放程序初始地址,IP 存放程序偏移地址。
再使用 -u 看一下 exe 程序的源代码,这个 exe 程序是经过编译和链接之后的程序。
我们来分析一下这段,这是一段栈段的入栈和出栈的程序,首先
mov ax,2000H
mov ss,ax
mov sp,0
是设置栈段的栈顶指令,执行完成后会设置栈顶的物理地址为 20000 H ,即 SS:SP = 2000:0000。
我们执行这个程序的过程中,发现 mov sp,0 这个指令为什么没有出现呢?难道是我们漏写了?查看了一下,源代码确实是有这条指令的,难道是没有执行?
为了验证这个假设,我们重新 debug 一下这段程序,然后先把 SP 的值进行修改,如下图所示。
刚开始,我们使用 -r 把 sp 的值改成 0002,然后单步执行,在执行到 mov ss,ax 之后,发现 SP 的值变为 0000,这也就是说 mov sp,0 这条指令其实是执行了的,只是 debug 模式下没有显示而已。
程序继续向下执行,下面是两个 pop 出栈操作。
pop ax 和 pop bx 做了两件事:把寄存器清空;栈顶位置 + 2 ,所以 ax 和 bx 寄存器的内容为 0 ,并且 SP = SP + 2 ,执行后 SP = 000E。
之后是两个 push 操作,把出栈的两个寄存器再进行入栈,如下图所示。
push 操作也做了两件事情,将寄存器入栈,SP = SP - 2,由于 ax 和 bx 已经 pop 出栈了,所以寄存器内容为 0 ,最后再进行 pop 操作,然后再结束程序的执行过程。
我们再来看一下 PSP 的情况,由于程序被装入的时候前 256 个字节是 PSP 所占用的,此时 DS(SA)处就是 PSP 的起始地址,而 CS = SA + 10H ,也就是 CS = 076AH。
下面我们来 debug 一下循环程序,看看有哪些有意思的细节。
现在有这样一道问题,计算 ffff:0006 单元中的数乘 3 ,让结果存储在 dx 中。
针对这个问题,有几个点需要思考:
所以这段汇编程序的代码如下
assume cs:codesg
codesg segment
mov ax,0ffffh
mov ds,ax
mov ah,0
mov al,[6]
mov cx,3
s: add dx,ax
loop s
mov ax,4c00h
int 21h
codesg ends
end
编写完毕,编译链接成 exe 程序后,对其进行 debug xxx.exe 操作。
我们来看下程序的执行过程。
前两段没毛病,设置 DS 段寄存器的值为 FFFF 。然后继续向下执行
执行到 mov al,[6] 的时候我发现,怎么 AX 寄存器中的内容变成 0006 了?我不是想要把 06 放入 ax 中啊,我是想把 ffff:06 内存单元中的值放入 ax 中啊,我突然意识到编译器是个傻子。
经过我认真仔细细心耐心用心的排查了一番问题之后,我方才大悟,原来我是个傻子!不知道各位小伙伴们看出来我代码的问题了吗?
我怎么敢在源程序中把立即数当做内存偏移地址来用呢?必须要用 bx 中转啊!
这也就是说,编译器编译完源代码之后,会把 06 当做立即数使用,如果想要使 06 表示内存地址,必须要用 bx 进行中转,修改之后的源代码如下:
assume cs:codesg
codesg segment
mov ax,0ffffh
mov ds,ax
mov bx,6
mov ah,0
mov al,[bx] # 必须要用 bx 进行中转,才能表示内存地址
mov dx,0 # 累加寄存器清 0
mov cx,3
s: add dx,ax
loop s
mov ax,4c00h
int 21h
codesg ends
end
然后再重新链接成为 exe 程序之后,我们一步一步 debug 看一下。
执行到 mov al,[bx] 的时候,我们发现,此时右侧有个 ds:0006 = 31,这段代码表示的是 ds:0006 处内存单元的值是 31,这才表明我们的程序是正确的。
继续向下执行程序。
前两条指令执行完成后,(dx) = 0 ,(cx) = 3,完成对累加寄存器的清空和循环计数器的赋值操作。最后一条指令是第一次循环操作指令,此时 CS:IP 指向 076A:0012 ,继续向下执行。
可以看到,第一次 add dx,ax 执行完成后 IP = 0014H ,此时指向的指令是 LOOP 0012,这条指令的意思是让程序再执行一次 (IP) = 0012H 处的指令,也就是再执行一次 add dx,ax,可以看到 cx 的值变成了 0002,因为循环指令执行后 (cx) = (cx) - 2 ,然后再向下执行,发现后面的循环指令还是 LOOP 0012 ,再执行一次 add dx,ax,一直到 (cx) = 0 后结束程序执行,如下图所示
可以发现,整个程序一共循环三次,最终 dx 中的值是 93 ,程序执行到 int 21H 处,使用 -p 命令结束程序的执行。
网站标题:来看三段程序,你学会了什么?
网站地址:http://www.csdahua.cn/qtweb/news31/445881.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网