《汇编语言》 学习笔记
<h1 id="汇编语言-学习笔记">《汇编语言》 学习笔记</h1><h2 id="第一章-基础知识">第一章 基础知识</h2>
<h3 id="11-机器语言">1.1 机器语言</h3>
<p>每一种微处理器,由于硬件设计和内部结构的不同,就需要<strong>不同的点评脉冲来控制</strong>,使他工作。所以<strong>每一种微处理器都有自己的机器指令级</strong>,也就是机器语言。</p>
<h3 id="12-汇编语言的产生">1.2 汇编语言的产生</h3>
<p><img src="https://img-blog.csdnimg.cn/d6b4c927a3fa4771ac7d2d050677fc0f.png" alt="image-20220220002459635" loading="lazy"></p>
<p>此后,程序员使用<strong>汇编指令</strong>编写源程序,这时候就需要使用<strong>编译器</strong>,将汇编指令转成机器指令的编译程序。</p>
<p><img src="https://img-blog.csdnimg.cn/23c4f8afb6ba4bb8b4aefedb13a068b4.png" alt="image-20220220002729801" loading="lazy"></p>
<h3 id="13-汇编语言的组成">1.3 汇编语言的组成</h3>
<p>汇编语言发展至今,有以下三类指令组成</p>
<ol>
<li>
<p><strong>汇编指令</strong>:机器码的助记符,有对应的机器码</p>
</li>
<li>
<p><strong>伪指令</strong>:没有对应的机器码,由编译器执行,计算机并不执行。</p>
</li>
<li>
<p><strong>其他符号</strong>:如<code>+,-,*,、\</code>等,由编译器识别,没有对应的机器码。</p>
<p><strong>汇编语言的核心是汇编指令,它决定了汇编语言的特性。</strong></p>
</li>
</ol>
<h3 id="14-存储器">1.4 存储器</h3>
<p>存储器中存储CPU需要的指令与数据,也就是平时所说的内存。</p>
<h3 id="15-指令与数据">1.5 指令与数据</h3>
<p>在内存或磁盘上,指令与数据没有任何区别,都是二进制信息。</p>
<p>CPU在工作时才会赋予不同意义,使其发挥不同的作用。</p>
<p><img src="https://img-blog.csdnimg.cn/a0cf3f9a073046108c27d58e60d30c6a.png" alt="image-20220220005158751" loading="lazy"></p>
<h3 id="16-存储单元">1.6 存储单元</h3>
<p><strong>存储器被划分成若干个存储单元</strong>,<strong>每个存储单元从0开始顺序编号</strong>,例如一个存储器有128个存储单元,编号从0~127,如下图所示</p>
<p><img src="https://img-blog.csdnimg.cn/3716feff02004c3a9bc091758c6e197a.png" alt="image-20220220005543172" loading="lazy"></p>
<p><strong>这些编号可以看作存储单元在存储器中的地址</strong></p>
<p><strong>计算机最小的信息单元为bit</strong>(音译为比特),也就是<strong>一个二进制位</strong></p>
<p>8个bit组成一个<strong>Byte</strong>,也就是<strong>一个字节</strong></p>
<p><strong>微型机存储器</strong>:<strong>每个存储单元可以存储一个Byte</strong>即8个二进制位,一个存储器有128个存储单元,它可以存储128个Byte,即1024个二进制位。微机存储器的容量是<strong>以字节为最小单位</strong>。</p>
<p><strong>大容量存储器</strong>:一般用以下单位计量容量(以下B代表Byte)</p>
<ul>
<li>1KB = 1024B</li>
<li>1MB = 1024KB</li>
<li>1GB = 1024MB</li>
<li>1TB = 1024GB</li>
</ul>
<h3 id="17-cpu对存储器的读写">1.7 CPU对存储器的读写</h3>
<p>CPU要从内存中读数据,首先要指定存储单元的地址。</p>
<p>在微机中,不只有存储器这一种期间,所以CPU在读写数据的时候还要指明,它要对那个器件进行操作,进行那种操作,从中读取数据,还是向里面写入数据。</p>
<p>可见,<strong>CPU要进行数据读写,必须和外部器件,进行下面3类的信息交互</strong></p>
<ul>
<li><strong>地址信息</strong>:存储单元的地址</li>
<li><strong>控制信息</strong>:器件的选择,读或写的命令</li>
<li><strong>数据信息</strong>:读或写的数据</li>
</ul>
<p>电子计算机能处理、传输的信号都是电信号,要是用导线传送。在计算机中专门有连接CPU和其他芯片的导线,通称为<strong>总线</strong>。</p>
<p><strong>总线根据传送信息的不同,从逻辑上分为3类,地址总线、控制总线和数据总线。</strong></p>
<p>CPU从3号单元<strong>读取数据</strong>的过程如下:</p>
<p><img src="https://img-blog.csdnimg.cn/e914b3017cf5487fb51c6bf4a61ba2f0.png" alt="image-20220220011811726" loading="lazy"></p>
<ol>
<li>CPU通过<strong>地址线</strong>将地址信息<code>3</code>发出</li>
<li>CPU通过<strong>控制线</strong>发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据</li>
<li>存储器将3号单元中的数据<code>8</code>通过<strong>数据线</strong>送入CPU</li>
</ol>
<p>要让一个计算机或者危机处理器工作,影响他输入能够驱动他进行工作的电平信息(机器码)</p>
<p>对于8086CPU,下面的代码能实现从3号单元读取数据</p>
<p>机器码:<code>10100001 00000011 00000000</code></p>
<p>汇编指令:<code>MOV AX,</code></p>
<p>含义:传送<code>3</code>号单元的内容入寄存器<code>AX</code></p>
<h3 id="18-地址总线">1.8 地址总线</h3>
<p><strong>地址总线上能够传多少个不同信息,CPU就能对多少个存储单元进行寻址。</strong></p>
<p><strong>地址总线的宽度决定了CPU的寻址能力。</strong></p>
<p>在电子计算机中,一根导线可以传送的稳定状态只有两种,高电平或是低电平,用二进制表示就是1或者0,10跟导线可以传送10位二进制数据,<strong>10位二进制数据可以表示2的10次方个不同的数据,最小为0最大为1023。</strong></p>
<p><strong>一个CPU有N跟地址线,则可以说这个CPU的地址总线宽度为N,这样的CPU最多可以寻找2的N次方个内存地址(Byte)</strong></p>
<p>下图展示了一个具有10跟地址线的CPU向内存发出地址信息11时10跟地址总线上传送的二进制信息</p>
<p><img src="https://img-blog.csdnimg.cn/9059326d49944ec2a3b85f89aac65593.png" alt="image-20220220013429547" loading="lazy"></p>
<p>若<strong>访问地址为12</strong>时,地址总线上穿得内容就是12的二进制数据即<code>000000 1100</code></p>
<p><strong>访问地址13</strong>时,地址总线数据为<code>000000 1101</code></p>
<p><strong>访问地址14</strong>时,地址总线数据为<code>000000 1110</code></p>
<h3 id="19-数据总线">1.9 数据总线</h3>
<p><strong>CPU与内存或其他器件之间的数据传送是通过数据总线进行的。</strong></p>
<p><strong>数据总线的宽度决定了CPU与外界的数据传送速度。</strong></p>
<p><strong>8跟数据总线一次可以传一个8位二进制数据(即一个字节),16根数据总线一次可传送两个字节。</strong></p>
<p><img src="https://img-blog.csdnimg.cn/35aae01d6c744b63bca4ed2f7244cf0f.png" alt="image-20220220014252766" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/1a243738f9644b598003f9ee5d9c0bd1.png" alt="image-20220220014307262" loading="lazy"></p>
<h3 id="110-控制总线">1.10 控制总线</h3>
<p><em>CPU对外部器件的控制是通过控制总线进行的</em>,控制总线是个总称,<em>是一些不同的控制线的集合</em>。<strong>有多少跟控制总线,就意味着CPU提供了对外器件的多少种控制</strong></p>
<p>所以,控制总线的宽度<strong>决定了</strong>CPU对外部器件的控制能力。</p>
<p>前面所讲的内存读或写是由几根控制总线综合发出的,其中一个称为“<strong>读信号输出</strong>”的控制线负责由CPU向外传送读信号,CPU向该控制线上输出低电压表示将要读取数据;有一个称为“<strong>写信号输出</strong>”的控制总线负责传送写信号。</p>
<h3 id="111-内存地址空间概述">1.11 内存地址空间(概述)</h3>
<p>系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受CPU寻址能力的限制,这个逻辑存储器即使我们所说的内存地址空间。</p>
<h3 id="112-主板">1.12 主板</h3>
<p><strong>主板上有核心器件和一些主要器件,这些器件通过总线(地址总线、数据总线、控制总线)相连。</strong>这些器件有CPU、存储器、外围芯片组、扩展插槽等。扩展插槽上一般插有RAM内存条和各类接口卡。</p>
<h3 id="113-接口卡">1.13 接口卡</h3>
<p>CPU对外部设备无法直接控制,如显示器、音响、打印机等。直接控制这些设备进行工作的是插在拓展插槽上的接口卡。拓展插槽通过总线和CPU相连,所以接口也通过总线同CPU相连。</p>
<p><strong>总的来说,CPU通过总线向接口卡发送命令,接口卡根据CPU的命令控制外设进行工作。</strong></p>
<h3 id="114-各类存储器芯片">1.14 各类存储器芯片</h3>
<p>这些存储器芯片从物理连接上看是独立的、不同的器件。从<strong>读写属性上看</strong>分为两类:</p>
<ul>
<li><strong>随机存储器(RAM)</strong>:可读可写,关机后存储内容丢失</li>
<li><strong>只读存储器(ROM)</strong>:只能读取不能写入,关机后其中内容不丢失</li>
</ul>
<p><strong>从功能和连接上看</strong>可分为三类:</p>
<ul>
<li>
<p><strong>随机存储器</strong>:</p>
<p>用于存放供CPU使用的绝大部分程序和数据,主随机存储器一般由两个位置上的RAM组成,装在主板上的RAM和装在拓展插槽上的RAM。</p>
</li>
<li>
<p><strong>装有BIOS(Basic Input/output System,基本输入/输出系统)的ROM</strong></p>
<p>BIOS是由主板和各类接口卡(如显卡、网卡等)厂商提供的软件系统,可以通过它利用该硬件设备进行最基本的输入输出。在主板和某些接口上插有存储相应的BIOS的ROM。</p>
</li>
<li>
<p><strong>接口卡上的RAM</strong></p>
<p>某些接口卡需要对大批量输出、输出输出的数据进行展示存储,在其上装有RAM。最典型的就是显卡上的RAM,一般称为显存。</p>
<p><img src="https://img-blog.csdnimg.cn/379f99bcb29640b9bc89933216483e36.png" alt="image-20220220161533317" loading="lazy"></p>
</li>
</ul>
<h3 id="115-内存地址空间">1.15 内存地址空间</h3>
<p>CPU在操控存储器的时候,<strong>把存储器都当作内存来对待</strong>,把他们总的看作一个由若干存储单元组成的逻辑存储器,这个逻辑存储器就是我们所说的<strong>内存地址空间</strong>。</p>
<p><img src="https://img-blog.csdnimg.cn/eb4e4485df5c444ca9cb6811565e41f6.png" alt="image-20220228143638841" loading="lazy"></p>
<p>CPU向显存地址空间中,然后会被显卡输出到显示器上</p>
<p>CPU向显卡BIOS ROM写入数据,写入的单元内容不会改变</p>
<p><strong>内存地址空间的大小受CPU地址总线宽度的限制</strong></p>
<p> 8086CPU地址总线宽度为20,可以传送<code>2^20</code>个不同的地址信息(大小从0至2^20-1),则8086PC的内存地址空间的大小为1MB。同理80386CPU的总线宽度为32,内存空间的最大为4MB</p>
<p>我们基于计算机硬件系统编程的时候,必须知道这个系统的内存中的内存地址空间分配情况。当我们想在某类存储器中读写数据的时候,必须知道它的第一个单元的地址和最后一个单元的地址,才能保证读写操作是在预期的存储器中进行。</p>
<p>不同的内存地址空间分配情况不同,下图是8086PC机内存储地址空间分配的进本情况</p>
<p><img src="https://img-blog.csdnimg.cn/6e6ec5dad2334c53adc5ff2fe86e2761.png" alt="image-20220228201433581" loading="lazy"></p>
<p>向地址<code>C0000~FFFF</code>的内存单元写入数据的操作是无效的,因此这等于改写制度存储器中的内容。</p>
<p><img src="https://img-blog.csdnimg.cn/0989fb1d68984cbba57f7cf725f5d680.png" alt="image-20220228201641591" loading="lazy"></p>
<h2 id="第二章-寄存器">第二章 寄存器</h2>
<p>在CPU中</p>
<ul>
<li>
<p>运算器进行信息处理</p>
</li>
<li>
<p>寄存器进行信息存储</p>
</li>
<li>
<p>控制器控制各种器件进行工作</p>
</li>
<li>
<p>内部总线连接各种器件,在他们之间进行数据的传送</p>
</li>
</ul>
<p>对于一个汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序可以用指令读写的部件。程序员通过各种寄存器中的内容来实现对CPU的控制。</p>
<p>不同的CPU寄存器的个数、结构是不同的</p>
<h3 id="21-通用寄存器">2.1 通用寄存器</h3>
<p>8086CPU的所有寄存器都是<code>16</code>位的,可以存放<code>两字节</code></p>
<p>AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器。</p>
<p>以AX为例,寄存器的逻辑结构如图所示</p>
<p><img src="https://img-blog.csdnimg.cn/17b35d8763654c56ba74b3628588acb0.png" alt="image-20220228202422766" loading="lazy"></p>
<p>一个16位寄存器所能存储的数据的最大值约为两字节</p>
<p>8086CPU上一代CPU中的存储器都是8位的,为了保证兼容性,需要使得AX、BX、CX、DX这四个寄存器都可分为两个独立使用的8位寄存器使用。见下图</p>
<p><img src="https://img-blog.csdnimg.cn/b7d0051e50904067bfd5827bae79cea5.png" alt="image-20220228203013441" loading="lazy"></p>
<p><img src="https://img-blog.csdnimg.cn/54da80118f9f4e4e94b9a53483277f77.png" alt="image-20220228203649552" loading="lazy"></p>
<p>一个16位寄存器可以存储一个16位的数据,数据在寄存器中的存放情况如下图所示</p>
<p><img src="https://img-blog.csdnimg.cn/45351cf12d2e40ae9f528c3d78e51f34.png" alt="image-20220228203340810" loading="lazy"></p>
<h3 id="22-字在寄存器中的存储">2.2 字在寄存器中的存储</h3>
<p>8086CPU可以一次处理一下两种尺寸的数据</p>
<ul>
<li>字节:记为BYTE,一个字节由8个bit组成,可以存放在8位寄存器中</li>
<li>字:记为word,一个字由两个字节组成,这两个字节分别成为这个字的高位字节和低位字节。</li>
</ul>
<p>一个字可以存放在一个16位寄存器中,这个字的高位字节和低位字节自然存在这个寄存器的高8位寄存器和低8位寄存器中</p>
<h3 id="23-几条汇编指令">2.3 几条汇编指令</h3>
<table>
<thead>
<tr>
<th>汇编指令</th>
<th>控制CPU完成的操作</th>
<th>高级语言描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>mov ax,18</td>
<td>将18送入寄存器AX</td>
<td>AX=18</td>
</tr>
<tr>
<td>mov ah,78</td>
<td>将78送入寄存器AH</td>
<td>AH=78</td>
</tr>
<tr>
<td>add ax,8</td>
<td>将寄存器AX中的值加上8</td>
<td>AX=AX+8</td>
</tr>
<tr>
<td>mov ax,bx</td>
<td>将寄存器BX中的数据送入寄存器AX</td>
<td>AX=BX</td>
</tr>
<tr>
<td>add ax,bx</td>
<td>将AX和BX的值相加,结果存在AX中</td>
<td>AX=AX+BX</td>
</tr>
</tbody>
</table>
<p>汇编指令不区分大小写</p>
<table>
<thead>
<tr>
<th>程序段中的指令</th>
<th>指令执行后AX中的数据</th>
<th>指令执行后BX中的数据</th>
</tr>
</thead>
<tbody>
<tr>
<td>MOV AX,4E20H</td>
<td>4E20H</td>
<td>0000H</td>
</tr>
<tr>
<td>ADD AX,1406H</td>
<td>6226H</td>
<td>0000H</td>
</tr>
<tr>
<td>MOV BX,2000H</td>
<td>6226H</td>
<td>2000H</td>
</tr>
<tr>
<td>ADD AX,BX</td>
<td>8226H</td>
<td>2000H</td>
</tr>
<tr>
<td>MOV BX,AX</td>
<td>8226H</td>
<td>8226H</td>
</tr>
<tr>
<td>ADD AX,BX</td>
<td>044CH</td>
<td>8226H</td>
</tr>
</tbody>
</table>
<p>由于<code>ax</code>寄存器是16位寄存器只能存放4位十六进制的数据,但是在执行<code>add ax,bx</code>指令后<code>ax</code>为<code>1033C</code>,超出了ax寄存器的上限,所以<code>1044C</code>中的最高位<code>1</code>不能存放在<code>ax</code>寄存器中,最终<code>ax</code>寄存器中的数据为<code>044CH</code></p>
<p>再看一段程序的执行情况</p>
<table>
<thead>
<tr>
<th>程序段中的指令</th>
<th>AX</th>
<th>BX</th>
</tr>
</thead>
<tbody>
<tr>
<td>MOV AX,001AH</td>
<td>001AH</td>
<td>0000H</td>
</tr>
<tr>
<td>MOV BX,0026H</td>
<td>001AH</td>
<td>0026H</td>
</tr>
<tr>
<td>ADD AL,BL</td>
<td>0040H</td>
<td>0026H</td>
</tr>
<tr>
<td>ADD AH,BL</td>
<td>2640H</td>
<td>0026H</td>
</tr>
<tr>
<td>ADD BH,AL</td>
<td>2640H</td>
<td>4026H</td>
</tr>
<tr>
<td>MOV AH,0</td>
<td>0040H</td>
<td>4026H</td>
</tr>
<tr>
<td>ADD AL,85H</td>
<td>00C5H</td>
<td>4026H</td>
</tr>
<tr>
<td>ADD AL,93H</td>
<td>0058H</td>
<td>4026H</td>
</tr>
</tbody>
</table>
<p>程序的最后一条指令<code>mov al,93h</code>在执行前,<code>al</code>中的值为<code>C5H</code>,相加后为<code>158H</code>,但是由于<code>al</code>为8位寄存器,只能存放两位十六进制数据,所以最高位1丢失,<code>ax</code>中的值位<code>0058h</code></p>
<p>此时,<code>al</code>是作为一个独立的8位寄存器使用,和<code>ah</code>没有关系</p>
<p>若执行的是<code>add ax,93h</code>低8位的进位会存储在<code>ah</code>中,CPU再执行指令时,只认为有1个16位寄存器<code>ax</code>进行的是16位计算,执行完这条指令后,<code>ax</code>中的值变为<code>0158h</code>使用的寄存器是16位寄存器<code>ax</code>相当于<code>00C5H</code>加上<code>0093H</code></p>
<p><strong>错误指令:</strong></p>
<p> mov ax,bx ;<strong>在8位寄存器和16位寄存器之间传送数据</strong></p>
<p> mov bh,ax ;<strong>在16位寄存器和8位寄存器之间传送数据</strong></p>
<p> mov al,20000 ;<strong>8位寄存器最大可存放值为255的数据</strong></p>
<p> add al,100h ;<strong>将一个高于8位的数据加到一个8位寄存器中</strong></p>
<p><strong>检测</strong></p>
<p>只能使用目前学过的汇编指令,最多使用四条指令,编程计算2的4次方</p>
<pre><code class="language-asm">mov ax,2
add ax,ax
add ax,ax
add ax,ax
</code></pre>
<h3 id="24-物理地址">2.4 物理地址</h3>
<p>CPU在在访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯一的地址称为<strong>物理地址</strong>。</p>
<p>CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须要先在内部形成这个物理地址。</p>
<h3 id="25-16位结构的cpu">2.5 16位结构的CPU</h3>
<p>概括的说,16位结构(16位机,字长为16位)描述了一个CPU具有下面几方面的结构特性。</p>
<ul>
<li>
<p>运算器一次最多可以处理16位的数据</p>
</li>
<li>
<p>寄存器最大的宽度位16位</p>
</li>
<li>
<p>寄存器和运算器之间的通路为16位</p>
</li>
</ul>
<p>在十六位结构的CPU内部,能过一次性处理、传输、暂时存储的信息最大长度是16位的</p>
<h3 id="26-8086cpu给出物理地址的方法">2.6 8086CPU给出物理地址的方法</h3>
<p>8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址</p>
<p><img src="https://img-blog.csdnimg.cn/af1e17efa7f94988be292019de388751.png" alt="image-20220301111723273" loading="lazy"></p>
<p>如图所示,当8086CPU要读写内存时:</p>
<ol>
<li>
<p>cpu中的相关部件提供两个16位地址,一个段地址,另一个时偏移地址</p>
</li>
<li>
<p>段地址和偏移地址通过内部总线送入一个称为<strong>地址加法器</strong>的部件</p>
</li>
<li>
<p>地址加法器将两个16位地址合成一个20位的<strong>物理地址</strong></p>
</li>
<li>
<p>地址加法器通过内部总线将20位物理地址送入输入输出控制电路</p>
</li>
<li>
<p>输入输出控制电路将20位物理地址送上地址总线</p>
</li>
<li>
<p>20位物理地址被地址总线送到存储器</p>
</li>
</ol>
<p><img src="https://img-blog.csdnimg.cn/8cfd8765a98a4e70aaf7216074d04c64.png" alt="image-20220301112042771" loading="lazy"></p>
<p>其中,地址加法器采用<strong>物理地址=段地址*16+偏移地址</strong>的方法用段地址合成<strong>物理地址</strong></p>
<h3 id="27-段地址16偏移地址的本质含义">2.7 段地址*16+偏移地址的本质含义</h3>
<p><strong>CPU在访问内存时,用一个基础地址(段地址*16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。</strong></p>
<p>8086CPU中,段地址*16可看作<strong>基础地址</strong>(起始地址)</p>
<h3 id="28-段的概念">2.8 段的概念</h3>
<p>内存并没有分段,段的含义来自于CPU</p>
<p>以后在编程的时候可以根据需要,<strong>将若干连续的内存单元看作一个段,用段地址*16定位段的起始地址(及地址)用偏移地址定位段中的内存单元。</strong></p>
<p>有两点需要注意:<strong>段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址为16位,16位的地址寻址能力为64KB,所以一个段的长度最大为64KB。</strong></p>
<p>CPU可以用不同的段地址和偏移地址形成同一个物理地址</p>
<p>如果给定一个段地址,仅通过变化偏移地址来进行寻址,最多可以定位64KB个内存单元,因为<strong>偏移地址16位,变化范围为0~FFFFH</strong>。</p>
<h3 id="29-段寄存器">2.9 段寄存器</h3>
<p>段地址在8086CPU的段寄存器中存放,8086CPU有四个段寄存器,CS、DS、SS、ES。当8086CPU要访问内存时由这四个段寄存器提供内存单元的段地址</p>
<h3 id="29-cs和ip">2.9 CS和IP</h3>
<p>CS和IP时8086CPU中两个最为关键的寄存器,他们指示了CPU当前要读取地址的地址。</p>
<p><strong>CS为段寄存器,IP为指令寄存器</strong></p>
<p>在8086PC中任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存<strong>M*16+N</strong>单元开始,读取一条指令并执行</p>
<p>也可以这样表述,<strong>任意时刻,CPU将CS:IP指向的内容当作指令执行</strong></p>
<p><img src="https://img-blog.csdnimg.cn/a61bebd316744f49a939fff04e0d9a03.png" alt="image-20220301115435781" loading="lazy"></p>
<p>8086CPU的工作过程可以简要描述如下</p>
<ol>
<li><strong>从CS:IP所指向的内存单元读取指令,读取的指令进入指令缓冲区</strong></li>
<li><strong>IP=IP+所读取指令的长度,从而指向下一条指令</strong></li>
<li><strong>执行命令。转到步骤1,重复这个过程</strong></li>
</ol>
<p>在8086CPU加点启动或复位后(即CPU刚开始工作时),CS和IP被设置为CS=FFFFH,IP=0000H,即在刚启动时候,CPU从内存单元FFFF0H端元读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令</p>
<p>CPU将CS:IP指向的内存单元中的内容看作指令,因为,在任何时候,CPU将CS、IP中的内容当作指令的段地址偏移地址,用他们合成指令的物理地址,到内存中读取指令码。</p>
<h3 id="211-修改csip的指令">2.11 修改CS、IP的指令</h3>
<p><code>mov</code>指令不能设置CS、IP的值,需要使用<code>jmp</code>指令进行修改</p>
<p>若想修改CS、IP的内容,可以用形如"<strong>JMP 段地址:偏移地址</strong>"的指令完成,如</p>
<pre><code>jmp 2AE3:3
;执行后:CS=2AE3H IP=0003H,CPU将从2AE33H处读取指令
jmp 3:0B16
;执行后:CS=0003H IP=0B16H,CPU将从00B46H处读取指令
</code></pre>
<p>"<strong>JMP 段地址:偏移地址</strong>"的功能是:用指令中给出的段地址修改CS,偏移地址(IP)</p>
<p><code>jmp ax</code>在含以上等同于 <code>mov IP,ax</code></p>
<p><code>jmp 3:01B6</code>含以上等同于<code>mov CS,3 mov ax,01B6</code></p>
<p><strong>设CPU初始状态CS=2000H,IP=0000H,请写出指令执行序列</strong></p>
<p><img src="https://img-blog.csdnimg.cn/ed778092d0854040abaf76ff5e9b0c26.png" alt="image-20220303203536760" loading="lazy"></p>
<ol>
<li>当CS=2000H,IP=0000H时,CPU从<code>2000h*16+0h=20000h</code>处读取指令,读入的指令是:B8 22 66(MOV AX,6622H),读入后<code>IP=IP+3=0003h</code></li>
<li>指令执行后,CS=2000H(未变),IP=0003h,则CPU从内存<code>2000h*16+0003h=20003</code>处读取指令,读入的指令是EA 03 00 00 10(JMP 1000:0003),读入后<code>IP=IP+5=0008H</code></li>
<li>指令执行后,CS=1000H,IP=0003H,则CPU从内存<code>1000h*16+0003h=10003h</code>处读取指令,读入的指令是B8 00 00(MOV AX,0000)读入后<code>IP=IP+3=0006H</code></li>
<li>......</li>
</ol>
<p>分析后可知指令序列为</p>
<p>mov ax,6622h</p>
<p>jmp 100:3</p>
<p>mov ax,0000</p>
<p>mov bx,ax</p>
<p>jmp bx</p>
<p>mov ax,0123h</p>
<p>转到第三步执行</p>
<h3 id="212-代码段">2.12 代码段</h3>
<p><strong>将一段内存单元定义为一个段,将长度N(N<=64KB)的一簇代码,存在一组地址连续、起始地址是16倍数的内存单元中</strong></p>
<p>例如</p>
<pre><code class="language-asm">mov ax,0000 (B8 00 00)
add ax,0123h (05 23 01)
mov bx,ax (8B D8)
jmp bx (FF E3)
</code></pre>
<p>这段长度为10个字节的指令,存放在123B0H<sub>123B9H的一组内存单元中,我们可以认为,123B0H</sub>123B9H这段内存是用来存放代码的,是一个代码段,段地址为123BH,长度为10个字节。</p>
<p>为了执行上面的代码段,需要使<strong>CS=123BH、IP=0000H</strong></p>
<h3 id="实验1-查看cpu和内存用机器指令和汇编指令编程">实验1 查看CPU和内存,用机器指令和汇编指令编程</h3>
<p><strong>DEBUG基础指令</strong></p>
<ul>
<li>R 查看、改变CPU寄存器中的内容</li>
<li>D 查看内存中的内容</li>
<li>E 改写内存中的内容</li>
<li>U 将内存中的机器指令翻译成汇编指令</li>
<li>T 执行一条机器指令</li>
<li>A 以汇编指令的格式在内存中写入一条机器指令</li>
<li></li>
</ul>
<p>alt+enter 将dos窗口切换为全屏模式</p>
<p><strong>R 查看、改写寄存器中的值</strong></p>
</div>
<div id="MySignature" role="contentinfo">
A lion doesn't concern himself with the opinions of a sheep.<br><br>
来源:https://www.cnblogs.com/murkuo/p/16015313.html
頁:
[1]