app模板网站,莆田 做网站的公司,查询企业信息的官方网站,村级门户网站建设文章目录 前言1. do01.1 do0程序1.2 存放字符串#xff0c;得到完整的程序1.3 分析初步完成的程序1.4 正确的完整程序1.5 分析正确的完整程序 2. 设置中断向量3. 单步中断3.1 什么是单步中断#xff1f;3.2 CPU为什么要提供单步中断3.2.1 思考一下Debug功能3.2.2 Debug是如何… 文章目录 前言1. do01.1 do0程序1.2 存放字符串得到完整的程序1.3 分析初步完成的程序1.4 正确的完整程序1.5 分析正确的完整程序 2. 设置中断向量3. 单步中断3.1 什么是单步中断3.2 CPU为什么要提供单步中断3.2.1 思考一下Debug功能3.2.2 Debug是如何利用单步中断的3.2.3 可能的问题以及如何解决的 4. 响应中断的特殊情况4.1 说明情况4.2 举例说明 —— 栈相关寄存器的设置4.2.1 产生的原因4.2.2 反映在Debug中的情况 结语 前言 汇编语言是很多相关课程如数据结构、操作系统、微机原理的重要基础。但仅仅从课程的角度出发就太片面了其实学习汇编语言可以深入理解计算机底层工作原理提升代码效率尤其在嵌入式系统和性能优化方面有重要作用。此外它在逆向工程和安全领域不可或缺帮助分析软件运行机制并增强漏洞修复能力。 本专栏的汇编语言学习章节主要是依据王爽老师的《汇编语言》来写的和书中一样为了使学习的过程容易展开我们采用以8086CPU为中央处理器的PC机来进行学习。 1. do0
1.1 do0程序
do0程序的主要任务是显示字符串程序如下
do0:;设置ds:si指向字符串 mov ax, 0b800hmov es, axmov di, 12*16036*2 ;设置es:di指向显存空间的中间位置mov cx, 21 ;设置cx为字符串长度s: mov al, [si]mov es:[di], alinc siadd di, 2loop smov ax, 4c00hint 21hdo0end: nop1.2 存放字符串得到完整的程序
程序写好了可要显示的字符串放在那里呢
我们看下面完整的程序。
assume cs:code data segmentdb overflow
data endscode segment
start: mov ax, csmov ds, axmov si, offset do0 ;设置ds:si指向源地址mov ax, 0mov es, axmov di, 200h ;设置es:di指向目的地址mov cx, offset do0end - offset do0 ;设置cx为传输长度cld ;设置传输方向为正rep movsb;设置中断向量表mov ax, 4c00hint 21hdo0: mov ax, datamov ds, axmov si, 0 ;设置ds:si指向字符串mov ax, 0b800hmov es, axmov di, 12*16036*2 ;设置es:di指向显存空间的中间位置mov cx, 21 ;设置cx为字符串长度s: mov al, [si]mov es:[di], al inc siadd di, 2loop smov ax, 4c00hint 21h
do0end: nopcode ends
end start1.3 分析初步完成的程序
上面的程序看似合理可实际上却大错特错。
注意“overflow !“在上面程序的data段中。程序执行完成后返回它所占用的内存空间被系统释放而在其中存放的“overfow!”也将很可能被别的信息覆盖。
而do0程序被放到了0:200处随时都会因发生了除法溢出而被 CPU 执行0号中断程序很难保证 do0程序从原来程序所处的空间中取得的是要显示的字符串“overflow!”。
因为 do0 程序随时可能被执行而它要用到字符串“overflow!”所以该字符串也应该存放在一段不会被覆盖的空间中。
1.4 正确的完整程序
正确的程序如下。
assume cs:codecode segment
start: mov ax, csmov ds, axmov si, offset do0 ;设置ds:si指向源地址mov ax, 0mov es, axmov di, 200h ;设置es:di指向目的地址mov cx, offset do0end - offset do0 ;设置cx为传输长度cld ;设置传输方向为正rep movsb;设置中断向量表mov ax,4c00hint 21hdo0: jmp short do0startdb overflowdo0start:mov ax, csmov ds, axmov si, 202h ;设置ds:si指向字符串mov ax, 0b800hmov es, axmov di, 12*16036*2 ;设置es:di指向显存空间的中间位置mov cx, 21 ;设置cx为字符串长度s: mov al, [si]mov es:[di], alinc siadd di, 1mov al, 02h ;设置颜色mov es:[di], al add di, 1loop smov ax, 4c00hint 21h
do0end: nopcode ends
end start1.5 分析正确的完整程序
在最新的程序中将“overflow!”放到do0程序中程序执行时将标号 do0到标号 do0end 之间的内容送到 0000:0200处。 ❗注意因为在do0程序开始处的“overflow!”不是可以执行的代码所以在“overflow!”之前加上一条 jmp 指令转移到正式的 do0 程序。 当除法溢出发生时CPU 执行 0:200处的jmp指令跳过后面的字符串转到正式的do0程序执行。
do0程序执行过程中必须要找到“overfow!”那么它在哪里呢 首先来看段地址“overflow!”和 do0的代码处于同一个段中而除法溢出发生时CS中必然存放do0的段地址也就是“overflow!”的段地址 再来看偏移地址0:200处的指令为jmp short do0start这条指令占两个字节所以“overfow!”的偏移地址为202h。
2. 设置中断向量
下面将do0的入口地址0:200写入中断向量表的0号表项中使do0成为0号中断的中断处理程序。
0号表项的地址为0:0其中0:0字单元存放偏移地址0:2字单元存放段地址。
程序如下。
mov ax, 0
mov es, ax
mov word ptr es:[0*4], 200h
mov word ptr es:[0*42], 03. 单步中断
3.1 什么是单步中断 基本上CPU在执行完一条指令之后如果检测到标志寄存器的TF位为1则产生单步中断引发中断过程。 单步中断的中断类型码为1则它所引发的中断过程如下。
1取得中断类型码12标志寄存器入栈TF、IF设置为03CS、IP 入栈4(CS)(1*42)。(IP)(1*4)。
如上所述如果 TF1则执行一条指令后CPU 就要转去执行1号中断处理程序。
3.2 CPU为什么要提供单步中断
3.2.1 思考一下Debug功能
我们在使用 Debug的 t 命令的时候有没有想过这样的问题Debug如何能让CPU在执行一条指令后就显示各个寄存器的状态
我们知道CPU在执行程序的时候是从CS:IP指向的某个地址开始自动向下读取指令执行。也就是说如果CPU不提供其他功能的话就按这种方式工作只要CPU一加电它就从预设的地址开始一直执行下去不可能有任何程序能控制它在执行完一条指令后停止去做别的事情。 可是我们在Debug中看到的情况却是Debug可以控制CPU执行被加载程序中的一条指令然后让它停下来显示寄存器的状态。 Debug 有特殊的能力吗
显然没有
我们只能说Debug利用了CPU提供的一种功能。只有CPU提供了在执行一条指令后就转去做其他事情的功能Debug或是其他的程序才能利用CPU提供的这种功能做出我们使用T命令时的效果。
3.2.2 Debug是如何利用单步中断的
好了我们来简要地考虑一下Debug是如何利用CPU所提供的单步中断的功能的。 首先Debug 提供了单步中断的中断处理程序功能为显示所有寄存器中的内容后等待输入命令。 然后在使用t命令执行指令时Debug将TF设置为1使得CPU工作于单步中断方式下则在CPU执行完这条指令后就引发单步中断执行单步中断的中断处理程序所有寄存器中的内容被显示在屏幕上并且等待输入命令。
3.2.3 可能的问题以及如何解决的
那么接下来的问题是当TF1时CPU在执行完一条指令后将引发单步中断转去执行中断处理程序。注意中断处理程序也是由一条条指令组成的如果在执行中断处理程序之前TF1则CPU在执行完中断处理程序的第一条指令后又要产生单步中断则又要转去执行单步中断的中断处理程序在执行完中断处理程序的第一条指令后又要产生单步中断则又要转去执行单步中断的中断处理程序……
看来上面的过程将陷入一个永远不能结束的循环CPU永远执行单步中断处理程序的第一条指令。 CPU 当然不能让这种情况发生解决的办法就是在进入中断处理程序之前设置TF0。从而避免CPU在执行中断处理程序的时候发生单步中断。 这就是为什么在中断过程中有 TF0这个步骤我们再来看一下中断过程。
1取得中断类型码12标志寄存器入栈TF、IF设置为03CS、IP 入栈4(CS)(1*42)。(IP)(1*4)。 ✍最后CPU提供单步中断功能的原因就是为单步跟踪程序的执行过程提供了实现机制。 4. 响应中断的特殊情况
4.1 说明情况
一般情况下CPU 在执行完当前指令后如果检测到中断信息就响应中断引发中断过程。可是在有些情况下CPU在执行完当前指令后即便是发生中断也不会响应。
4.2 举例说明 —— 栈相关寄存器的设置
4.2.1 产生的原因
对于这些情况我们不一一列举只是用一种情况来进行说明。
在执行完向ss寄存器传送数据的指令后即便是发生中断CPU也不会响应。这样做的主要原因是ss:sp联合指向栈顶而对它们的设置应该连续完成。
如果在执行完设置ss的指令后CPU 响应中断引发中断过程要在栈中压入标志寄存器、CS和IP的值。而ss改变sp并未改变ss:sp指向的不是正确的栈顶将引起错误。
所以CPU在执行完设置ss的指令后不响应中断。这给连续设置ss和sp指向正确的栈顶提供了一个时机。 即我们应该利用这个特性将设置ss和sp的指令连续存放使得设置sp的指令紧接着设置ss的指令执行而在此之间CPU不会引发中断过程。 比如我们要将栈顶设为 1000:0应该
mov ax,1000h
mov ss,ax
mov sp,0
mov ax,0而不应该
mov ax,1000h
mov ss,ax
mov ax,0
mov sp,04.2.2 反映在Debug中的情况
Debug 利用单步中断来实现T命令的功能也就是说用T命令执行一条指令后CPU响应单步中断执行Debug设置好的处理程序才能在屏幕上显示寄存器的状态并等待命令的输入。
而在mov ss,ax指令执行后CPU 根本就不响应任何中断其中也包括单步中断所以Debug设置好的用来显示寄存器状态和等待输入命令的中断处理程序根本没有得到执行所以我们看不到预期的结果。
CPU接着向下执行后面的指令mov sp,10h然后响应单步中断我们才看到正常的结果。
结语
今天的分享到这里就结束啦如果觉得文章还不错的话可以三连支持一下。
也可以点点关注避免以后找不到我哦
Crossoads主页还有很多有趣的文章欢迎小伙伴们前去点评您的支持就是作者前进的动力