汇编语言程序设计
<p align="center">汇编语言程序设计</p><p align="center">第二章</p>
<p>1 通用数据寄存器--以AX为例</p>
<p> 1.1 最大值:2^16-1</p>
<p> 例:在AX中存储18D</p>
<p> 18D</p>
<p> -12H</p>
<p> -10010B</p>
<p> 1.2 8086为16位寄存器,如何保证程序兼容性</p>
<p> l 将通用寄存器分为两个独立的8位寄存器</p>
<p> l 细分:AX可以分为AH和AL</p>
<p> 1.3 “字”在寄存器中的存储</p>
<p> 8086 是16位CPU</p>
<p> l 8086的字长为16bit</p>
<p> l 一个字可以存在一个16位寄存器中</p>
<p>2 mov和add指令(汇编语言不区分大小写)</p>
<p> 2.1 mov ax,18 将18送入AX中 ax=18</p>
<p> mov ah,78 将78送入AH中 ah=78</p>
<p> add ax,8 将寄存器AX的值加8 ax=ax+8</p>
<p> mov ax,bx 将bx值说送入ax中 ax=bx</p>
<p> add ax,bx 将ax,bx内容相加存入ax ax=ax+bx</p>
<p> 2.2 在进行运算时无论是ah,al还是ax只要发生溢出,都会舍弃溢出值保留剩下的值</p>
<p> </p>
<p>3 确定物理地址的方法</p>
<p> 3.1 cpu访问内存单元时要给出内存单元的地址</p>
<p> 3.2 所有的内存单元构成的存储空间是一个一维的线性空间</p>
<p> 3.3 每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址</p>
<p> 3.4 事实8086有20位地址总线,可传送20位地址,寻址能力为1M(2^16)</p>
<p> 3.5 8086是16位结构的CPU</p>
<p> 3.5.1 运算器一次最多可以处理16位数据,寄存器的最大运算宽度为16位</p>
<p> 3.5.2 在8086内部处理、传输、暂存的地址也是16位,寻址能力只是64K</p>
<p> 3.6 解决方案:</p>
<p> 3.6.1 用两个16位地址(段地址、偏移地址)和成一个20位的物理地址</p>
<p> 3.6.2 地址加法器合成物理地址的方法:物理地址=段地址x16+偏移地址</p>
<p> 3.6.3 本质意义</p>
<p> CPU在访问内存时,用一个基础地址(段地址x16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址</p>
<p>4 内存分段表示</p>
<p> 4.1 用分段的方式管理内存</p>
<p> 4.1.1 8086CPU用“(段地址x16)+偏移地址=物理地址”的方式给出内存单元的物理地址</p>
<p> 4.1.2 内存并没有分段,段的划分来自于CPU</p>
<p> 4.1.3 段地址x16必然是16的倍数,所以一个段的起始地址也一定是16的倍数</p>
<p> 4.1.4 偏移地址为16位,16位地址的寻址能力是64K,所以一个段地址的长度为64K。</p>
<p> 4.1.5 偏移地址16位,变化范围为0~FFFFH,用偏移地址最大寻址64K。</p>
<p> 4.1.6 例:数据在21F60H内存中,段地址是2000H,说法</p>
<p> 4.1.6.1 数据存在内存2000:1F60单元中(这里的2000是段地址,1F60是偏移地址)。</p>
<p> 4.1.6.2 数据存在内存中2000H段中的1F60H中。</p>
<p> 4.1.6.3 段地址很重要</p>
<p> 4.1.6.3.1 CS-代码段寄存器 DS-数据段寄存器</p>
<p> SS-栈段寄存器 ES-附加段寄存器</p>
<p>5 Debug调试工具</p>
<p> 5.1.1 Debug是DOS系统中的著名的调试程序,也可以运行在windows系统模式下</p>
<p> 5.1.2 使用Debug程序,可以观察CPU各种寄存器中内容,内存的情况,并且在机器指令级跟踪程序的运行。</p>
<p> 5.1.3 R-查看、改变CPU寄存器的内容</p>
<p> 5.1.3.1 R:查看寄存器的内容</p>
<p> 5.1.3.2 R 寄存器名:改变指定寄存器内容(空格可加可不加)</p>
<p> 5.1.4 T-单步调试,执行机器指令</p>
<p> 5.1.4.1 T:执行CS:IP中的指令</p>
<p> 5.1.5 D-查看内存中的内容</p>
<p> 5.1.5.1 D:列出预设地址内存处的128个字节的内容</p>
<p> 5.1.5.2 D 段地址:偏移地址:列出内存中指定地址处的内容</p>
<p> 5.1.5.3 D 段地址:偏移地址 结尾偏移地址:列出内存中指定地址范围内的内容</p>
<p> 5.1.6 E-改变内存中的内容</p>
<p> 5.1.6.1 E 段地址:偏移地址:数据1数据2</p>
<p> 5.1.6.2 E段地址:偏移地址</p>
<p> 逐个访问式修改</p>
<p> 空格:接受,继续</p>
<p> 回车:结束</p>
<p> 内存中的数据可以是数据,也可以是代码,完全取决于完美自己。</p>
<p> 5.1.7 U-将机器指令翻 译成汇编指令</p>
<p> 5.1.7.1 U 地址:查看代码</p>
<p> 5.1.8 A-以汇编指令的形式在机器中写入机器指令</p>
<p> 5.1.8.1 A 地址:写入汇编指令。(一般情况写在CS中,IP是偏移地址)出现错误继续输入就可以了。</p>
<p> 5.1.9 Q:退出Debug</p>
<p> 5.2 修改CS,IP指令</p>
<p> 5.2.1 事实:执行指令取决于CS:IP</p>
<p> 5.2.2 应用:可以通过改变CS:IP的内容,控制CPU主要执行的目标指令,但是现在是不通过debug修改的。</p>
<p> 5.2.3 指令修改的方法</p>
<p> 5.2.3.1 首先mov cs,2000h mov ip,0000H 是不行的。</p>
<p> 5.2.3.2 唯一可以改变的是间接修改cs的值,且ip的值是无法间接修改的,也就是说,汇编中是不太支持,程序去修改内存地址的。</p>
<p> Mov ax,2000H 赋值</p>
<p> Mov cs,ax 可以运行</p>
<p> Mov ip,ax 错误</p>
<p> 5.2.3.3 所以引用了跳转指令 jmp(转移指令)</p>
<p> 5.2.3.3.1 Jmp 段地址:偏移地址</p>
<p> 功能:用指令中给出的段地址修改CS,偏移地址修改IP</p>
<p> 5.2.3.3.2 仅修改IP的内容</p>
<p> Jmp 某一合法寄存器</p>
<p> Jmp ax(ax中保存的是一个偏移地址,类似于mov ip,ax(只是有相同的意思,但是现实中确是没有的))</p>
<p>6 内存中字的存储</p>
<p> 6.1 事实:对于8086CPU,16位为一个字</p>
<p> 6.2 问题:16位字的储存在一个16位的寄存器中,如何存储</p>
<p> 回答:高8位放在高字节,低8位放在低字节</p>
<p> 6.3 问题:16位的字在内存中需要2个连续字节,怎么存放</p>
<p> 回答:低字节存放在低8位,高字节存放在高8位</p>
<p> 6.4 字单元</p>
<p> 6.4.1 字单元:由两个地址连续的内存单元组成,存放一个字型数据(16位)</p>
<p> 6.4.2 原理:在一个字单元中,低地址单元存放的是低位字节,高地址单元存放高位字节。</p>
<p>7 DS和实现字节的传送</p>
<p> 7.1 要求:CPU在读取一个内存单元的时候,必须先给出这个内存单元的地址</p>
<p> 原理:内存地址由段地址和偏移地址组成</p>
<p> 解决方案:DS和</p>
<p> 用DS寄存器存放要访问的数据的段地址</p>
<p> 偏移地址用[…]形式直接访问</p>
<p> 7.2 将段地址存入DS两种方式</p>
<p> 7.2.1 Mov ds,1000h (错的)</p>
<p> 7.2.2 Mov bx,1000h</p>
<p> Mov ds,bx (对的)</p>
<p> 不支持直接将数据送入段地址中(硬件的设计问题)</p>
<p> 套路:数据->一般寄存器->段寄存器</p>
<p>8 DS与数据段-一般情况下降数据存入DS段地址中</p>
<p>9 栈及栈操作的实现</p>
<p> 9.1 栈是一种只能在一端进行插入或删除操作的数据结构</p>
<p> 9.2 栈有两个基本操作:出栈和入栈。</p>
<p> 入栈:将一个新的元素放到栈顶。</p>
<p> 出栈:从栈顶取出一个元素。</p>
<p> 9.3 栈顶的元素总是最后入栈,需要出栈时,又最是先被从栈中取出。</p>
<p> 栈底就是第一个进栈的数据,栈顶就是最后一个进栈的数据。</p>
<p> 9.4 栈的操作规则:LIFO(last in first out,后进先出)</p>
<p> 9.5 PUSH(入栈)和POP(出栈)指令</p>
<p> push ax :将ax的数据送入栈中</p>
<p> pop ax :从栈顶取出数据送人ax</p>
<p> 以字(16位)为单位对栈进行操作。</p>
<p> 9.6 CPU是如何知道一段内存空间被当做栈来使用</p>
<p> 栈段寄存器SS 存放栈顶的段地址</p>
<p> 栈顶指针寄存器SP 存放栈顶的偏移地址</p>
<p> 9.7 执行push和pop的时候,如何知道那个单元时栈顶单元</p>
<p> 任意时刻,SS:SP指向栈顶元素</p>
<p> 9.8 过程</p>
<p> push ax</p>
<p> (1) SP=SP-2;</p>
<p> (2) 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶</p>
<p> pop ax</p>
<p> (1) 将SS:SP指向的内存单元的数据送入ax中</p>
<p> (2) SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。</p>
<p> (3) 栈越界的问题</p>
<p> 如何能够保证在入栈和出栈时,栈顶不会超过出栈空间。</p><br><br>
来源:https://www.cnblogs.com/-xxhh-/p/12501213.html
頁:
[1]