惹和惹和 發表於 2020-2-22 00:30:00

[课堂小笔记] 汇编语言

<p><strong><span style="font-size: 18px">第一章&nbsp;汇编语言基础</span></strong></p>
<p><strong><span style="font-size: 16px">&gt; 第一节课 20200217</span></strong></p>
<p>进制怎么转换就省略了。一些基本概念——</p>
<p>位 - bit,数据存储最小单位,两种状态——0和1;</p>
<p>字节 - byte,每8个bit组成一个byte,存放一个8位二进制数,CPU读写内存或外设的基本单位。</p>
<p>对于一个8位二进制数,如果是无符号数,则表示范围为0~255(2 ^ 8 - 1);如果是有符号数:</p>
<p>1、最高位表示符号,0为正,1为负;</p>
<p>2、表示范围为-127(1111 1111)~127(0111 1111);</p>
<p>3、先看原码、反码、补码给出的概念</p>
<p><strong>原码</strong>:可以理解为真值的绝对值(?)</p>
<p><strong>反码</strong>:x &gt; 0时,同等于原码;x &lt; 0时,除符号位全部取反。</p>
<p><strong>补码</strong>:x &gt; 0时,同等于反码;x &lt; 0时,在反码基础上+1。</p>
<p>特殊情况:0的原码和反码不是唯一的,分为+0和-0;但补码唯一,即0000 0000;</p>
<p>初看这概念就很奇怪,也不好记忆,但也没想太多。</p>
<p>然后今天老师说“如果是有符号数,表达式中的数就是补码”,就很懵,为什么?补码有什么特权吗?</p>
<p>带哲学家bebe说过,电脑里只存在补码这一种存储方式,也就是说原码、反码纯粹只是为了求出补码二弄出来的东西,本身没有实际用处。</p>
<p>而后我看了篇关于这个的回答,有点恍然大明白的感觉。</p>
<p>一个很不错的理解,用于给出补码求原值:</p>
<p>无视符号位说法,直接看成无符号型,即0~255范围;</p>
<p><strong>如果 0 &lt;= x补 &lt;= 127(0111 1111),x = x补;如果 128(1000 0000) &lt;= x补 &lt;= 255(1111 1111), x = x补 - 256(也就是符号位取1表负数)</strong></p>
<p>这样做的好处在于,不用纠结于有符号无符号和符号位这种反计算机逻辑的概念。</p>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18px">第二章 CPU和存储器</span></strong></p>
<p><strong><span style="font-size: 16px">&gt; 第二节课 20200221</span></strong></p>
<p>一些零散概念:</p>
<p>1、<strong>三总线:数据总线DB,地址总线AB,控制总线CB;</strong></p>
<p>DB:&nbsp;在CPU与存储器和CPU与I/O接口之间双向传送数据;传送数据信息;</p>
<p>AB:&nbsp;传送CPU发出的地址,以寻址存储单元或I/O端口;传送地址信息;地址总线是单向的;</p>
<p>CB:&nbsp;向计算机系统的各部件发送操作命令和定时信息;传送各种控制信号,如CPU向存储器或外设发读/写命令。</p>
<p><span style="background-color: rgba(255, 255, 255, 1)">(对于<strong>8086CPU</strong>,有16条DB,一次可以并行传送2个字节;AB宽度为20位,即有20条AB,可寻址内存空间为1MB(2 ^ 20 Byte))</span></p>
<p>2、8086CPU的逻辑结构分为:总线接口单元BIU,执行单元EU;</p>
<p><img src="https://img2018.cnblogs.com/common/790029/202002/790029-20200228141730880-379500351.png"></p>
<p>3、8086总线三个周期:</p>
<p>① 时钟周期:系统主时钟一个周期信号所持续的时间称为时钟周期(T);</p>
<p>② 总线周期:CPU通过外部总线对存储器或I/O端口进行一次读/写操作的过程称为总线周期;</p>
<p>③ 指令周期:执行一条指令所用的时间;</p>
<p>4、六大条件码标志:</p>
<p><strong>① OF - 溢出标志:出现溢出&nbsp;-&gt; 1;无溢出&nbsp;-&gt; 0;可以理解为判断运算时是否超出范围的一半(即有符号运算时超出范围)</strong></p>
<p><strong>② CF - 进位标志:最高位进位&nbsp;-&gt;&nbsp; 1;无进位&nbsp;-&gt; 0;可以理解为判断无符号运算时超出范围;</strong></p>
<p>③ SF - 符号标志:结果为负 -&gt; 1;结果为正 -&gt; 0;可以理解为判断最高位是否为1;</p>
<p>④ ZF - 零标志:结果为零 -&gt; 1;结果非零 -&gt; 0;</p>
<p>⑤ AF - 辅助进位标志:第3位进位 -&gt; 1;无进位 -&gt; 0;</p>
<p>⑥ PF - 奇偶标志:低8位中有偶数个1&nbsp;-&gt; 1;奇数个 -&gt; 0。</p>
<p>(对于六个状态位,要以实际运算判断,不能用转换的运算判断)</p>
<p><strong><span style="font-size: 16px">&gt; 第三节课 20200224</span></strong></p>
<p>【例题】设DS=1100H,(12000H)=80H,(12001H)=20H,(12002H)=30H,执行MOV AX, 则AX=( )。</p>
<p>直接寻址方式,题中物理地址PA = 段地址 × 16 + 偏移量,段地址存放在DS中,偏移量为1000H,相加则可算出物理地址为12000H,故低八位为80H,高八位为20H,答案为2080H。</p>
<p>20位物理地址各种概念:</p>
<p>逻辑地址 = 段基址:偏移地址(偏移量)</p>
<p>段首地址 = 段基址左移1位,即能被16整除,与偏移地址相加得到20位物理地址。</p>
<p>CS : IP</p>
<p>8086CPU引脚BHE名称是 <strong>高字节使能信号</strong>,作用是&nbsp;<strong>确定高字节内存的访问</strong>。</p>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18px">第三章 80X86寻址</span></strong></p>
<p><strong><span style="font-size: 16px">&gt; 第四节课 20200228</span></strong></p>
<p><strong><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200306155005804-851871354.png"></span></strong></p>
<p><span style="background-color: rgba(255, 255, 255, 1); color: rgba(255, 0, 0, 1)"><strong>(图中寄存器相对/间接寻址写反)</strong></span></p>
<p><span style="font-size: 16px"><strong>一、与数据有关的寻址方式</strong></span></p>
<p><strong>7 种基本的寻址方式:立即寻址、寄存器寻址、存储器寻址(直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址、相对基址加变址寻址)。</strong></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">立即寻址</span>:MOV 目的操作数,立即数。例如:MOV AX, 1234H,其中12H存在AX高8位AH,34H存在AX低8位AL;</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">寄存器寻址</span>:指操作数据存放在寄存器中。寄存器可以为:</p>
<p>8位(r8): AH、AL、BH、BL、CH、CL、DH、DL<br>16位(r16): AX、BX、CX、DX、SI、DI、BP、SP<br>段寄存器(seg): CS、DS、SS、ES</p>
<p>存储器寻址:必须提供两个有效地址:(段基址(DS):偏移地址)。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">直接寻址(MOV AX, )</span>;</p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">寄存器间接寻址(MOV AX, )</span>:所使用的的寄存器可以为BP, BX, SI, DI。使用BP,其默认段为SS段,其他寄存器默认的段地址在DS段寄存器。</p>
<p>指令中也可指定段跨越前缀来取得其他段中的数据。例如:MOV   AX, ES: 。</p>
<p>5、<span style="color: rgba(255, 0, 0, 1)">寄存器相对寻址(MOV AX, )</span>;</p>
<p>6、<span style="color: rgba(255, 0, 0, 1)">基址变址寻址(MOV AX, )</span>:只能是基址和变址组合;</p>
<p>7、<span style="color: rgba(255, 0, 0, 1)">相对基址变址寻址(MOV AX, )</span>;</p>
<p>I/O端口寻址?</p>
<p><span style="font-size: 16px"><strong>二、与程序有关的寻址方式 / 寻找转移地址的寻址方式</strong></span></p>
<p>指令地址由代码段寄存器CS和指令指针寄存器IP的内容共同决定。(CS : IP)</p>
<p>SHORT表示位移量为8位时的短位移;</p>
<p>NEAR表示16位的在同一代码段内的近转移,只修改IP的值;</p>
<p>FAR表示段间转移的表示符,CS和IP的值都要修改。</p>
<p><strong>4种:段内直接寻址,段内间接寻址,段间直接寻址,段间间接寻址。</strong></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">段内直接寻址:JMP (SHORT) NEXT; JMP NEAR PTR NEXT;</span></p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">段内间接寻址:JMP BX; JMP NEAR PTR ; JMP ;</span></p>
<p>【例题】说明转移指令JMP TABLE专一地址的寻址方式。假设(DS) = 2000H, (CS) = 3000H, (SI) = 7800H, 位移量TABLE = 0008H, (27808H) = 3600H。</p>
<p>转移地址的寻址方式为段内间接寻址。该指令执行后,</p>
<p>(IP) = ((DS) * 10H + TABLE + (SI)) = (20000H + 0008H + 7800H) = (27808H) = 3600H, (CS) = 3000H, 即转移地址为CS : IP = 3000H : 3600H.</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">段间直接寻址:JMP FAR PTR NEXT; JMP 1000 : 0;</span></p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">段间间接寻址:JMP DWORD PTR ; JMP DWORD PTR .</span></p>
<p>&nbsp;</p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong><span style="color: rgba(0, 0, 0, 1); font-size: 18px">第四章 80X86指令系统</span></strong><br></span></p>
<p><strong><span style="color: rgba(255, 0, 0, 1); font-size: 16px"><span style="color: rgba(0, 0, 0, 1)">&gt; 第五/六/七节课 20200302/06/09</span></span></strong></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">80X86指令系统按功能分为以下几类:</span></span></p>
<p><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">一、数据传送指令;  二、算术运算指令;  三、十进制调整指令;</span></span></strong></p>
<p><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">四、逻辑运算指令;  五、移位指令;    六、标志位操作指令;</span></span></strong></p>
<p><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">七、字符串操作指令; 八、控制转移指令;  九、伪指令。</span></span></strong></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200316212458769-397893013.png"></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">分类介绍:</span></span></p>
<p><span style="font-size: 16px"><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">一、数据传送指令</span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">1、通用数据传送指令</span></span></strong></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">① <span style="color: rgba(255, 0, 0, 1)">传送指令 MOV</span>:MOV OPD(目的操作数), OPS(源操作数),作用:将OPS的值送给OPD。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">多种形式:MOV Reg / Mem, Reg / Mem / ImData;其中Reg表示寄存器,Mem表示存储器,ImData表示立即数。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">不能使用MOV将一个段寄存器的值传送到另一个段寄存器,可以使用通用寄存器来作为中间媒介,比如:</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">MOV AX, DS; MOV ES, AX; 即将DS的值传到ES。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">传送时类型必须匹配,例如8位必须匹配8位。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">② <span style="color: rgba(255, 0, 0, 1)">堆栈操作指令</span> <span style="color: rgba(255, 0, 0, 1)">PUSH / POP</span>:PUSH OPS / POP OPD,作用:入栈 / 出栈。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">参见第五章第六节堆栈操作程序。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">③ <span style="color: rgba(255, 0, 0, 1)">交换指令</span> <span style="color: rgba(255, 0, 0, 1)">XCHG</span>:XCHG OPD, OPS,作用:将两个操作数交换。</span></span></p>
<p><span style="font-size: 16px"><strong><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">2、地址传送指令</span></span></strong></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">① <span style="color: rgba(255, 0, 0, 1)">偏移地址传送指令 LEA</span>:LEA REG, VAR_NAME,作用:将内存变量VAR_NAME的偏移地址传送到寄存器REG上。</span></span></p>
<p>REG必须为16位寄存器。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">传送指针到指定寄存器和DS的装载指令 LDS</span>:LDS REG, POINTER,</p>
<p>作用:将内存变量POINTER的4个字节的内容分别传送到REG(低地址字)和DS(高地址字)。</p>
<p>REG常为SI或BX。</p>
<p>③&nbsp;<span style="color: rgba(255, 0, 0, 1)">传送指针到指定寄存器和ES的装载指令 LES</span>:LES REG, POINTER,作用见上。</p>
<p>REG常为DI。</p>
<p><strong><span style="font-size: 16px">3、标志传送指令</span></strong></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">取标志指令 LAHF</span>,作用:将标志寄存器的低8位传送到AH;</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">设置标志指令</span> <span style="color: rgba(255, 0, 0, 1)">SAHF</span>,作用:将AH的低8位传送到标志寄存器;</p>
<p>③<span style="color: rgba(255, 0, 0, 1)"> 标志进栈指令 PUSHF</span>,作用:SP -=2, 将标志寄存器的值压入堆栈顶部;</p>
<p>④<span style="color: rgba(255, 0, 0, 1)"> 标志出栈指令 POPF</span>,作用:将堆栈顶部弹出2字节内容传送到标志寄存器,SP += 2;</p>
<p><strong><span style="color: rgba(0, 0, 0, 1); font-size: 16px">4、查表指令</span></strong></p>
<p><span style="color: rgba(255, 0, 0, 1)">XLAT / XLATB</span>,有两个隐含操作数:BX, AL。</p>
<p>作用:使用该指令前,要求将内存数据段中的数据表的首地址存放于BX寄存器中,元素在表内的偏移地址存放在AL寄存器中。使用该指令能够找到由BX和AL指令的表内元素值,并传送到AL寄存器。</p>
<p>即AL ← ((BX) + (AL)).</p>
<p><strong><span style="font-size: 16px">二、算术运算指令</span></strong></p>
<p><strong><span style="font-size: 16px">1、加法指令</span></strong></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">加法指令 ADD</span>:ADD OPD, OPS。</p>
<p>OPD可为非段寄存器或内存单元,OPS还可以为立即数。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">带进位加法指令 ADC:ADC OPD, OPS</span>,作用:将OPD, OPS, CF的值相加放至OPD。</p>
<p>③ 加1指令 INC:INC OPR,作用:给OPR加1。</p>
<p>OPR不能是立即数和段寄存器(同OPD)。标志位中CF不受影响。</p>
<p><span style="font-size: 16px"><strong>2、减法指令</strong></span></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">减法指令 SUB</span>:SUB OPD, OPS。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">带借位减法指令 SBB</span>:SBB OPD, OPS,作用:将OPD - OPS - CF的值放入OPD。</p>
<p>③ <span style="color: rgba(255, 0, 0, 1)">减1指令 DEC</span>:DEC OPS,作用:给OPS减1。CF不受影响。</p>
<p>④ <span style="color: rgba(255, 0, 0, 1)">求补指令 NEG</span>:NEG OPR,作用:求操作数的相反数(即求补码,按位取反后+1)</p>
<p>⑤ <span style="color: rgba(255, 0, 0, 1)">比较指令 CMP</span>:CMP OP1, OP2,作用:根据CF, ZF, OF, SF判断两个操作数的大小。</p>
<p><span style="font-size: 16px"><strong>3、乘法指令</strong></span></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">无符号数乘法指令 MUL</span>:MUL OPS。</p>
<p>OPD为隐含的AL或AX寄存器,OPS为寄存器或存储单元。</p>
<p>如果是8位二进制数乘法,OPD为AL,结果存放在AX。</p>
<p>如果是16为二进制数乘法,OPD为AX,结果高位存放在DX,低位存放在AX。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">有符号数乘法指令 IMUL</span>:IMUL OPS。同上。</p>
<p><strong><span style="font-size: 16px">4、除法指令</span></strong></p>
<p>①<span style="color: rgba(255, 0, 0, 1)"> 无符号数除法指令 DIV</span>:DIV OPS。</p>
<p>OPD为隐含的AX或DX/AX,OPS为寄存器或存储单元。</p>
<p>如果除数为8位,被除数要求为16位,存放在AX,商存放在AL,余数存放在AH;</p>
<p>如果除数为16位,被除数要求为32位,存放在DX/AX,商存放在AX,余数存放在DX。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">有符号数除法指令 IDIV</span>:IDIV OPS。同上。</p>
<p><span style="font-size: 16px"><strong>三、十进制调整指令</strong></span></p>
<p>压缩型BCD码:4位二进制数表示一位十进制数;</p>
<p>非压缩型BCD码:8位二进制数表示一位十进制数,其中高4位无意义。</p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">十进制加法调整指令 DAA</span></p>
<p>作用:由于上述的运算指令均为十六进制形式,该指令作用是调整为十进制。</p>
<p>加在运算指令后一条。例如:ADD AL, BL; DAA.</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">十进制减法调整指令 DAS</span></p>
<p>同上。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">非压缩的加法调整指令 AAA</span></p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">非压缩的减法调整指令 AAS</span></p>
<p><span style="font-size: 16px"><strong>四、逻辑运算指令</strong></span></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">逻辑与指令 AND</span>:AND OPD, OPS,作用:每一位二进制数字相与。</p>
<p>常用于屏蔽某些位。</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">逻辑或指令 OR</span>:OR OPD, OPS。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">逻辑非指令 NOT</span>:NOT OPR。</p>
<p>OPR不能为段寄存器和立即数。</p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">异或指令 XOR</span>:XOR OPD, OPS。</p>
<p>5、<span style="color: rgba(255, 0, 0, 1)">测试指令 TEST</span>:TEST OP1, OP2,作用:两个操作数AND,但结果不保存。</p>
<p>用于不改变OP1的情况下检测其某一位的条件是否满足。</p>
<p><span style="font-size: 16px"><strong>五、移位指令</strong></span></p>
<p><span style="font-size: 16px"><strong>1、逻辑移位指令</strong></span></p>
<p>①<span style="color: rgba(255, 0, 0, 1)"> 逻辑左移指令 SHL</span>:SHL OP, 1 / CL。</p>
<p>每次移动,最高位移出到标志位CF中。OP不能为立即数和段寄存器。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">逻辑右移指令 SHR</span>:SHR OP, 1 / CL。</p>
<p>每次移动,最低位移出到标志位CF中。最高位补0。</p>
<p><span style="font-size: 16px"><strong>2、算术移位指令</strong></span></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">算术左移指令 SAL</span>:SAL OP, 1 / CL。</p>
<p>和SHL完全相同。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">算数右移指令 SAR</span>:SAR OP, 1 / CL。</p>
<p>每次移动,最低位移出到标志位CF中。最高位保持符号位不变(注意和SHR的不同)。</p>
<p><span style="font-size: 16px"><strong>3、循环移位指令</strong></span></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">循环左移指令 ROL</span>:ROL OP, 1 / CL。</p>
<p>每次移动,最高位移出并送到CF标志位和最低位。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">循环右移指令 ROR</span>:ROR OP, 1 / CL。</p>
<p>同理。</p>
<p>③ <span style="color: rgba(255, 0, 0, 1)">带进位的循环左移指令 RCL</span>:RCL OP, 1 / CL。</p>
<p>每次移动,最高位移出并送到CF标志位,CF标志位再送到最低位。以此实现进位。</p>
<p>④ <span style="color: rgba(255, 0, 0, 1)">带进位的循环右移指令 RCR</span>:RCR OP, 1 / CL。</p>
<p>同理。</p>
<p><span style="font-size: 16px"><strong>六、标志位操作指令</strong></span></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">CF标志操作指令 CLC</span>:将CF标志位清零。</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">CF标志操作指令 STC</span>:将CF标志位变为1。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">方向标志操作指令 CLD</span>:将方向标志位清零。</p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">方向标志操作指令 STD</span>:将方向标志位变为1。</p>
<p>5、<span style="color: rgba(255, 0, 0, 1)">中断标志操作指令 CLI</span>:将中断标志位清零。IF = 0,表示CPU屏蔽外部可屏蔽中断。</p>
<p>6、<span style="color: rgba(255, 0, 0, 1)">中断标志操作指令 STI</span>:将中断标志位变为1。IF = 1,表示CPU开放外部可屏蔽中断。</p>
<p><span style="font-size: 16px"><strong>七、字符串操作指令</strong></span></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">串传送指令 MOVSB / MOVSW</span></p>
<p>MOVSB:</p>
<p>把DS : SI所指向的<strong>字节型数据</strong>传送到由ES : DI指向的内存单元中。</p>
<p>DF = 0, (SI) ← (SI) + 1, (DI)&nbsp;← (DI) + 1; DF = 1, (SI)&nbsp;← (SI) - 1, (DI)&nbsp;← (DI) - 1.</p>
<p>MOVSW:</p>
<p>把DS : SI所指向的<strong>字型数据</strong>传送到由ES : DI指向的内存单元中。</p>
<p>DF = 0, (SI) ← (SI) + 2, (DI)&nbsp;← (DI) + 2; DF = 1, (SI)&nbsp;← (SI) - 2, (DI)&nbsp;← (DI) - 2.</p>
<p>串传送指令能将内存单元数据不经过CPU内部寄存器传送到另一区域,MOV做不到。</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">存入数据到串中指令 STOSB / STOSW</span></p>
<p>把AL中的数据存储到ES : DI。</p>
<p>STOSB / STOSW 只有DI,其他同上。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">从串中取数据指令 LODSB / LODSW</span></p>
<p>从DS : SI中取出数据送到AL / AX中。</p>
<p>只有SI,其他同上。</p>
<p>4、<span style="color: rgba(255, 0, 0, 1)">重复操作前缀指令 REP</span></p>
<p>加在上述指令前,表示重复传送、存储和读取。</p>
<p>(CX) = 0退出。(CX) ← (CX) - 1。</p>
<p>5、<span style="color: rgba(255, 0, 0, 1)">串比较指令 CMPSB / CMPSW</span></p>
<p>把DS : SI与ES : DI内容相减。其他同上。</p>
<p>6、<span style="color: rgba(255, 0, 0, 1)">串扫描指令 SCASB / SCASW</span></p>
<p>将AL / AX中的数据与ES : DI相减。用于查找串中是否含有某个元素值。</p>
<p>7、<span style="color: rgba(255, 0, 0, 1)">重复操作前缀指令 REPZ / REPNZ</span></p>
<p>加在上述指令前,表示重复执行。</p>
<p>(CX) = 0或ZF = 0退出。(CX) ← (CX) - 1。</p>
<p><strong><span style="font-size: 16px">八、控制转移指令</span></strong></p>
<p>可以修改IP或同时修改CS和IP的指令。</p>
<p><strong>1、无条件转移指令 JMP</strong></p>
<p>① <span style="color: rgba(255, 0, 0, 1)">段内直接段跳转:JMP (SHORT) 地址标号</span>,作用:(IP) ← (IP) + 8位位移量。</p>
<p>② <span style="color: rgba(255, 0, 0, 1)">段内直接近转移:JMP NEAR PTR 地址标号</span>,作用:(IP) ← (IP) + 16位位移量。</p>
<p>③ <span style="color: rgba(255, 0, 0, 1)">段内间接转移:JMP 存放转移地址的寄存器 / 内存地址</span>。</p>
<p>作用:(IP) ← 16位寄存器或存储子单元的内容(偏移地址)。</p>
<p>④ <span style="color: rgba(255, 0, 0, 1)">段间直接转移:JMP 段地址:偏移地址</span><span style="color: rgba(255, 0, 0, 1)">;JMP FAR PTR 地址标号</span>。</p>
<p>作用:(CS)&nbsp;← 段地址;(IP)&nbsp;← 偏移地址。</p>
<p>⑤ <span style="color: rgba(255, 0, 0, 1)">段间间接转移:JMP DWORD PTR 内存地址</span>。</p>
<p>作用:(CS)&nbsp;← 指定单元高地址字内容;(IP)&nbsp;← 低地址字内容。</p>
<p><strong>2、条件转移指令</strong></p>
<p>一般格式:JXX 地址标号。</p>
<p>① 基于无符号数运算的条件转移指令</p>
<p>&nbsp;-<span style="color: rgba(255, 0, 0, 1)"> JZ / JE指令</span>,条件:ZF = 1,作用:结果为0 / 相等则转移。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JNZ / JNE指令</span>,条件:ZF = 0,作用:结果不为0 / 不相等则转移。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JS指令</span>,条件:ZF = 0,作用:结果为负。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JNS指令</span>,条件:ZF = 0,作用:结果为正。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JO指令</span>,条件:ZF = 0,作用:结果溢出。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JNO指令</span>,条件:ZF = 0,作用:结果不溢出。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JP / JPE指令</span>,条件:ZF = 0,作用:结果含偶数个1。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JNP / JPO指令</span>,条件:ZF = 0,作用:结果含奇数个1。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JC / JNAE / JB指令</span>,条件:ZF = 0,作用:结果产生进借位 / 比较无符号数时小于。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JNC / JAE / JNB指令</span>,条件:ZF = 0,作用:结果不产生进借位 / 不小于。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JBE / JNA指令</span>,条件:ZF = 0,作用:比较无符号数小于等于。</p>
<p>&nbsp;- <span style="color: rgba(255, 0, 0, 1)">JA / JNBE指令</span>,条件:ZF = 0,作用:大于。</p>
<p>②&nbsp;基于有符号数运算的条件转移指令</p>
<p>- <span style="color: rgba(255, 0, 0, 1)">JL / JNGE指令</span>,条件:SF ⊕ OF = 1,作用:比较有符号数小于。</p>
<p>- <span style="color: rgba(255, 0, 0, 1)">JNL / JGE指令</span>,条件:SF&nbsp;⊙ OF = 1,作用:比较有符号数不小于。</p>
<p>- <span style="color: rgba(255, 0, 0, 1)">JLE / JNG指令</span>,条件:(SF&nbsp;⊕ OF) ∨ ZF = 1,作用:小于等于。</p>
<p>- <span style="color: rgba(255, 0, 0, 1)">JG / JNLE指令</span>,条件:(SF&nbsp;⊕ OF)&nbsp;∨ ZF = 0,作用:大于。</p>
<p>③ 特殊判断依据的条件转移指令</p>
<p>- <span style="color: rgba(255, 0, 0, 1)">JCXZ指令</span>,条件:(CX) = 0,作用:将计数值放入CX,CX = 0则转移。</p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>3、循环指令</strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">① <span style="color: rgba(255, 0, 0, 1)">循环指令 LOOP</span>:LOOP 地址标号,作用:循环。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">CX--, CX = 0时退出循环。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">② LOOPE / LOOPZ / LOOPNE / LOOPNZ指令。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>4、调用返回指令</strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">① <span style="color: rgba(255, 0, 0, 1)">过程调用指令 CALL</span>:</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">段内直接调用方式:CALL 近程过程标号;</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">段内间接调用方式:CALL OPD(16位寄存器,存储器);</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">段间直接调用方式:CALL 远程过程标号;</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">段间间接调用方式:CALL OPD(32位存储器);</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">② RET n,作用:用于参数传递。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>5、中断指令</strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)">① INT n:n为8位中断类型号。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">INT 20H:直接退出程序;</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">MOV AH, ?&nbsp; &nbsp;INT 21H 表见下:</span></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093054774-320280431.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093110522-1536261337.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093131237-717602312.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093137156-133207877.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093142667-217144619.png"></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200326093147980-1974039234.png"></p>
<p><span style="color: rgba(153, 153, 153, 1)">INT 3H:退出到断点。</span></p>
<p><span style="color: rgba(153, 153, 153, 1)">② INTO:如果OF = 1,相当于INT 4;否则无。</span></p>
<p><span style="color: rgba(153, 153, 153, 1)">③ IRET。</span></p>
<p><span style="font-size: 16px"><strong>九、常用伪指令</strong></span></p>
<p>1、<span style="color: rgba(255, 0, 0, 1)">设置起始地址伪指令 ORG</span>:ORG 数值表达式。</p>
<p>作用:指明指令代码或数据存放的偏移位置。</p>
<p>2、<span style="color: rgba(255, 0, 0, 1)">符号赋值伪指令 EQU</span>:符号名称 EQU 表达式。</p>
<p>作用:实现对符号的赋值。</p>
<p>3、<span style="color: rgba(255, 0, 0, 1)">定义数据伪指令 DB</span>:变量名 DB 数1, (数2), (数3)...</p>
<p>作用:定义字节变量,将数据存放至内存单元中。</p>
<p>同类伪指令还有:DW(定义字变量,占用2个字节),DD(定义双字变量,4个)</p>
<p>DUP:N DUP(数1, 数2, 数3),N表示重复次数,作用:重复定义。</p>
<p>和DB/DW/DD联合使用,例如:DATA1 DB 2 DUP(0, 1, 2, 3), 5。</p>
<p>&nbsp;</p>
<p><span style="font-size: 18px"><strong>第五章 汇编语言程序设计</strong></span></p>
<p><span style="font-size: 16px"><strong>&gt; 第八课 20200313</strong></span></p>
<p><strong><span style="font-size: 14px">一、基本框架</span></strong></p>
<p><span style="font-size: 14px">1、结构</span></p>
<p><span style="font-size: 16px"><strong><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200313130844060-489861511.png"></strong></span></p>
<p><span style="font-size: 14px">2、ASSUME伪指令</span></p>
<p><span style="font-size: 14px">作用:通知汇编程序建立段名与段寄存器之间的对应关系。</span></p>
<p>例如:ASSUME CS:CODE, DS:DATA, SS:STACK, ES:NOTHING</p>
<p>3、段寄存器的装入</p>
<p>① DS/ES:MOV AX, 段名; MOV DS/ES, AX;</p>
<p>② SS:MOV AX, 堆栈段段名; MOV SS, AX;</p>
<p>③ CS:使用程序结束伪指令END:END 程序启动地址</p>
<p><strong>二、基本数据</strong></p>
<p>1、标识符</p>
<p>字母+数字+特殊字符(? @ $ _);字母开头。</p>
<p>2、常量</p>
<p>数值常量(0A8H),字符串常量("ABC", 414243H),符号常量(COUNT = 10)。</p>
<p>3、变量</p>
<p>操作数的符号地址。3个属性:段属性(段地址),偏移属性(从起始地址到变量位置之间的字节数),类型属性(字节/字/双字)。例如:DATA1 DW 6, 7, 8, 9, 10。</p>
<p>4、标号</p>
<p>指令的符号地址。</p>
<p><strong>三、运算符和表达式</strong></p>
<p>1、算术运算符:+, -, *, /, MOD。</p>
<p>2、逻辑运算符:AND, OR, NOT, XOR。</p>
<p>3、关系运算符:EQ(=), LT(&lt;), LE(&lt;=), GT(&gt;), GE(&gt;=), NE(!=)</p>
<p>4、分析运算符:SEG, OFFSET, TYPE, LENGTH, SIZE</p>
<p>(段地址,偏移地址,变量类型,元素个数,占用内存字节空间大小)</p>
<p>TYPE = ?</p>
<p>5、修改属性运算符</p>
<p>① PTR:类型 PTR 变量/标号名,类型:BYTE, WORD, DWORD, NEAR, FAR。</p>
<p>② THIS:</p>
<p>符号名 EQU THIS 类型</p>
<p>原符号名 类型 参数, ...</p>
<p>6、表达式</p>
<p>数值表达式和地址表达式。</p>
<p><span style="font-size: 16px"><strong>&gt; 第九课 20200316</strong></span></p>
<p><strong>四、基本结构</strong></p>
<p>1、顺序结构</p>
<p>2、分支结构</p>
<p>① 使用 TEST, AND, XOR, CMP 判断;</p>
<p>② 使用 JZ, JNZ, JC, JNC, JS, JNS, JB, JA 跳转。</p>
<p>3、循环结构</p>
<p>① 用 JMP / JXX 指令实现循环;</p>
<p>② 用 LOOP 指令实现循环。</p>
<p><strong>五、数据块的传送</strong></p>
<p>① 使用传送指令 MOV,建立循环程序结构;</p>
<p>② 使用串传送指令 MOVSB / MOVSW:</p>
<p>&gt; 隐含寻址,源操作数存在数据段中,偏移地址保存在 SI 中;目的操作数存在附加段中,偏移地址保存在 DI 中。</p>
<p>&gt; 重复串传送指令 REP 前缀</p>
<p>相关寄存器有 DS:SI, ES:DI, CX, DF。</p>
<p><strong>六、段超越前缀</strong></p>
<p>四种:"CS:", "SS:", "DS:", "ES:"</p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200322161552619-1650067084.png"></p>
<p><strong>七、堆栈操作程序</strong></p>
<p>SS存储堆栈的段地址,SP存储栈顶单元的偏移地址</p>
<p>堆栈操作指令&nbsp;PUSH / POP:PUSH OPS / POP OPD,作用:入栈 / 出栈。</p>
<p>其中,PUSH OPS: (SP) ← (SP) - 2; ((SP) + 1, SP) ← (OPS);</p>
<p>POP OPD: (OPD) ← ((SP) + 1, (SP)); (SP) ← (SP) + 2.</p>
<p>OPS / OPD不能为立即数。CS不能作为OPD(MOV也是)。</p>
<p>更多见下。</p>
<p><strong>八、端口操作程序</strong></p>
<p>见下。</p>
<p><strong>九、用户中断服务程序</strong></p>
<p>见下。</p>
<p><strong>十、可执行文件与PSP</strong></p>
<p>&nbsp;</p>
<p><span style="font-size: 18px"><strong>第六章 子程序设计</strong></span></p>
<p><strong><span style="font-size: 16px">&gt; 第十/十一课 20200320/23</span></strong></p>
<p><strong>一、定义与应用条件</strong></p>
<p>子程序名 PROC 类型NEAR / FAR</p>
<p>...</p>
<p>子程序名 ENDP</p>
<p>最后一条指令必须为返回指令RET</p>
<p><strong>二、调用和返回指令</strong></p>
<p>1、调用:CALL 子程序名</p>
<p>2、返回:RET/RETF&nbsp;</p>
<p><strong>三、结构</strong></p>
<p>可以利用堆栈来“保护现场”——即将通用寄存器里的数据放入堆栈,然后就可以在子程序里被使用了;使用完后再弹回到原来的寄存器里即可。</p>
<p>PUSH AX; PUSH CX; PUSH SI; PUSHF;</p>
<p>POPF; POP SI; POP CX; POP AX.</p>
<p><strong>四、参数传递</strong></p>
<p>1、寄存器传递</p>
<p>2、存储器传递</p>
<p>3、堆栈传递</p>
<p>堆栈与基址寄存器 BP</p>
<p>PUSH BP; MOV BP, SP</p>
<p>BP 指向 SP 基地址, 为 BP 保存值, 为主程序断点 IP 的值, 为子程序需要的第 1 个参数,以此类推(NEAR)。</p>
<p>对于 FAR, 断点的 CS 值, 为第 1 个参数,以此类推。</p>
<p>MOV SP, BP; POP BP</p>
<p><strong>五、嵌套和递归调用</strong></p>
<p>注意寄存器的保存和恢复。</p>
<p><strong>六、EXE文件和COM文件</strong></p>
<p><strong>七、模块化程序设计</strong></p>
<p><span style="color: rgba(255, 0, 0, 1)">EXTRN A</span> : 类型FAR / BYTE / WORD / ... :告知 LINK 程序,A 是外部引入的一个过程 / 变量。</p>
<p><span style="color: rgba(255, 0, 0, 1)">PUBLIC A</span>:声明过程 / 变量是全局的</p>
<p>先将两个源程序分别编译成 .obj 文件,然后连接为 .exe 文件:</p>
<p>Object Modules [.OBJ] : MODUL1 + MODUL2</p>
<p>&nbsp;</p>
<p><span style="font-size: 18px"><strong>第七章 输入与输出程序设计</strong></span></p>
<p><span style="font-size: 16px"><strong>&gt; 第十二/三课 20200327/30</strong></span></p>
<p><span style="font-size: 14px"><strong>一、端口</strong></span></p>
<p><span style="font-size: 14px">接口:在CPU和I/O设备之间起连接作用。</span></p>
<p><span style="font-size: 14px">端口:被CPU操作的接口中的寄存器。分成三类:</span></p>
<p><span style="font-size: 14px">1、数据端口:暂存数据;</span></p>
<p><span style="font-size: 14px">2、控制端口:存放CPU发来的命令;</span></p>
<p><span style="font-size: 14px">3、状态端口:存放外设工作状态,以供CPU查询。</span></p>
<p><span style="font-size: 14px">常用的输入输出方式:</span></p>
<p><span style="font-size: 14px">1、查询输入输出; 2、中断输入输出; 3、DMA方式(成组数据传送方式)。</span></p>
<p><span style="font-size: 14px">I / O端口地址编码</span></p>
<p><span style="font-size: 14px"><img src="https://img2020.cnblogs.com/blog/790029/202003/790029-20200331173209385-1162829219.png"></span></p>
<p><span style="font-size: 14px"><strong>二、I/O指令</strong></span></p>
<p><span style="font-size: 14px">直接端口寻址:</span><span>直接给出要访问的端口地址,最多允许寻址 256 个端口。</span></p>
<p><span style="font-size: 14px">间接端口寻址:</span><span>必须由 DX 寄存器指定,允许寻址 64K 个端口。</span>&nbsp;</p>
<p><span style="font-size: 14px">1、输入指令 IN</span></p>
<p><span style="font-size: 14px">IN AL / AX, PortNo / DX</span></p>
<p><span style="font-size: 14px">2、输出指令 OUT</span></p>
<p><span style="font-size: 14px">OUT PortNo / DX, AL / AX</span></p>
<p><strong>三、端口操作编程</strong></p>
<p>无条件传送方式:不查询外设工作状态,直接传送。</p>
<p><strong>四、中断传送方式</strong></p>
<p>1、中断概念</p>
<p>由于内部或外部事件引起CPU暂停当前程序的执行,转去执行与事件对应的服务程序,但执行完毕后再返回断点(CS:IP)仅需执行。</p>
<p>常见中断源有:</p>
<p>① 输入输出设备; ② 数据通道(如磁盘); ③ 实时时钟; ④ 故障信号; ⑤ 软件指令(如INT n)。</p>
<p>2、中断种类</p>
<p>外部中断和内部中断,每种中断由类型号 0~255 标识。</p>
<p><strong>外部中断</strong>又称为硬件中断,可分为可屏蔽中断 INTR 和非屏蔽中断 NMI。</p>
<p>两个控制条件起决定作用:1、外设中断请求是否屏蔽;2、CPU是否允许响应中断。</p>
<p>两者分别由中断屏蔽寄存器 IMR 和标志寄存器 PSW 中的中断允许位 IF 控制。</p>
<p>其 I / O 端口地址为 21H,它的8位对应8个外部设备:</p>
<p>0 - 定时器;1 - 键盘;2 - 保留;3 - 串行通讯口2;4 - 串行通讯口1;5 - 硬盘;6 - 软盘;7 - 打印机。</p>
<p>例如:MOV&nbsp; AL, 11111101B; OUT 21H, AL,表示只允许键盘中断。</p>
<p><strong>内部中断</strong>又称为软件中断,是 CPU 执行指令时产生的。</p>
<p>① DIV 指令:除数为0,产生中断类型号为 0 的中断;</p>
<p>② 单步中断:TF = 1,执行每条指令都要停下来进行调试,中断类型号为 1;</p>
<p>③ INTO 指令:溢出标志为 1,中断类型号为 4;</p>
<p>④ INT n:中断调用指令中断,n为中断类型号。</p>
<p><strong>中断向量</strong>是中断服务程序的入口地址,即第一条指令的CS:IP值。<strong>中断向量表</strong>是将中断向量在内存中编排而成的表。存储器的最低 1KB 用来存放 256 项中断向量,每一项占用 4 个字节,2 个存放段地址,2 个存放偏移地址,即[(IP) = (n * 4), (CS) = (n * 4 + 2)]。<span style="color: rgba(255, 0, 0, 1)">某中断类型为 4AH,即 4AH * 4 = 128H 和 129H 为偏移地址 IP,12AH 和 12BH 为段地址 CS。</span></p>
<p><strong>【例题】阐述 INT 21H 中断的 CPU 处理过程。</strong></p>
<p>① CPU 取得中断类型号 21H;</p>
<p>② 标志, CS, IP值入栈;</p>
<p>③ 装入中断向量:(IP) = (84H / 85H), (CS) = (86H / 87H);</p>
<p>④ 执行中断服务程序;</p>
<p>⑤ 执行 IRET 指令,从堆栈中依次弹出 IP, CS, 标志,恢复断点;</p>
<p>⑥ 从断点处继续执行主程序。</p>
<p>指令为终端类型 n 设置中断向量模板:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">MOV</span> AX, <span style="color: rgba(128, 0, 128, 1)">0</span>
<span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> ES, AX
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span> BX, N * <span style="color: rgba(128, 0, 128, 1)">4</span>
<span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AX, OFFSET A
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> ES : WORD PTR , AX
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AX, SEG A
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span> ES : WORD PTR , AX
...
</span><span style="color: rgba(0, 128, 128, 1)">INTHAND:</span><span style="color: rgba(0, 0, 0, 1)">
...
</span><span style="color: rgba(0, 0, 255, 1)">IRET</span></pre>
</div>
<p>3、取中断向量</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AL, 1CH
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AH, 35H
</span><span style="color: rgba(0, 0, 255, 1)">INT</span><span style="color: rgba(0, 0, 0, 1)"> 21H
</span><span style="color: rgba(0, 0, 255, 1)">PUSH</span><span style="color: rgba(0, 0, 0, 1)"> ES
</span><span style="color: rgba(0, 0, 255, 1)">PUSH</span> BX</pre>
</div>
<p>把由 AL 指定的中断类型的中断向量从中断向量表中取到 ES : BX 中。</p>
<p>4、设置中断向量</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> DX, OFFSET A
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AX, SEG A
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> DS, AX
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AL, 1CH
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span><span style="color: rgba(0, 0, 0, 1)"> AH, 25H
</span><span style="color: rgba(0, 0, 255, 1)">INT</span> 21H</pre>
</div>
<p>令 A 为要设置的中断向量过程,把由 AL 指定的中断类型的中断向量 DS : DX 放置在中断向量表中。</p>
<p>允许键盘中断:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">IN</span><span style="color: rgba(0, 0, 0, 1)"> AL, 21H(当新增设时才写)
</span><span style="color: rgba(0, 0, 255, 1)">MOV</span> AL, 111111<span style="color: rgba(128, 0, 128, 1)">01B</span>
<span style="color: rgba(0, 0, 255, 1)">OUT</span> 21H, AL</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 18px"><strong>第七章 80386汇编基础</strong></span></p>
<p><span style="font-size: 16px"><strong>&gt; 第十四/五课 20200403/10</strong></span></p>
<p><span style="font-size: 16px"><strong>一、逻辑结构及引脚</strong></span></p>
<p><strong><span style="font-size: 14px">1、六大功能部件</span></strong></p>
<p><span style="font-size: 14px">① BIU: 总线接口部件</span></p>
<p><span style="font-size: 14px">② IPU: 指令预取部件</span></p>
<p><span style="font-size: 14px">③ IDU: 指令译码部件</span></p>
<p><span style="font-size: 14px">④ SU: 分段部件</span></p>
<p><span style="font-size: 14px">⑤ PU: 分页部件</span></p>
<p><span style="font-size: 14px">⑥ EU: 执行部件</span></p>
<p><strong><span style="font-size: 14px">2、80386 CPU 结构</span></strong></p>
<p><span style="font-size: 14px"><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200412122657342-1657064522.png"></span></p>
<p>80386 CPU 总共 132 根引脚,其中含有 34 条地址线,32 条数据线,3 条中断线,1 条时钟线, 13 条控制线,20 条电源线, 21 条地线。</p>
<p><span style="font-size: 16px"><strong>二、寄存器</strong></span></p>
<p><span style="font-size: 14px"><strong>1、数据寄存器</strong></span></p>
<p><span style="font-size: 14px">4 个 32 位数据寄存器:EAX, EBX, ECX, EDX。</span></p>
<p><strong><span style="font-size: 14px">2、变址寄存器和指针寄存器</span></strong></p>
<p><span style="font-size: 14px">2 个 32 位变址寄存器:ESI, EDI;2 个 32 位指针寄存器:ESP, EBP。</span></p>
<p><strong><span style="font-size: 14px">3、段寄存器和指令指针寄存器</span></strong></p>
<p><span style="font-size: 14px">6 个 16 位段寄存器:CS, DS, SS, ES, FS, GS;1 个 32 位指令指针寄存器 EIP;</span></p>
<p><span style="font-size: 14px">在保护模式下,段寄存器存放<strong>段选择子</strong>。</span></p>
<p><strong><span style="font-size: 14px">4、标志寄存器</span></strong></p>
<p><span style="font-size: 14px">大体分为三类:</span></p>
<p><span style="font-size: 14px">① A 表示条件码标志,记录程序运行结果状态,CPU 自动设置,往往作为条件转移指令的判断条件。比如:CF, PF, AF, ZF, SF, OF;</span></p>
<p><span style="font-size: 14px">② B 为方向标志位 DF;</span></p>
<p><span style="font-size: 14px">③ C 为系统标志位,可用于 I / O,可屏蔽中断,程序调试,任务切换和系统工作方式等的控制。比如:TF, IF, IOPL, NT, RF, VM, AC, VIF, VIP, ID。</span></p>
<p><strong><span style="font-size: 14px">5、系统表寄存器</span></strong></p>
<p>① GDTR:全局描述符表寄存器,48位</p>
<p>② IDTR:中断描述符表寄存器,48位</p>
<p>③ LDTR:局部描述符表寄存器,16位,选择子</p>
<p>④ TR:任务状态寄存器,16位,选择子</p>
<p><strong>6、控制寄存器</strong></p>
<p>4 个 32 位的控制寄存器:CR0, CR1, CR2, CR3</p>
<p>CR0 中的 PE 是保护状态标记:</p>
<p>PE = 0, PG = 0:实模式(16 位 DOS 系统模式)</p>
<p>0, 1 非法;1, 0 保护模式禁止分页;1, 1 保护模式启动分页</p>
<p>CR2 保存页故障的线性地址;CR3 页目录表物理页码。</p>
<p><strong>7、调试寄存器</strong>:DR0~7</p>
<p><strong>8、测试寄存器</strong>:TR6, TR7</p>
<p><span style="font-size: 16px"><strong>三、寻址方式</strong></span></p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200412173444234-172736410.png"></p>
<p><span style="font-size: 16px"><strong>四、新增指令</strong></span></p>
<p><strong>略</strong></p>
<p><span style="font-size: 16px"><strong>五、工作模式</strong></span></p>
<p><strong>三大工作模式:实模式,保护模式,虚拟 86 模式。</strong></p>
<p><strong>1、实模式(实地址模式,RM)</strong></p>
<p>CR0 的 PE 位为 0 时,进入实模式。内存单元地址的透明的,没有对应唯一的段地址,比如物理地址为 04806H 的内存单元可以被 047C:0046 和 047D:0036 等逻辑地址访问到,所以本段数据可以被其他段程序访问,容易出现地址越界,数据段可以对代码段进行修改。</p>
<p>实模式下,段全部可以读写和执行,软件可以直接访问 BIOS 和外围硬件,没有内存保护和多任务工作模式。</p>
<p><strong>2、保护模式</strong></p>
<p>采用分段、分页的虚拟内存管理机制来从<strong>逻辑地址</strong>求出<strong>物理地址</strong>,寻址时给出一个 32 位地址就可以直接找到存储单元。</p>
<p><strong>3、V86 模式</strong></p>
<p>支持多用户、多任务操作系统运行,是在 32 位保护模式下支持 16 位实模式应用程序的一种保护模式。</p>
<p><strong>三种工作模式的相互转换</strong></p>
<p><strong><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200412155453063-1192779308.png"></strong></p>
<p><span style="font-size: 16px"><strong>六、保护模式下物理地址形成机制</strong></span></p>
<p><span style="font-size: 14px"><strong>1、选择子与描述符</strong></span></p>
<p><span style="font-size: 14px">选择子的作用是选择<strong>段描述符。</strong></span></p>
<p><span style="font-size: 14px">段描述符分为:</span><span>存储段描述符(代码段 + 数据段);</span><span>系统段描述符( LDT 段 + 任务状态段);门描述符(调用门,任务门,中断门,陷阱门);</span></p>
<p><span><strong>&gt; 存储段 / 系统段描述符(S决定):</strong></span></p>
<p><span style="font-size: 14px"><strong><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200412171410378-1659487475.png"></strong></span></p>
<p>① 段基址为 32 位,允许起始于任何位置;</p>
<p>② TYPE:4 位,说明段的具体属性。</p>
<p>对于存储段:</p>
<p>  A / 位0:表示是否被访问过,0 - 未被访问,1 - 已被访问;</p>
<p>  W/R / 位1:对数据段,W = 1 - 可读可写,0 - 可读不可写;对代码段,R = 1 - 可执行可读,0 - 可执行不可读;</p>
<p>  ED/C / 位2:对数据段,0 - 数据向高扩展,1 - 向低;对代码段,0 - 普通代码,1 - 一致代码段;</p>
<p>  E / 位3:0 - 不可执行,数据段,1 - 可执行,代码段;</p>
<p>对于系统段:略。</p>
<p>③ 段限长:最大允许偏移地址,20位;</p>
<p>④ G:粒度位。0 - 以 1B 为单位,1 - 以 4 KB 为单位;</p>
<p>⑤ D:存取方式位。0 - 16 位地址,16 / 8 位操作数;1 - 32 位地址,32 / 16 / 8 位操作数;</p>
<p>⑥ AVL:指示段是否有效。0 - 无效,1 - 有效;</p>
<p>⑦ P:存在位。0 - 描述符对地址转换无效,使用将引起异常;1 - 有效;</p>
<p>⑧ DPL:2 位,指示最低<strong>优先级</strong>;下图为优先级 / 特权级分级。</p>
<p><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200412173233782-1826081499.png"></p>
<p>⑨ S / DT:描述符类型。0 - 系统段,1 - 存储段。</p>
<p><strong>&gt; 段选择子:</strong></p>
<p>在 16 位段选择子结构中,高 13 位(3 ~ 15)表示要选择的段描述符的索引号;</p>
<p>第 2 位 TI 指明描述符在 GDT(0) 还是 LDT(1) 中;</p>
<p>第 0, 1 位 RPL 是选择子自身优先级,只有该优先级 &gt;= DPL,描述符才能被存取。</p>
<p><strong>段描述符的内存地址 = 内存首地址 + 索引号 * 8.</strong></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong>七、中断和异常处理</strong></span></p>
<p><strong><span style="font-size: 14px">1、异常</span></strong></p>
<p><span style="font-size: 14px">80386CPU引入“异常”概念,表示内部中断,而外部中断称为“中断”。</span></p>
<p><span style="font-size: 14px">异常可归为三类:故障、陷阱和中止。故障和陷阱可以恢复,中止不能,只能系统重启。</span></p>
<p><span style="font-size: 14px">故障:指令启动后执行前被检测到的异常,中断服务完成后返回该指令。如被 0 除,溢出,保护模式下越界等;</span></p>
<p><span style="font-size: 14px">陷阱:指令执行完后才报告,中断服务程序返回吓一跳指令。如内部中断,等待调试,设置断点等;</span></p>
<p><span style="font-size: 14px">中止:对引起异常的指令的确切位置不确定的异常。如双重故障异常、协处理器段越界等。</span></p>
<p><span style="font-size: 14px"><img src="https://img2020.cnblogs.com/blog/790029/202004/790029-20200427221308438-2068729403.png"></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>2、保护模式下的中断与异常</strong></p>
<p>与实模式相比,CPU 根据中断类型号从中段描述符表 IDT 而不是中断向量表获取中断服务程序入口的有关信息;中断过程中药对被中断程序代码进行保护;若有出错码还需要将其压入堆栈。</p>
<p>① 中断描述符表</p>
<p>IDT 起始位置通过中断描述符表寄存器 IDTR 设置,只有一个,包含的是<strong>门描述符</strong>而不是中断向量,可以使中断门、陷阱门或人物们,最多允许 256 个门描述符:门 0 ~ 门 255。</p>
<p>② 获得中断服务程序地址</p>
<p>③ 中断响应及异常处理</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/jinkun113/p/12343867.html
頁: [1]
查看完整版本: [课堂小笔记] 汇编语言