【汇编语言】第二章 寄存器
<p> </p><div class="toc">
<h3>目录</h3>
<ul>
<li>前言</li>
<li>2.1寄存器</li>
<li>
<ul>
<li>通用寄存器</li>
<li>字</li>
<li>字在寄存器中的存储</li>
</ul>
</li>
<li>2.2 mov,add,sub指令</li>
<li>
<ul>
<li>mov指令</li>
<li>add指令</li>
<li>sub指令</li>
</ul>
</li>
<li>2.3 16位结构的CPU</li>
<li>2.4 物理地址</li>
<li>
<ul>
<li>8086CPU给出物理地址的方法</li>
</ul>
</li>
<li>2.5 段</li>
<li>
<ul>
<li>段的概念</li>
<li>段寄存器</li>
</ul>
</li>
<li>2.6 CS和IP</li>
<li>2.7 修改CS和IP指令</li>
<li>
<ul>
<li>jmp指令</li>
</ul>
</li>
<li>总结</li>
</ul>
</div>
<p> </p>
<h1>前言</h1>
<p>最近学了王爽教授写的《汇编语言》,整理一下学习笔记。</p>
<h1>2.1寄存器</h1>
<p><strong>寄存器</strong>是<strong>CPU</strong>内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。因此不同的<strong>CPU</strong>,寄存器的个数,结构是不相同的。<strong>8086CPU</strong>有14个寄存器,每个寄存器都有各自的名称,AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW。</p>
<p><strong>寄存器</strong>是可以<strong>用指令读写</strong>的部件,程序员可以通过<strong>改变寄存器的内容</strong>来实现<strong>对CPU的控制</strong>。</p>
<h2>通用寄存器</h2>
<p>在<strong>8086CPU</strong>中寄存器都是<strong>16</strong>位的,可以存放两个字节。<strong>AX,BX,CX,DX</strong>这四个寄存器用来存放一般性的数据,因此叫做<strong>通用寄存器</strong>。</p>
<p><strong>8086CPU</strong>中<strong>一个16位</strong>寄存器被分为<strong>两个8位</strong>寄存器,以<strong>AX</strong>为例,分别为<strong>AX</strong>的<strong>高8位</strong>(<strong>AH</strong>)和<strong>低8位</strong>(<strong>AL</strong>)。<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165217050-1273352045.png" alt="" loading="lazy"></p>
<h2>字</h2>
<p><strong>字</strong>,<strong>word</strong>,一个字有两个字节构成,类比上面16位寄存器分成两个8位寄存器,这两个字节又分别称为这个字的<strong>高位字节</strong>和<strong>低位字节</strong>。<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165228608-1749566726.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 以AX寄存器为例,将16位寄存器的高8位和低8位与字的高位字节和低位字节对比,不难发现,<strong>AX</strong>在存储一个字时,<strong>AH</strong>存高位字节,<strong>AL</strong>存低位字节。</p>
<h2>字在寄存器中的存储</h2>
<p>以十进制数<strong>20000</strong>为例,它的十六进制数为<strong>4E20H</strong>(这里的H并不是数值,它放在数值的末尾表示这个数是16进制数),它的二进制数为<strong>0100111000100000</strong>,它在<strong>AX</strong>中的存储情况为<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165240953-400564845.png" alt="" loading="lazy"></p>
<h1>2.2 mov,add,sub指令</h1>
<h2>mov指令</h2>
<p>mov,<strong>数据传输指令</strong>,传送<strong>字</strong>或<strong>字节</strong>,比如 “<strong>mov ax 8</strong>”表示“<strong>将8送入寄存器ax</strong>(<strong>AX</strong>跟<strong>ax</strong>都是一个寄存器,不区分大小写)”,mov指令可以有以下几种形式:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165254052-259185457.png" alt="" loading="lazy"></p>
<h2>add指令</h2>
<p>add,<strong>算数运算指令</strong>,<strong>加法</strong>,比如“<strong>add ax 8</strong>” 表示 “<strong>将寄存器ax中的数值加上8</strong>”,同时add指令也有以下形式:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165306170-1499424604.png" alt="" loading="lazy"></p>
<h2>sub指令</h2>
<p>sub,<strong>算数运算指令</strong>,<strong>减法</strong>,比如“<strong>sub ax 8</strong>” 表示 “<strong>将寄存器ax中的数值减去8</strong>”,同时sub指令也有以下形式:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165317047-2027567820.png" alt="" loading="lazy"></p>
<h1>2.3 16位结构的CPU</h1>
<p>一个CPU由<strong>运算器</strong>,<strong>控制器</strong>,<strong>寄存器</strong>等器件构成,这些器件靠<strong>内部总线</strong>相连,上一章说的总线(数据,地址,控制总线)相对于CPU是<strong>外部总线</strong>。</p>
<p><strong>内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系</strong>。可以概括为以下几点:<br> <strong>(1)运算器进行信息处理<br> (2)寄存器进行信息处理<br> (3)控制器控制各种器件进行工作<br> (4)内部总线连接各种器件,在它们之间进行数据的传送。</strong></p>
<p><strong>我们知道8086CPU是16位结构的CPU,这个16位是什么意思呢?</strong></p>
<p>它其实描述了CPU的以下特性:<br> <strong>(1)运算器一次最多可以处理16位的数据<br> (2)寄存器的最大宽度为16位<br> (3)寄存器和运算器之间的通路为16位</strong></p>
<p>要知道,内存单元的地址在送往地址总线之前,要在CPU中处理,传输,暂时存放,所以16位CPU能一次性处理,传输和暂时存储16位的地址以及最大长度为16位的信息。</p>
<h1>2.4 物理地址</h1>
<p><strong>物理地址</strong>(Physical Address),又叫<strong>实际地址</strong>或<strong>绝对地址</strong>。在存储器里以字节为单位存储信息,所有的内存单元构成存储空间,为正确地存放或取得信息,<strong>每一个内存单元在空间中都有唯一的地址</strong>,这个地址就是物理地址。</p>
<p>地址从<strong>0</strong>开始编号,顺序地每次加<strong>1</strong>,因此存储器的物理地址空间是<strong>呈线性增长</strong>的。它是用二进制数来表示的,是<strong>无符号整数</strong>,书写格式为<strong>十六进制数</strong>。</p>
<h2>8086CPU给出物理地址的方法</h2>
<p><strong>16</strong>位结构的<strong>8086CPU</strong>有<strong>20</strong>位地址总线,可以传送<strong>20</strong>位地址,达到<strong>1MB</strong>的寻址能力,但它是<strong>16</strong>位结构,在内部一次性传输,处理,暂时存储的地址为<strong>16</strong>位,表现出的寻址能力只有<strong>64KB</strong>,所以问题来了</p>
<p><strong>它是怎么形成一个20位的物理地址呢?</strong></p>
<p><strong>806CPU是采用在内部用两个16位地址合成的方法来形成一个20位的物理地址</strong><br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165332307-751315737.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 其运行的步骤如下:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165344594-1478552879.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 地址加法器采用 <strong>物理地址 = 段地址*16 + 偏移地址</strong>的方法用段地址和偏移地址合成物理地址。</p>
<p>例如<strong>8086CPU</strong>访问地址为<strong>123C8H</strong>的内存单元,其地址加法器的工作流程如下(图中数字皆为16进制数)<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165356677-1175895876.png" alt="" loading="lazy"></p>
<p> 其实说白了,<strong>段地址*16</strong>就是16进制段地址<strong>左移一位</strong>。但问题又来了</p>
<p><strong>这个公式是怎么个思想呢?</strong> 举个例子:<br> 从家到网吧要走<strong>2222</strong>米,当走了<strong>222</strong>米时会经过学校</p>
<p><strong>家–222米----学校-------2000米-----------------------------------网吧<br> 家-------------------------2222米-------------------------------------网吧</strong></p>
<p>我现在要记录下我从家走到学校的距离,很显然这个距离是个四位数,但我一次性只能写三位数,于是我可以记录下这样的三位数字<strong>200</strong>和<strong>222</strong>,然后用<strong>200</strong>(<strong>段地址</strong>)*<strong>10</strong> + <strong>222</strong>(<strong>偏移地址</strong>)= <strong>2222</strong>(<strong>物理地址</strong>),就可以得到总距离了。<strong>8086CPU</strong>就是这样只能提供两个三位数的CPU。</p>
<h1>2.5 段</h1>
<h2>段的概念</h2>
<p><strong>段</strong>的划分来自于CPU,由于8086CPU用“<strong>段地址*16+偏移地址=物理地址</strong>”的方式给出内存单元的物理地址,使得我们可以用<strong>分段</strong>的方法管理内存。如图所示:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165411081-2143982945.png" alt="" loading="lazy"></p>
<p> 由图可知<br> 左边的图,地址<strong>10000H-100FFH</strong>的内存单元组成一个段,该段的<strong>起始地址</strong>为<strong>10000H</strong>,<strong>段地址</strong>为<strong>1000H</strong>,<strong>大小</strong>为<strong>100H</strong>。右边的类比左边。</p>
<p>需要注意的是,偏移地址为<strong>16</strong>位,<strong>16</strong>位地址的寻址能力为<strong>64KB</strong>,所以<strong>一个段的长度最大为64KB</strong>。</p>
<p>前面讲到了段地址和偏移地址,那么问题来了,<strong>什么东西提供段地址呢?</strong></p>
<h2>段寄存器</h2>
<p><strong>段地址</strong>在8086CPU的<strong>段寄存器</strong>中存放,<strong>8086CPU</strong>有<strong>4</strong>个段寄存器,<strong>CS</strong>,<strong>DS</strong>,<strong>SS</strong>,<strong>ES</strong>。当8086CPU访问内存时,由这四个段寄存器提供内存单元的段地址。</p>
<h1>2.6 CS和IP</h1>
<p><strong>CS</strong>和<strong>IP</strong>是8086CPU中两个最关键的寄存器,它们<strong>指示了CPU当前要读取指令的地址</strong>。<br> <strong>CS放段地址,IP放偏移地址</strong>。8086机中,任意时刻,CPU将<strong>CS:IP</strong>指向的内容当作指令执行。<br> 举个例子,看下图:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165429954-719576949.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 图中的说明如下:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165440956-41606349.png" alt="" loading="lazy"></p>
<p> </p>
<p> </p>
<p> 其运行步骤如下:<br> (1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器<br> (2)IP=IP+所读取指令的长度,从而指向下一条指令<br> (3)执行指令,转到步骤(1)重复整个过程。</p>
<h1>2.7 修改CS和IP指令</h1>
<h2>jmp指令</h2>
<p>(1)想要<strong>同时修改CS</strong>和<strong>IP</strong>的指令,可以用形如“<strong>jmp 段地址:偏移地址</strong>”的指令完成。如下:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165458396-330666651.png" alt="" loading="lazy"></p>
<p> (2)想要只修改IP的内容,可以用形如“<strong>jmp 某一合法寄存器</strong>”。如:<br><img src="https://img2023.cnblogs.com/blog/3079609/202303/3079609-20230318165508990-863378665.png" alt="" loading="lazy"></p>
<h1>总结</h1>
<p>以上为本人学习汇编语言时的摘录总结,主要内容来源于汇编语言(第四版) 王爽 著,大家若是感兴趣可以看看原书,很值得推荐,以上内容如果有什么错误的话,还请大家指正!</p><br><br>
来源:https://www.cnblogs.com/Seversan-Sickle/p/17228248.html
頁:
[1]