汇编语言各种指令的解释与用法
<div id="topics"><div class="post">
<h1 class="postTitle"> 汇编语言各种指令的解释与用法 </h1>
<div class="clear"> </div>
<div class="postBody">
<div id="cnblogs_post_body" class="blogpost-body blogpost-body-html">
<p class="p" align="justify">【<strong><span style="font-family: 宋体">数据传输指令</span></strong><strong><span style="font-family: 宋体">】</span></strong></p>
<p class="p" align="justify">一、<strong><span style="font-family: 宋体">通用数据传送指令</span></strong><strong><br></strong>1、传送指令<strong> </strong><strong>MOV</strong> (move)<br><span style="font-family: 宋体">指令的汇编格式:</span>MOV DST,SRC<br><span style="font-family: 宋体">指令的基本功能:</span>(DST)<-(SRC) 将原操作数(字节或字)传送到目的地址。<br>指令支持的寻址方式:目的操作数和源操作数不能同时用存储器寻址方式,这个限制适用于所有指令。指令的执行对标志位的影响:不影响标志位。<br><span style="font-family: 宋体">指令的特殊要求:目的操作数</span>DST和源操作数SRC不允许同时为段寄存器;<br><span style="font-family: 宋体">目的操作数</span>DST不能是CS,也不能用立即数方式。<br>2、<strong><span style="font-family: 宋体">进栈指令</span> </strong><strong>PUSH</strong> (push onto the stack) <br><span style="font-family: 宋体">出栈指令</span> POP (pop from the stack)<br><span style="font-family: 宋体">指令的汇编格式:</span>PUSH SRC ;POP DST<br><span style="font-family: 宋体">指令的基本功能:</span>PUSH指令在程序中常用来暂存某些数据,而POP指令又可将这些数据恢复。PUSH SRC (SP)<-(SP)-2 ;(SP)<-(SRC)<br>POP DST (DST)<-((SP));(SP)<-(SP)<br><span style="font-family: 宋体">指令支持的寻址方式:</span>push 和 pop指令不能不能使用立即数寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>PUSH 和 POP指令都不影响标志位。<br><span style="font-family: 宋体">指令的特殊要求:</span>PUSH 和 POP指令只能是字操作,因此,存取字数据后,SP的修改必须是+2 或者 -2; POP指令的DST不允许是CS寄存器;<br>3、交换指<strong><span style="font-family: 宋体">令</span> </strong><strong>XCHG</strong> (exchange)<br><span style="font-family: 宋体">指令的汇编格式:</span>XCHG OPR1,OPR2<br><span style="font-family: 宋体">指令的基本功能:</span>(OPR1)<->(OPR2)<br>指令支持的寻址方式:一个操作数必须在寄存器中,另一个操作数可以在寄存器或存储器中。<br>指令对标志位的影戏:不影响标志位。<br>指令的特殊要求:不允许使用段寄存器。<br>二、<strong><span style="font-family: 宋体">累加器专用传送指令</span></strong><strong><br></strong>4、输入指令 <strong>IN</strong> (input)<br><span style="font-family: 宋体">输出指令</span> OUT (output)<br><span style="font-family: 宋体">指令的汇编格式:</span>IN ac,port port<=0FFH<br>IN ac,DX port>0FFH<br>OUT port,ac port<=0FFH<br>OUT DX,ac port>0FFH<br><span style="font-family: 宋体">指令的基本功能:对</span>8086及其后继机型的微处理机,所有I/O端口与CPU之间的通信都由输入输出指令IN和OUT来完成。IN指令将信息从I/O输入到CPU,OUT指令将信息从CPU输出到I/O端口,因此,IN和OUT指令都要指出I/O端口地址。<br>IN ac,port port<=0FFH (AL)<-(port)传送字节 或 (AX)<-(port+1,port)传送字<br>IN ac,DX port>0FFH (AL)<-((DX))传送字节或 (AX)<-((DX)+1,(DX))传送字<br>OUT port,ac port<=0FFH (port)<-(AL)传送字节 或 (port+1,port)<-(AX)传送字<br>OUT DX,ac port>0FFH (DX)<-(AL)传送字节 或 ((DX)+1,(DX))<-(AX)传送字<br><span style="font-family: 宋体">指令对标志位的影响:不影响标志位。指令的特殊要求:只限于在</span>AL或AX与I/O端口之间传送信息。传送16位信息用AX,传送8位信息用AL,这取决于外设端口的宽度。<br>5、换码指令 <strong>XLAT</strong> (translate)<br><span style="font-family: 宋体">指令的汇编格式:</span>XLAT opr 或 XLAT<br><span style="font-family: 宋体">指令的基本功能:这条指令根据</span>AL寄存器提供的位移量,将BX指使的字节表格中的代码换存在AL中。 (AL)<-((DS)*16+(BX)+(AL))<br><span style="font-family: 宋体">指令对标志位的影响</span>:不影响标志位。<br><span style="font-family: 宋体">指令的特殊要求:所建字节表格的长度不能超过</span>256字节,因为存放位移量的是8位寄存器AL。opr为表格的首地址,因为opr所表示的偏移地址已存入BX寄存器,所以opr在换码指令中可有可无,有则提高程序的可读性。<br>三、地址传送指令<br>6、有效地址传送器 <strong>LEA</strong> (load effective address)<br><span style="font-family: 宋体">指令的汇编格式:</span>LEA reg,src<br><span style="font-family: 宋体">指令的基本功能:</span>LEA指令把源操作数的有效地址送到指定的寄存器,这个有效地址是由src选定的一种存储器寻址方式确定的。<br>指令支持的寻址方式:各种存储器寻址方式。<br>指令对标志位的影响:不影响标志位。<br><span style="font-family: 宋体">指令的特出要求:指令中</span>reg不能是段寄存器;<br>7、<strong><span style="font-family: 宋体">指针送寄存器和</span>DS LDS</strong> (load DS with point)<br><span style="font-family: 宋体">指针送寄存器和</span>ES LES (load ES with point)<br><span style="font-family: 宋体">指令的汇编格式:</span>LDS reg,src LES reg,src<br><span style="font-family: 宋体">指令的基本功能:</span>LDS和LES指令把确定内存单元位置的偏移地址送寄存器,段地址DS或ES。这个偏移地址和段地址(也称地址指针)是由src指定的两个相继字单元提供的。<br>LDS reg,src (reg)<-(src) (DS)<-(src+2)<br>LES reg,src (reg)<-(src) (ES)<-(src+2)<br><span style="font-family: 宋体">指令支持的寻址方式:</span>src必须为存储器寻址方式<br>指令对标志位的影响:不影响标志位。<br><span style="font-family: 宋体">指令的特殊要求:指令中</span>REG不能是段寄存器;<br>四、<strong><span style="font-family: 宋体">标志寄存器传送指令</span></strong><strong><br></strong>8、<strong><span style="font-family: 宋体">标志寄存器的低字节送</span>AH LAHF</strong> (load AH with FLAGS)<br><span style="font-family: 宋体">指令的汇编格式:</span>LAHF<br><span style="font-family: 宋体">指令的基本功能:</span>(AH)<-(FLAGS)0-7<br>指令对标志位的影响:不影响标志位<br>9、<strong>AH<span style="font-family: 宋体">送标志寄存器低字节 </span><span style="font-family: "Times New Roman"">SAHF</span></strong>(store AH into FLAGS)<br><span style="font-family: 宋体">指令的格式:</span>SAHF<br><span style="font-family: 宋体">指令的基本功能:</span>(FLAGS)0-7<-(AH)<br>指令对标志位的影响:由装入值来确定标志位的值。<br>10、<strong><span style="font-family: 宋体">标志进栈</span> PUSHF</strong> (push the flags)<br><span style="font-family: 宋体">指令的汇编格式:</span>PUSHF<br><span style="font-family: 宋体">指令的基本功能:</span>(SP)<-(SP)-2 ((SP)+1,(SP))<-(FLAGS)0-15<br>指令对标志位的影响:不影响标志位。<br>11、<strong><span style="font-family: 宋体">标志出栈</span> POPF</strong> (pop the FLAGES)<br><span style="font-family: 宋体">指令的汇编格式:</span>POPF<br><span style="font-family: 宋体">指令的基本功能:</span>(FLAGS)0-15<-((SP)+1,(SP)) (SP)<-(SP)+2<br>指令对标志位的影响:由装入值来确定标志位的值。</p>
<p class="p" align="justify"><strong><span style="font-family: 宋体">【</span></strong><strong><span style="font-family: 宋体">算术指令</span></strong><strong><span style="font-family: 宋体">】</span></strong><br>一、<strong><span style="font-family: 宋体">加法指令</span></strong><br>12、加法指令 <strong>ADD</strong> (addition)<br><span style="font-family: 宋体">指令的汇编格式:</span>add dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(src)+(dst)<br>指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 加法结果为负数(符号位为1)<br>SF=0 加法结果为正数(符号位为0)<br>ZF=1 加法结果为零<br>ZF=0 加法结果不为零<br>CF=1 最高有效位向高位有进位<br>CF=0 最高有效位向高位无进位<br>OF=1 两个同符号数相加(正数+正数或负数+负数),结果符号与其相反。<br>OF=0 两个不同符号数相加,或同符号数相加,结果符号与其相同。<br>13、带进为加法指令 <strong>ADC</strong> (add with carry)<br><span style="font-family: 宋体">指令的汇编格式:</span>ADD dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(src)+(dst)+CF<br>指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 加法结果为负数<br>SF=0 加法结果为正数<br>ZF=1 加法结果为零<br>ZF=0 加法结果不为零<br>CF=1 最高有效位向高位有进位<br>CF=0 最低有效位相高位无进位<br>OF=1 两个同符号数相加,结果符号与其相反,<br>OF=0 两个同符号数相加,或同符号相加,结果符号与其相同<br>14、加1指令 <strong>INC</strong> (increament)<br><span style="font-family: 宋体">指令的汇编格式:</span>INC opr<br><span style="font-family: 宋体">指令的基本功能:</span>(opr)<-(opr)<br><span style="font-family: 宋体">指令支持的寻址方式</span> <span style="font-family: 宋体">可以使用除立即数方式外的任何寻址方式</span><br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 加法结果为负数<br>SF=0 加法结果为正数<br>ZF=1 加法结果为零<br>ZF=0 加法结果不为零<br>OF=1 两个同符号数相加,结果符号与其相反,<br>OF=0 两个同符号数相加,或同符号相加,结果符号与其相同。<br>二、<strong><span style="font-family: 宋体">减法指令</span></strong><br>15、减法指令 <strong>SUB</strong> (subtract)<br><span style="font-family: 宋体">指令的汇编格式:</span>SUB dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(dst)-(src)<br>指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 减法结果为负数(符号位为1)<br>SF=0 减法结果为正数(符号位为0)<br>ZF=1 减法结果为零<br>ZF=0 减法结果不为零<br>CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)<br>CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>16、带借位减法指令 <strong>SBB</strong> (subtract with borrow)<br><span style="font-family: 宋体">指令的汇编格式:</span>SBB dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(dst)-(src)-CF<br>指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 减法结果为负数(符号位为1)<br>SF=0 减法结果为正数(符号位为0)<br>ZF=1 减法结果为零<br>ZF=0 减法结果不为零<br>CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)<br>CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>17、减1指令 <strong>DEC</strong> (decrement)<br><span style="font-family: 宋体">指令的汇编格式:</span>DEC opr<br><span style="font-family: 宋体">指令的基本功能:</span>(opr)<-(opr)-1<br>指令支持的寻址方式:可以使用除立即数方式外的任何寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>SF=1 减法结果为负数(符号位为1)<br>SF=0 减法结果为正数(符号位为0)<br>ZF=1 减法结果为零<br>ZF=0 减法结果不为零<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>18、比较指令 <strong>CMP</strong> (compare)<br><span style="font-family: 宋体">指令的汇编格式:</span>CMP opr1,opr2<br><span style="font-family: 宋体">指令的基本功能:</span>(opr1)-(opr2),根据相减结果设置条件码,但不回送结果。<br>指令支持的寻址方式:他们两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。<br>指令对标志位的影响:</p>
<p class="p" align="justify">SF=1 减法结果为负数(符号位为1)<br>SF=0 减法结果为正数(符号位为0)<br>ZF=1 减法结果为零<br>ZF=0 减法结果不为零<br>CF=1 二进制减法运算中</p>
<p class="p" align="justify">最高有效位向高位有借位(被减数小于减数,不够减的情况)<br>CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>19、求补指令 <strong>NEG</strong> (negate)<br><span style="font-family: 宋体">指令的汇编格式:</span>NEG opr<br><span style="font-family: 宋体">指令的基本功能:</span>(opr)<- -(opr)<br>指令支持的寻址方式:可以使用除立即数方式外的任何寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=1 不为0的操作数求补时<br><span style="font-family: 宋体"> </span> CF=0 为0的操作数求补时<br>OF=1 操作数为-128(字节运算)或操作数为-32768(字运算)<br>OF=0 当求补运算的操作数不为-128(字节)或-32768(字)时三、乘法指令<br>20、无符号乘法指令 <strong>NUL</strong> (unsigned multiple)<br><span style="font-family: 宋体">有符号乘法指令</span> IMUL(signed muliple)<br><span style="font-family: 宋体">指令的汇编格式:</span>NUL src IMUL src<br><span style="font-family: 宋体">指令的基本功能:</span>(AX)<-(AL)*(src) (DX,AX)<-(AX)*(src)<br><span style="font-family: 宋体">指令支持的寻址方式:</span>src可以使用除立即数方式以外的任一种寻址方式。<br><span style="font-family: 宋体">指令对标志位的影响:乘法指令只影响标志位</span>CF和OF,其他条件码位无定义。<br>MUL指令的条件码设置为:<br>CF OF=0 0 乘积的高一半为0(字节操作的(AH)或字操作的(DX))<br>CF OF=1 1 乘积的高一半不为0<br>IMUL指令的条件码设置为:<br>CF OF=0 0 乘积的高一半为低一半的符号扩展.<br>CF OF=1 1 其他情况<br><span style="font-family: 宋体">指令的特殊要求:</span>MUL和IMUL指令的区别仅在于操作数是无符号还是带符号数,它们的共同点是,指令中只给出源操作数src,目的操作数是隐含的,它只能是累加器(字运算为AX,字节运算为AL)。隐含的乘积寄存器是AX或DX(高位)和AX(低位)。<br>四、<strong><span style="font-family: 宋体">符号扩展指令</span></strong><strong><br></strong>21、节扩展为字 <strong>CBW</strong> (convert byte to word)<br><span style="font-family: 宋体">指令的汇编格式:</span>CBW<br><span style="font-family: 宋体">指令的基本功能:</span>(AH)=00H 当(AL)的最高有效位为0时<br>(AH)=FFH 当(AL)的最高有效位为1时<br>指令对标志位的影响:不影响标志位<br><span style="font-family: 宋体">指令的特殊要求:这是条无操作数的指令,进行符号扩展的操作数必须存放在</span>AL寄存器 AX寄存器中。<br>22、字扩展为双字 <strong>CWD</strong> (convert word to double word)<br><span style="font-family: 宋体">指令的汇编格式:</span>CWD<br><span style="font-family: 宋体">指令的基本功能:</span>(DX)=0000H 当(AX)的最高有效位为0时<br>(DX)=FFFFH 当(AX)的最高有效位为1时<br>指令对标志位的影响:不影响标志位<br><span style="font-family: 宋体">指令的特殊要求:这是条无操作数的指令,进行符号扩展的操作数必须存放在</span>AL寄存器或AX寄存器中。<br>五、除法指令<br>23、无符号数除法 <strong>DIV</strong> (unsigned divide)<br><span style="font-family: 宋体">带符号数除法</span> IDIV (singed divide)<br><span style="font-family: 宋体">指令的汇编格式:</span>DIV src IDIV src<br>指令的基本功能:字操作<br>(AL)<-(AX)/src的商 (AH)<-(AX)/src的余数<br>字节操作<br>(AX)<-(DX,AX)/src的商 (DX)<-(DX,AX)/src的余数<br><span style="font-family: 宋体">指令支持的寻址方式:</span>src作为除数,可用除立即数以外的任一种寻址方式来取得。<br>指令对标志位的影响:不影响条件码。<br><span style="font-family: 宋体">指令的特殊要求:除法指令要求字操作时,被除数必须为</span>32位,除数是16位,商和余数是16位的;字节操作时,被除数必须为16位,除数是8位,得到的商和余数是8位的。</p>
<p class="p" align="justify">六、<strong><span style="font-family: 宋体">十进制调整指令</span></strong></p>
<p class="p" align="justify"><strong><span style="font-family: 宋体">【</span></strong><strong><span style="font-family: 宋体">逻辑指令</span></strong><strong><span style="font-family: 宋体">】</span></strong></p>
<p><strong><br></strong><span style="font-family: 宋体">一、</span><strong><span style="font-family: 宋体">逻辑运算</span></strong><br><span style="font-family: 宋体">指令的格式:</span><strong>AND</strong> dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(dst)<span style="font-family: 宋体">与</span><span style="font-family: "Times New Roman"">(src)</span><br><span style="font-family: 宋体">指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,源操作数和目地操作数必须有一个寄存器寻址方式。</span><br><span style="font-family: 宋体">指令对标志位的影响:指令执行后</span> CF <span style="font-family: 宋体">和 </span><span style="font-family: "Times New Roman"">OF </span><span style="font-family: 宋体">置零,</span><span style="font-family: "Times New Roman"">AF</span><span style="font-family: 宋体">无定义。</span><br>SF=1 <span style="font-family: 宋体">指令执行后的结果为负数(符号位为</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">)</span><br>SF=0 <span style="font-family: 宋体">指令执行后的结果为正数(符号位为</span><span style="font-family: "Times New Roman"">0</span><span style="font-family: 宋体">)</span><br>ZF=1 <span style="font-family: 宋体">指令执行后的结果为零</span><br>ZF=0 <span style="font-family: 宋体">指令执行后的结果不为零</span><br>PF=1 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为偶数时置</span><span style="font-family: "Times New Roman"">1</span><br>PF=0 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为奇数时置</span><span style="font-family: "Times New Roman"">0</span><br>25<span style="font-family: 宋体">、逻辑或 </span><strong>OR</strong> (logic or)<br><span style="font-family: 宋体">指令的汇编格式:</span>OR dst<span style="font-family: 宋体">,</span><span style="font-family: "Times New Roman"">src</span><br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(dst)<span style="font-family: 宋体">或</span><span style="font-family: "Times New Roman"">(src)</span><br><span style="font-family: 宋体">指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,原操作数和目的操作数必须有一个寄存器寻址方式。</span><br><span style="font-family: 宋体">指令对标志位的影响:令执行后</span> CF <span style="font-family: 宋体">和 </span><span style="font-family: "Times New Roman"">OF </span><span style="font-family: 宋体">置零,</span><span style="font-family: "Times New Roman"">AF</span><span style="font-family: 宋体">无定义。</span><br>SF=1 <span style="font-family: 宋体">指令执行后的结果为负数(符号位为</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">)</span><br>SF=0 <span style="font-family: 宋体">指令执行后的结果为正数(符号位为</span><span style="font-family: "Times New Roman"">0</span><span style="font-family: 宋体">)</span><br>ZF=1 <span style="font-family: 宋体">指令执行后的结果为零</span><br>ZF=0 <span style="font-family: 宋体">指令执行后的结果不为零</span><br>PF=1 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为偶数时置</span><span style="font-family: "Times New Roman"">1</span><br>PF=0 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为奇数时置</span><span style="font-family: "Times New Roman"">0</span><br>26<span style="font-family: 宋体">、逻辑非 </span><strong>NOT</strong> (logic not)<br><span style="font-family: 宋体">指令的汇编格式:</span>NOT orc<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(opr)<br><span style="font-family: 宋体">指令支持的寻址方式:除立即数寻址方式以外的其余寻址方式</span><br><span style="font-family: 宋体">指令对标志位的影响:对标志位无影响</span><br>27<span style="font-family: 宋体">、异或 </span><strong>XOR</strong> (exclusice or)<br><span style="font-family: 宋体">指令的汇编格式:</span>XOR dst,src<br><span style="font-family: 宋体">指令的基本功能:</span>(dst)<-(dst)<span style="font-family: 宋体">异或</span><span style="font-family: "Times New Roman"">(src)</span><br><span style="font-family: 宋体">指令支持的寻址方式:两个操作数不能同时为存储器寻址。即为除源操作数为立即数的情况外,原操作数和目的操作数必须有一个寄存器寻址方式。</span><br><span style="font-family: 宋体">指令对标志位的影响:令执行后</span> CF <span style="font-family: 宋体">和 </span><span style="font-family: "Times New Roman"">OF </span><span style="font-family: 宋体">置零,</span><span style="font-family: "Times New Roman"">AF</span><span style="font-family: 宋体">无定义。</span><br>SF=1 <span style="font-family: 宋体">指令执行后的结果为负数(符号位为</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">)</span><br>SF=0 <span style="font-family: 宋体">指令执行后的结果为正数(符号位为</span><span style="font-family: "Times New Roman"">0</span><span style="font-family: 宋体">)</span><br>ZF=1 <span style="font-family: 宋体">指令执行后的结果为零</span><br>ZF=0 <span style="font-family: 宋体">指令执行后的结果不为零</span><br>PF=1 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为偶数时置</span><span style="font-family: "Times New Roman"">1</span><br>PF=0 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为奇数时置</span><span style="font-family: "Times New Roman"">0</span><br>28<span style="font-family: 宋体">、测试指令 </span><strong>TEST</strong><strong><br></strong><span style="font-family: 宋体">指令的汇编格式:</span>TEST opr1,opr2<br><span style="font-family: 宋体">指令的基本功能:</span>(opr1)<span style="font-family: 宋体">与</span><span style="font-family: "Times New Roman"">(opr2)</span><br><span style="font-family: 宋体">指令支持的寻址方式:两个操作数不能同时为存储器寻址,即为除源操作数为立即数的情况外,源操作数和目的操作数必须有一个寄存器寻址方式。</span><br><span style="font-family: 宋体">指令对标志位的影响:令执行后</span> CF <span style="font-family: 宋体">和 </span><span style="font-family: "Times New Roman"">OF </span><span style="font-family: 宋体">置零,</span><span style="font-family: "Times New Roman"">AF</span><span style="font-family: 宋体">无定义。</span><br>SF=1 <span style="font-family: 宋体">指令执行后的结果为负数(符号位为</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">)</span><br>SF=0 <span style="font-family: 宋体">指令执行后的结果为正数(符号位为</span><span style="font-family: "Times New Roman"">0</span><span style="font-family: 宋体">)</span><br>ZF=1 <span style="font-family: 宋体">指令执行后的结果为零</span><br>ZF=0 <span style="font-family: 宋体">指令执行后的结果不为零</span><br>PF=1 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为偶数时置</span><span style="font-family: "Times New Roman"">1</span><br>PF=0 <span style="font-family: 宋体">结果操作数中</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">的个数为奇数时置</span><span style="font-family: "Times New Roman"">0</span><br><span style="font-family: 宋体">二、</span><strong><span style="font-family: 宋体">移位指令</span></strong><br>29<span style="font-family: 宋体">、逻辑左移 </span><strong>SHL</strong> (shift logical left)<br><span style="font-family: 宋体">指令的汇编格式:</span>SHL dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>SHL<span style="font-family: 宋体">指令向左逐位移动</span><span style="font-family: "Times New Roman"">cnt</span><span style="font-family: 宋体">次,每次逐位移动后,最低位用</span><span style="font-family: "Times New Roman"">0</span><span style="font-family: 宋体">来补充,最高位移入</span><span style="font-family: "Times New Roman"">CF</span><span style="font-family: 宋体">。</span><br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst<span style="font-family: 宋体">可以是除立即数外的任何寻址方式。移位次数(或位数)</span><span style="font-family: "Times New Roman"">cnt=1</span><span style="font-family: 宋体">时,</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">可以直接写在指令中,</span><span style="font-family: "Times New Roman"">cnt</span><span style="font-family: 宋体">〉</span><span style="font-family: "Times New Roman"">1</span><span style="font-family: 宋体">时,</span><span style="font-family: "Times New Roman"">cnt</span><span style="font-family: 宋体">必须放入</span><span style="font-family: "Times New Roman"">CL</span><span style="font-family: 宋体">寄存器中。</span><br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=<span style="font-family: 宋体">移入的数值</span><br>OF=1 <span style="font-family: 宋体">当</span><span style="font-family: "Times New Roman"">cnt=1</span><span style="font-family: 宋体">时,移动后最高位的值发生变化。</span><br>OF=0 <span style="font-family: 宋体">当</span><span style="font-family: "Times New Roman"">cnt=1</span><span style="font-family: 宋体">时,移动时最高位的值未发生变化。</span><br>SF<span style="font-family: 宋体">、</span><span style="font-family: "Times New Roman"">ZF</span><span style="font-family: 宋体">、</span><span style="font-family: "Times New Roman"">PF</span><span style="font-family: 宋体">根据移动后的结果设置</span></p>
<p>30、逻辑右移 <strong>SHR </strong>(shift logical right)<br><span style="font-family: 宋体">指令的汇编格式:</span>SHR dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>SHR指令向右逐位移动cnt次,每次逐位移动后,最高位用0来补充,最低位移入CF。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值<br>OF=1 当cnt=1时,移动后最高位的值发生变化。<br>OF=0 当cnt=1时,移动时最高位的值未发生变化。<br>SF、ZF、PF根据移动后的结果设置。<br>31、算术左移 <strong>SAL</strong> (shift arithmetic left)<br><span style="font-family: 宋体">指令的汇编格式:</span>SAL dst cnt<br><span style="font-family: 宋体">指令的基本功能:</span>SAL指令向左逐位移动cnt次,每次逐位移动后,最低位用0来补充,最高位移入CF。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值<br>OF=1 当cnt=1时,移动后最高位的值发生变化。<br>OF=0 当cnt=1时,移动时最高位的值未发生变化。<br>SF、ZF、PF根据移动后的结果设置。<br>32、算术右移 <strong>SAR</strong> (shift arithmetic right)<br><span style="font-family: 宋体">指令的汇编格式:</span>SAR dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>SAR指令向右逐位移动cnt次,每次逐位移动后,最高位用符号位来补充,最低位移入CF。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值<br>OF=1 当cnt=1时,移动后最高位的值发生变化。<br>OF=0 当cnt=1时,移动时最高位的值未发生变化。<br>SF、ZF、PF根据移动后的结果设置。<br>33、循环左移 <strong>ROL</strong> (rotate left)<br><span style="font-family: 宋体">指令的汇编格式:</span>ROL dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>ROL 对由dst指定的寄存器或存储器操作数左移循环移动cnt所指定的次数,每左移一次,把最高位同时移入CF和操作数最低位。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值<br>OF=1 当cnt=1时,移动后最高位的值发生变化。<br>OF=0 当cnt=1时,移动时最高位的值未发生变化。<br>SF、ZF、PF根据移动后的结果设置。<br>34、循环右移 <strong>ROR</strong> (rotate right)<br><span style="font-family: 宋体">指令的汇编格式:</span>ROR dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>ROR 对由dst指定的寄存器或存储器操作数右移循环移动cnt所指定的次数,每右移一次,把最低位同时移入CF和操作数最高位。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt>1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值<br>OF=1 当cnt=1时,移动后最高位的值发生变化。<br>OF=0 当cnt=1时,移动时最高位的值未发生变化。<br>SF、ZF、PF根据移动后的结果设置。<br>35、带进位的循环左移<strong> RCL</strong> (rotate left through carry)<br><span style="font-family: 宋体">指令的汇编格式:</span>RCL dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>RCL 对由dst指定的寄存器或存储器操作数,连同进位标志CF左循环移动,m所指定的次数,每左移一次,把操作数的最高位移入CF,而CF中原有内容移入操作数的最低位。<br><span style="font-family: 宋体">指定支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写在指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值。<br>OF=1 当cnt=1时,移动后最高位的值未发生变化。<br>OF=0 当cnt=1时,移动后最高位的值发生变化。<br>SF、ZF、PF标志位不受影响。<br>36、带进位的循环右移 <strong>RCR</strong> (rotate right through carry)<br><span style="font-family: 宋体">指令的汇编格式:</span>RCR dst,cnt<br><span style="font-family: 宋体">指令的基本功能:</span>RCR 对由dst指定的寄存器或存储器操作数,连同进位标志CF右循环移动,m所指定的次数,每右移一次,把操作数的最高低位移入CF,而CF中原有内容移入操作数的最高位。<br><span style="font-family: 宋体">指令支持的寻址方式:目的操作数</span>dst可以是除立即数外的任何寻址方式。移动次数(或位数)cnt=1时,1可以直接写入指令中,cnt〉1时,cnt必须放入CL寄存器中。<br><span style="font-family: 宋体">指令对标志位的影响:</span>CF=移入的数值。<br>OF=1 当cnt=1时,操作数最高位的值未发生变化。<br>OF=0 当cnt=1时,操作数最高位的值发生变化。<br>SF、ZF、PF标志位不受影响。</p>
<p><strong>【串处理指令】</strong></p>
<p><br>一、<strong>设置方向标志指令</strong><br>37、DF置零 <strong>CLD</strong> (clear direction flag)<br>DF置一 STD (set direction flag)<br><span style="font-family: 宋体">指令的汇编格式:</span>CLD<br>STD<br><span style="font-family: 宋体">指令的基本功能:</span>CLD DF=0<br>STD DF=1<br>二、串处理指令<br>38、串传送 <strong>MOVSB / MOVSW</strong> (move string byte/word)<br><span style="font-family: 宋体">指令的汇编格式:</span>MOVSB<br>MOVSW<br><span style="font-family: 宋体">指令的基本功能:</span>(ES:DI)<-(DS:SI)<br>(SI)<-(SI)+/-1(字节)或+/-2(字)<br>(DI)<-(DI)+/-1(字节)或+/-2(字)<br>指令对条件码的影响:不影响条件码。<br><span style="font-family: 宋体">指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是</span>SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。<br>39、存串 <strong>STOSB / STOSW</strong> (stroe from string byte/word)<br><span style="font-family: 宋体">指令的汇编格式:</span>STOSB<br>STOSW<br><span style="font-family: 宋体">指令的基本功能:</span>(ES:DI)<-(AL)或(AX)<br>(DI)<-(DI)+/-1(字节)或+/-2(字)<br>指令对条件码的影响:不影响条件码。<br><span style="font-family: 宋体">指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是</span>SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。<br>40、取串<strong>LODSB / LODSW</strong> (load from string byte/word)<br><span style="font-family: 宋体">指令的汇编格式:</span>LODSB<br>LODSW<br><span style="font-family: 宋体">指令的基本功能:</span>(AL)或(AX)<-(DS:SI)<br>(SI)<-(SI)+/-1(字节)或+/-2(字)<br>指令对条件码的影响:不影响条件码。<br><span style="font-family: 宋体">指令的特殊要求:源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是</span>SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。<br>41、串比较 <strong>CMPSB / CMPSW</strong> (compare string byte/word)<br><span style="font-family: 宋体">指令的汇编格式:</span>CMPSB<br>CMPSW<br><span style="font-family: 宋体">指令的基本功能:</span>(DS:SI)-(ES:DI) 根据比较结果设置条件码<br>(SI)<-(SI)+/-1(字节)或+/-2(字)<br>(DI)<-(DI)+/-1(字节)或+/-2(字)<br><span style="font-family: 宋体">指令对条件码的影响:</span>SF=1 减法结果为负数(符号位为1)<br>SF=0 减法结果为正数(符号位为0)<br>ZF=1 减法结果为零<br>ZF=0 减法结果不为零<br>CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)<br>CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>42、串扫描 <strong>SCASB / SCASW</strong> (scan string byte / word)<br><span style="font-family: 宋体">指令的格式:</span>SCASB<br>SCASW<br><span style="font-family: 宋体">指令的基本功能:</span>(AL)<-(ES:DI)或(AX)<-(ES:DI) 根据扫描比较的结果设置条件码。<br>(DI)<-(DI)+/-1(字节)或+/-2(字)<br><span style="font-family: 宋体">指令对条件码的影响:</span>SF=1 结果为负数(符号位为1)<br>SF=0 结果为正数(符号位为0)<br>ZF=1 结果为零<br>ZF=0 结果不为零<br>CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)<br>CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)<br>OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。<br>OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。<br>三、<strong>串重复前缀</strong><br>43、重复执行串 <strong>REP</strong> <br><span style="font-family: 宋体">指令的汇编格式:</span>REP (CX)=重复次数<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)=0时,串指令执行完毕,否则执行② ~ ④<br>② (CX)←(CX)-1③ 执行串指令(MOVS或STOS)④ 重复执行①<br>44、相等/为零时重复执行串指令 REPE/REPZ<br><span style="font-family: 宋体">指令的汇编格式:</span>REPE / REPZ (CX)=比较/扫描的次数<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)=0或ZF=0时,结束执行串指令,否则继续② ~ ④<br>② (CX)←(CX)-1③ 执行串指令(CMPS或SCAS)④ 重复执行①<br>45、不等/不为零时重复执行串指令 REPNE / PEPNZ<br><span style="font-family: 宋体">指令的汇编格式:</span>REPNE / PEPNZ (CX)=比较/扫描的次数<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)=0或ZF=1,结束执行串指令,否则继续② ~ ④<br>② (CX)←(CX)-1③ 执行串指令(CMPS或SCAS)④ 重复执行①</p>
<p><strong>【控制转移指令】</strong></p>
<p><br>一、<strong>无条件转移指令</strong><br>46、短转移 <strong>JMP SHORT label</strong> (short jump)<br><span style="font-family: 宋体">指令的汇编格式:</span>JMP SHORT label<br><span style="font-family: 宋体">指令的基本功能:</span>(IP)<-当前(IP)+8位位移量 8位位移量是汇编程序在汇编源程序时,根据目标地址和当前IP之间的距离自动生成的。<br>指令对条件码的影响:对标志位无影响。<br>47、近转移<strong> JMP NEAR PTR label</strong> (near jump)<br><span style="font-family: 宋体">指令的汇编格式:直接转移</span> JMP label (direct jump)<br><span style="font-family: 宋体">寄存器间接转移</span> JMP reg (register indirect jump)<br><span style="font-family: 宋体">存储器间接转移</span> JMP WORD PTR OPR (memory indirect jump)<br><span style="font-family: 宋体">指令的基本功能:</span>JMP label (IP) <- OFFSET label = (IP)当前+16位位移量<br>JMP reg (IP) <- (reg)<br>JMP WORD PTR OPR (IP) <- (PA+1,PA)<br>指令支持的寻址方式:指令中的转向地址可以是直接寻址方式、寄存器寻址方式、寄存器间接寻址方式和存储器寻址方式。<br>指令对条件码的影响:对标志位无影响。<br>48、远转移 <strong>JMP FAR PTR label</strong> (for jump)<br><span style="font-family: 宋体">指令的汇编格式:</span>JMP FAR PTR label<br><span style="font-family: 宋体">指令的基本功能:</span>(IP)<-label的段内偏移地址 (CS)<-label所在段的段地址<br>指令支持的寻址方式:远转移的目的地址可以使用除立即寻址方式外的任何寻址方式来表示。指令对条件码的影响:对标志位无影响。<br>二、<strong>条件转移指令</strong><br>指令的汇编格式及功能<br>根据条件码的值转移:<br>49、JZ(JE) OPR ZF=1 <strong>ZF=0(运算结果为0,ZF就置1)</strong><strong><br></strong>50、JNZ(JNE) OPR ZF=0<br>51、JS OPR SF=1 <strong>SF</strong>=0(二进制最高位是什么,SF就是什么,如最高位为1则SF=1)<br>52、JNS OPR SF=0<br>53、JO OPR OF=1 <strong>OF</strong>=1 (两个负数相加变成正数,溢出) <br>54、JNO OPR OF=0<br>55、JP OPR PF=1 <strong>PF</strong>=0 (反映结果“1”的个数,奇数☞0 偶数个☞1<span style="font-family: 宋体">)</span> <br>56、JNP OPR PF=0 <br>57、JC OPR CF=1 <strong>CF</strong>=1(最高位有进位或借位就置1) <br>58、JNC OPR CF=0<br>比较两个无符号数,根据比较的结果转移<br>59、JB(JNAE,JC) OPR CF=1 被减数小于减数则转移<br>60、JNB(JAE,JNC) OPR CF=0 被减数大于或等于减数则转移<br>61、JBE(JNA) OPR CF或ZF=1 被减数小于或等于减数则转移<br>62、JNBE(JA) OPR CF或ZF=0 被减数大于减数则转移<br>比较两个带符号数,根据比较结果转移<br>63、JL/JNGE OPR SF异或OF=1 被减数小于减数则转移 <br>64、JNL/JGE SF异或OF=0 被减数不小于减数则转移<br>65、JLE/JNE (SF异或OF)与ZF=1 被减数不大于减数则转移<br>66、JNLE/JG (SF异或OF)与ZF=0 被减数大于减数则转移<br><span style="font-family: 宋体">根据</span>CX寄存器的值转移<br>67、JCXZ (CX)=0 CX内容为零则转移<br><span style="font-family: 宋体">指令的特殊要求:所有条件转移指令都是短转移指令,转移的目标地址必须在当前</span>IP地址的-128至+127字节范围之内,因此条件转移指令是2字节指令。<br>三、<strong>循环指令</strong><br>68、循环<strong> LOOP</strong> (loop)<br><span style="font-family: 宋体">指令的汇编格式:</span>LOOP label<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)←(CX)-1 ② 若(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。<br><span style="font-family: 宋体">指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用</span>8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。<br>69、为零/相等时循环 <strong>LOOPZ/LOOPE</strong> (loop while nonzero or equal)<br><span style="font-family: 宋体">指令的汇编格式:</span>LOOPNZ/LOOPNE label<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)←(CX)-1<br><span style="font-family: 宋体"> </span> <span style="font-family: 宋体"> </span>② 若ZF=1且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。<br><span style="font-family: 宋体">指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用</span>8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。<br>70、不为零/不相等时循环 <strong>LOOPNZ/LOOPNE</strong> (loop while nonzero or not equal)<br><span style="font-family: 宋体">指令的汇编格式:</span>LOOPNZ/LOOPNE label<br><span style="font-family: 宋体">指令的基本功能:</span>① (CX)←(CX)-1<br><span style="font-family: 宋体"> </span> <span style="font-family: 宋体"> </span>② 若ZF=0且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束。<br><span style="font-family: 宋体">指令的特殊要求:循环指令都是短转移格式的指令,也就是说,位移量是用</span>8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。<br>四、<strong>子程序调用</strong><br>71、段内直接近调用 CALL SUBROUT<br><span style="font-family: 宋体">指令的基本功能:</span>(SP)<-(SP)-2<br>((SP)+1,(sp))<-(IP)<br>(IP)<-(IP)+16位位移量<br><span style="font-family: 宋体">段内间接近调用</span> CALL DESTIN<br><span style="font-family: 宋体">指令的基本功能:</span>(SP)<-(SP)-2<br>((SP)+1,(SP))<-(IP)<br>(IP)<-(EA)<br>72、段间直接调用 CALL FAR PTR SUBROUT<br><span style="font-family: 宋体">指令的基本功能:</span>(SP)<-(SP)-2,((SP))<-(CS)当前<br>(SP)<-(SP)-2,((SP))<-(IP)当前<br>(IP)<-偏移地址(在指令的第2、3个字节)<br>(CS)<-段地址(在指令的第4、5个字节)<br>五、<strong>返回指令</strong><br>73、段内返回(近返回) <strong>RET</strong><strong><br></strong><span style="font-family: 宋体">指令的基本功能:</span>(IP)<-((SP)+1,(SP))<br>(SP)<-(SP)+2<br><span style="font-family: 宋体">段间返回</span>(远返回) RET<br><span style="font-family: 宋体">指令的基本功能:</span>(IP)<-((SP)),(SP)<-(SP)+2<br>(CS)<-((SP)),(SP)<-(SP)+2<br><span style="font-family: 宋体">带立即数返回</span> RET N<br><span style="font-family: 宋体">执行操作:</span>① 返回地址出栈(操作同段内或段间返回)</p>
<p>② 修改堆栈指针:(SP) ← (SP)+N<br>六、<strong>中断及中断返回指令</strong><br>74、<strong>INT n 中断指令(interrupt),</strong>n为中断类型号<br><span style="font-family: 宋体"> 执行操作:</span>① 入栈保存FLAGS:(SP) ← (SP)-2,((SP)) ← (FLAGS)<br><span style="font-family: 宋体"> </span>② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)<br><span style="font-family: 宋体"> </span> (SP) ← (SP)-2,((SP)) ← (IP)<br><span style="font-family: 宋体"> </span>③ 转中断处理程序:(IP) ← (n×4)<br><span style="font-family: 宋体"> </span> (CS) ← (n×4+2)<br>75、<strong>IRET 中断返回指令</strong><span style="font-family: 宋体">(</span>return from interrupt)<br><span style="font-family: 宋体"> 执行操作:</span>① 返回地址出栈:(IP) ← ((SP)),(SP) ← (SP)+2<br><span style="font-family: 宋体"> </span> (CS) ← ((SP)),(SP) ← (SP)+2<br><span style="font-family: 宋体"> </span>② FLAGS出栈:(FLAGS) ← ((SP)),(SP) ← (SP)+2<br>76、<strong>INTO 溢出则中断(中断类型为4)</strong><br><span style="font-family: 宋体"> 执行操作:若</span>OF=1(有溢出),则:<br><span style="font-family: 宋体"> </span>① 入栈保存FLAGS:(SP) ← (SP)-2,((SP)) ← (FLAGS)<br><span style="font-family: 宋体"> </span>② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)<br><span style="font-family: 宋体"> </span> (SP) ← (SP)-2,((SP)) ← (IP)<br><span style="font-family: 宋体"> </span>③ 转中断处理程序:(IP) ← (4×4)= (10H)<br><span style="font-family: 宋体"> </span> (CS) ← (4×4+2)= (12H</p>
<p>HELLO,WORLD<span style="font-family: 宋体">进阶汇编程序系列</span></p>
<p> </p>
<p> Editor:admin Time:2004-3-21 12:49 Read:9785 Score:8 Print</p>
<p> Writer:LLUCT</p>
<p> Excerpt:80x86<span style="font-family: 宋体">汇编小站 </span></p>
<p> </p>
<p> Preface<span style="font-family: 宋体">:</span></p>
<p><span style="font-family: 宋体">感谢网友</span>lluct<span style="font-family: 宋体">为本站提供原创</span><span style="font-family: Arial">......</span><span style="font-family: 宋体">适合初学者学习哦 </span></p>
<p> </p>
<p> Content<span style="font-family: 宋体">:</span></p>
<p>TITLE ***HELLO,WORLD<span style="font-family: 宋体">进阶程序之选择分支 </span><span style="font-family: Arial">BY LLUCT*** </span></p>
<p> </p>
<p>DATA SEGMENT ;<span style="font-family: 宋体">定义数据段</span></p>
<p>MSG1 DB '***WELCOME TO MY PROGRAM BY LLUCT***','$'</p>
<p>;<span style="font-family: 宋体">定义输出的第一个字符串信息</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">字符串必须用</span><span style="font-family: Arial">DB</span><span style="font-family: 宋体">定义</span><span style="font-family: Arial">,$</span><span style="font-family: 宋体">为结束标志</span></p>
<p>MSG2 DB '1:BASIC MESSAGE 2:ADVANCED MESSAGE','$'</p>
<p>;<span style="font-family: 宋体">定义输出的字符串信息</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">选择菜单</span></p>
<p>MSG3 DB 'PLEASE CHOOSE:','$'</p>
<p>;<span style="font-family: 宋体">定义输出的字符串信息</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">选择前缀</span></p>
<p>MSG4 DB 'HELLO,WORLD!^-^','$'</p>
<p>;<span style="font-family: 宋体">定义输出的字符串信息</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">分支</span><span style="font-family: Arial">1</span><span style="font-family: 宋体">的信息</span></p>
<p>MSG5 DB 'THIS IS MY FIRST ASM_86 PROGRAM! @^-^@','$'</p>
<p>;<span style="font-family: 宋体">定义输出的字符串信息</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">分支</span><span style="font-family: Arial">2</span><span style="font-family: 宋体">的信息</span></p>
<p>ERRMSG DB 'CHOOSE ERROR! -_-b','$'</p>
<p>;<span style="font-family: 宋体">定义输出的字符串信息</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">选择错误信息</span></p>
<p>DATA ENDS ;<span style="font-family: 宋体">数据段结尾</span></p>
<p> </p>
<p>CODE SEGMENT ;<span style="font-family: 宋体">定义代码段</span></p>
<p> ASSUME CS:CODE ;<span style="font-family: 宋体">规定</span><span style="font-family: Arial">CS</span><span style="font-family: 宋体">的内容</span></p>
<p> ASSUME DS:DATA ;<span style="font-family: 宋体">规定</span><span style="font-family: Arial">DS</span><span style="font-family: 宋体">的内容</span></p>
<p> </p>
<p>START: MOV AX,DATA ;<span style="font-family: 宋体">程序从</span><span style="font-family: Arial">START</span><span style="font-family: 宋体">开始</span></p>
<p> MOV DS,AX ;DS<span style="font-family: 宋体">置初值</span><span style="font-family: Arial">,DATA</span><span style="font-family: 宋体">的段地址</span></p>
<p> </p>
<p> CALL ENTER ;<span style="font-family: 宋体">调用显示回车换行子程序</span></p>
<p> LEA DX,MSG1 ;<span style="font-family: 宋体">输出第一个字符串的偏移地址</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> CALL ENTER ;<span style="font-family: 宋体">调用显示回车换行子程序</span></p>
<p> CALL ENTER ;<span style="font-family: 宋体">这个</span><span style="font-family: Arial">...</span><span style="font-family: 宋体">同上啊</span><span style="font-family: Arial">^-^</span></p>
<p> </p>
<p> LEA DX,MSG2 ;<span style="font-family: 宋体">输出第二个字符串的偏移地址</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> </p>
<p>AGAIN: CALL ENTER ;<span style="font-family: 宋体">定义</span><span style="font-family: Arial">AGAIN</span><span style="font-family: 宋体">标号</span><span style="font-family: Arial">.</span><span style="font-family: 宋体">用于选择错误循环</span></p>
<p> </p>
<p> LEA DX,MSG3 ;<span style="font-family: 宋体">输出第三个字符串的偏移地址</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> </p>
<p> MOV AH,01H ;<span style="font-family: 宋体">调用</span><span style="font-family: Arial">1</span><span style="font-family: 宋体">号功能</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">从键盘输入一个字符并回显</span></p>
<p> INT 21H ;<span style="font-family: 宋体">完成输入回显</span></p>
<p> CMP AL,'1' ;<span style="font-family: 宋体">输入的字符和</span><span style="font-family: Arial">1</span><span style="font-family: 宋体">相比较</span></p>
<p> JE BASICP ;<span style="font-family: 宋体">如果相等</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">转移到</span><span style="font-family: Arial">BASICP</span><span style="font-family: 宋体">标号</span><span style="font-family: Arial">(JE=Jump if Equal)</span></p>
<p> CMP AL,'2' ;<span style="font-family: 宋体">输入的字符和</span><span style="font-family: Arial">2</span><span style="font-family: 宋体">相比较 </span><span style="font-family: Arial">||</span></p>
<p> JE ADVANP ;<span style="font-family: 宋体">如果相等</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">转移到</span><span style="font-family: Arial">ADVANP</span><span style="font-family: 宋体">标号</span><span style="font-family: Arial">(JE=</span><span style="font-family: 宋体">如果相等就转移</span><span style="font-family: Arial">)</span></p>
<p> JMP ERROR ;<span style="font-family: 宋体">否则就无条件转移到</span><span style="font-family: Arial">ERROR</span><span style="font-family: 宋体">标号</span></p>
<p> </p>
<p>EXIT: MOV AH,4CH ;4C<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">终止当前程序并返回调用程序</span></p>
<p> INT 21H ;<span style="font-family: 宋体">返回</span><span style="font-family: Arial">DOS</span></p>
<p> </p>
<p>BASICP: CALL ENTER ;<span style="font-family: 宋体">什么</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">还要解释啊</span><span style="font-family: Arial">.</span><span style="font-family: 宋体">晕</span><span style="font-family: Arial">-_-!!!</span></p>
<p> LEA DX,MSG4 ;<span style="font-family: 宋体">输出第三个字符串的偏移地址</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> CALL ENTER ;..........</p>
<p> JMP EXIT ;<span style="font-family: 宋体">无条件转移到</span><span style="font-family: Arial">EXIT</span><span style="font-family: 宋体">标号</span></p>
<p> </p>
<p>ADVANP: CALL ENTER ;55555555</p>
<p> LEA DX,MSG5 ;<span style="font-family: 宋体">解释了四次</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">应该懂了吧</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> CALL ENTER ;<span style="font-family: 宋体">再问就死给你看</span></p>
<p> JMP EXIT ;<span style="font-family: 宋体">无条件转移到</span><span style="font-family: Arial">EXIT</span><span style="font-family: 宋体">标号</span></p>
<p> </p>
<p>ERROR: CALL ENTER</p>
<p> LEA DX,ERRMSG ;<span style="font-family: 宋体">输出选择错误信息</span></p>
<p> CALL DISPCHS ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> MOV DL,07H ;<span style="font-family: 宋体">输出</span><span style="font-family: Arial">ASCII</span><span style="font-family: 宋体">码的报警</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">响铃</span><span style="font-family: Arial">)</span><span style="font-family: 宋体">控制符</span><span style="font-family: Arial">BEL(07H)</span></p>
<p> CALL DISPCH ;<span style="font-family: 宋体">调用显示单个字符子程序</span></p>
<p> CALL ENTER</p>
<p> JMP AGAIN</p>
<p> </p>
<p>DISPCH PROC NEAR </p>
<p>;<span style="font-family: 宋体">显示单个字符子程序</span><span style="font-family: Arial">,NEAR</span><span style="font-family: 宋体">说明子程序和主程序在同一个代码段中</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">现无主程序调用</span><span style="font-family: Arial">)</span></p>
<p> MOV AH,02H ;2<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">显示器输出字符</span></p>
<p> INT 21H ;<span style="font-family: 宋体">完成输出显示</span></p>
<p> RET ;<span style="font-family: 宋体">返回</span></p>
<p>DISPCH ENDP ;<span style="font-family: 宋体">子程序结尾</span></p>
<p> </p>
<p>ENTER PROC NEAR ;<span style="font-family: 宋体">显示回车换行子程序</span></p>
<p> MOV DL,0DH ;<span style="font-family: 宋体">输出</span><span style="font-family: Arial">ASCII</span><span style="font-family: 宋体">码的回车控制符</span><span style="font-family: Arial">CR(0DH)</span></p>
<p> CALL DISPCH ;<span style="font-family: 宋体">调用显示单个字符子程序</span></p>
<p> MOV DL,0AH ;<span style="font-family: 宋体">输出</span><span style="font-family: Arial">ASCII</span><span style="font-family: 宋体">码的换行控制符</span><span style="font-family: Arial">LF(0AH)</span></p>
<p> CALL DISPCH ;<span style="font-family: 宋体">调用显示单个字符子程序</span></p>
<p> RET ;<span style="font-family: 宋体">返回</span></p>
<p>ENTER ENDP ;<span style="font-family: 宋体">子程序结尾</span></p>
<p> </p>
<p>DISPCHS PROC NEAR</p>
<p>;<span style="font-family: 宋体">显示字符串子程序</span><span style="font-family: Arial">,NEAR</span><span style="font-family: 宋体">说明子程序和主程序在同一个代码段中</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">现无主程序调用</span><span style="font-family: Arial">)</span></p>
<p> MOV AH,09H ;9<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">显示字符串</span></p>
<p> INT 21H ;<span style="font-family: 宋体">完成输出显示</span></p>
<p> RET</p>
<p>DISPCHS ENDP</p>
<p> </p>
<p>CODE ENDS ;<span style="font-family: 宋体">代码段结尾</span></p>
<p> END START ;<span style="font-family: 宋体">结束汇编</span></p>
<p> </p>
<p>;<span style="font-family: 宋体">把以上代码复制到记事本等文本程序中</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">并保存</span><span style="font-family: Arial">.(</span><span style="font-family: 宋体">如</span><span style="font-family: Arial">helloch.asm)</span></p>
<p>;<span style="font-family: 宋体">编译</span><span style="font-family: Arial">:masm helloch.asm</span></p>
<p>;<span style="font-family: 宋体">连接</span><span style="font-family: Arial">:link helloch.obj</span></p>
<p>;<span style="font-family: 宋体">执行</span><span style="font-family: Arial">:helloch.exe</span></p>
<p> </p>
<p>======================================================</p>
<p> </p>
<p>title ***hello,world<span style="font-family: 宋体">进阶之字符串输入输出 </span><span style="font-family: Arial">by lluct*** </span></p>
<p> </p>
<p> </p>
<p>data segment ;<span style="font-family: 宋体">定义数据段</span></p>
<p>input db 100 dup(?)</p>
<p>;<span style="font-family: 宋体">定义输入的字符串</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">字符串必须用</span><span style="font-family: Arial">db</span><span style="font-family: 宋体">定义</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">长度为</span><span style="font-family: Arial">100</span><span style="font-family: 宋体">个字节</span></p>
<p>msg1 db 'Hello,','$'</p>
<p>;<span style="font-family: 宋体">定义输出的前缀字符串信息</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">字符串必须用</span><span style="font-family: Arial">db</span><span style="font-family: 宋体">定义</span><span style="font-family: Arial">,$</span><span style="font-family: 宋体">为结束标志</span><span style="font-family: Arial">(24h)</span></p>
<p>msg2 db ',Welcome to here!','$'</p>
<p>;<span style="font-family: 宋体">定义输出的后缀字符串信息</span></p>
<p>headmsg db 'PLEASE INPUT YOUR NAME:','$'</p>
<p>;<span style="font-family: 宋体">开始显示的字符串信息</span></p>
<p>data ends ;<span style="font-family: 宋体">数据段结尾</span></p>
<p> </p>
<p>code segment ;<span style="font-family: 宋体">定义代码段</span></p>
<p> assume cs:code ;<span style="font-family: 宋体">规定</span><span style="font-family: Arial">cs</span><span style="font-family: 宋体">的内容</span></p>
<p> assume ds:data ;<span style="font-family: 宋体">规定</span><span style="font-family: Arial">ds</span><span style="font-family: 宋体">的内容</span></p>
<p> </p>
<p>start: mov ax,data ;<span style="font-family: 宋体">程序从</span><span style="font-family: Arial">start</span><span style="font-family: 宋体">开始</span></p>
<p> mov ds,ax ;ds<span style="font-family: 宋体">置初值</span><span style="font-family: Arial">,data</span><span style="font-family: 宋体">的段地址</span></p>
<p> mov si,0 ;<span style="font-family: 宋体">变址寄存器置初值</span><span style="font-family: Arial">0</span></p>
<p> </p>
<p> call enter ;<span style="font-family: 宋体">调用显示回车换行子程序</span></p>
<p> lea dx,headmsg ;<span style="font-family: 宋体">输出开始显示的字符串的偏移地址</span></p>
<p> call dispchs ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p>repeat: mov ah,01h </p>
<p>;<span style="font-family: 宋体">定义</span><span style="font-family: Arial">repeat</span><span style="font-family: 宋体">标号</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">用于循环输入单个字符</span><span style="font-family: Arial">.</span><span style="font-family: 宋体">调用</span><span style="font-family: Arial">1</span><span style="font-family: 宋体">号功能</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">从键盘输入一个字符并回显</span></p>
<p> int 21h ;<span style="font-family: 宋体">完成输入回显</span></p>
<p> cmp al,0dh ;<span style="font-family: 宋体">输入的字符和</span><span style="font-family: Arial">CR(</span><span style="font-family: 宋体">回车</span><span style="font-family: Arial">)</span><span style="font-family: 宋体">比较</span></p>
<p> je exit ;<span style="font-family: 宋体">如果等于回车就转移到</span><span style="font-family: Arial">exit</span></p>
<p> mov input,al ;<span style="font-family: 宋体">把</span><span style="font-family: Arial">al</span><span style="font-family: 宋体">的值传送到</span><span style="font-family: Arial">input</span><span style="font-family: 宋体">的</span><span style="font-family: Arial">si</span><span style="font-family: 宋体">地址中</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">好像是这样吧</span><span style="font-family: Arial">)</span></p>
<p> inc si ;si<span style="font-family: 宋体">加</span><span style="font-family: Arial">1</span></p>
<p> jmp repeat ;<span style="font-family: 宋体">无条件转移到</span><span style="font-family: Arial">repeat</span></p>
<p> </p>
<p>exit: call enter</p>
<p> mov input,24h ;<span style="font-family: 宋体">给输入完成的字符串加上结束标志</span><span style="font-family: Arial">($)</span></p>
<p> call enter </p>
<p> lea dx,msg1 ;<span style="font-family: 宋体">输出前缀字符串的偏移地址</span></p>
<p> call dispchs ;<span style="font-family: 宋体">调用显示字符串子程序</span></p>
<p> lea dx,input ;<span style="font-family: 宋体">输出刚才输入的字符串</span></p>
<p> call dispchs </p>
<p> lea dx,msg2</p>
<p> call dispchs</p>
<p> call enter</p>
<p> </p>
<p> </p>
<p> mov ah,4ch ;4c<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">终止当前程序并返回调用程序</span></p>
<p> int 21h ;<span style="font-family: 宋体">返回</span><span style="font-family: Arial">dos</span></p>
<p> </p>
<p>enter proc near ;<span style="font-family: 宋体">显示回车换行子程序</span></p>
<p> mov dl,0dh ;<span style="font-family: 宋体">输出</span><span style="font-family: Arial">ascii</span><span style="font-family: 宋体">码的回车控制符</span><span style="font-family: Arial">cr(0dh)</span></p>
<p> call dispch </p>
<p> mov dl,0ah ;<span style="font-family: 宋体">输出</span><span style="font-family: Arial">ascii</span><span style="font-family: 宋体">码的换行控制符</span><span style="font-family: Arial">lf(0ah)</span></p>
<p> call dispch</p>
<p> ret ;<span style="font-family: 宋体">返回</span></p>
<p>enter endp ;<span style="font-family: 宋体">子程序结束</span></p>
<p> </p>
<p>dispch proc near</p>
<p> mov ah,02h ;2<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">显示器输出字符</span></p>
<p> int 21h ;<span style="font-family: 宋体">完成输出显示</span></p>
<p> ret ;<span style="font-family: 宋体">返回</span></p>
<p>dispch endp</p>
<p> </p>
<p>dispchs proc near</p>
<p> mov ah,09h ;9<span style="font-family: 宋体">号功能调用</span><span style="font-family: Arial">:</span><span style="font-family: 宋体">显示字符串</span></p>
<p> int 21h ;<span style="font-family: 宋体">完成输出显示</span></p>
<p> ret ;<span style="font-family: 宋体">返回</span></p>
<p>dispchs endp</p>
<p> </p>
<p>code ends ;<span style="font-family: 宋体">代码段结尾</span></p>
<p> end start ;<span style="font-family: 宋体">结束汇编</span></p>
<p> </p>
<p>;<span style="font-family: 宋体">把以上代码复制到记事本等文本程序中</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">并保存</span><span style="font-family: Arial">.(</span><span style="font-family: 宋体">如</span><span style="font-family: Arial">heinout.c)</span></p>
<p>;<span style="font-family: 宋体">编译</span><span style="font-family: Arial">:masm heinout.asm</span></p>
<p>;<span style="font-family: 宋体">连接</span><span style="font-family: Arial">:link heinout.obj</span></p>
<p>;执行:heinout.exe</p>
<p> </p>
<p><span style="font-family: 宋体">中断是指</span>CPU<span style="font-family: 宋体">对系统发生的某个事件作出的一种反应:</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">暂停正在执行的程序,保留现场后自动转去执行相应的处理程序,处理完该事件后再返回断点继续执行被</span><span style="font-family: Arial">"</span><span style="font-family: 宋体">打断</span><span style="font-family: Arial">"</span><span style="font-family: 宋体">的程序</span></p>
<p><span style="font-family: 宋体">在我们所用的电脑中,所有的硬件都需要执行中断请求的动作,简单说它的作用就是用来停止其相关硬件的工作状态。我们可以举一个日常生活中的例子来说明,假如你正在给朋友写信,电话铃响了,这时你放下手中的笔去接电话,通话完毕再继续写信。这个例子就表现了中断及其处理的过程:电话铃声使你暂时中止当前的工作,而去处理更为急需处理的事情</span>——<span style="font-family: 宋体">接电话,当把急需处理的事情处理完毕之后,再回过头来继续原来的事情。在这个例子中,电话铃声就可以称为</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">中断请求</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">,而你暂停写信去接电话就叫作</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">中断响应</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">,那么接电话的过程就是</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">中断处理</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">。由此我们可以看出,在计算机执行程序的过程中,由于出现某个特殊情况</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">或称为</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">事件</span><span style="font-family: Arial">”)</span><span style="font-family: 宋体">,使得系统暂时中止现行程序,而转去执行处理这一特殊事件的程序,处理完毕之后再回到原来程序的中断点继续向下执行,而这个过程就被称为中断。 </span></p>
<p> </p>
<p><span style="font-family: 宋体">中断的作用</span></p>
<p> </p>
<p><span style="font-family: 宋体">我们可以再举一个例子来说明中断的作用。假设有一个朋友来拜访你,但是由于不知何时到达,你只能在门口等待,于是什么事情也干不了;但如果在门口装一个门铃,你就不必在门口等待而可以在家里去做其他的工作,朋友来了按门铃通知你,这时你才中断手中的工作去开门,这就避免了不必要的等待。而计算机也一样,例如打印文稿的操作。因为</span>cpu<span style="font-family: 宋体">传送数据的速度高,而打印机速度较慢,如果不采用中断技术,</span><span style="font-family: Arial">cpu</span><span style="font-family: 宋体">将经常处于等待状态,这会使得电脑的工作效率极低。而采用了中断方式后,</span><span style="font-family: Arial">cpu</span><span style="font-family: 宋体">就可以在打印的同时进行其他的工作,而只在打印机缓冲区内的当前内容打印完毕,而发出中断请求之后才予以响应,这时才暂时中断当前的工作转去执行停止打印的操作,之后再返回执行原来的程序。这样就大大地提高了计算机系统的效率。 </span></p>
<p> </p>
<p>irq<span style="font-family: 宋体">中断 </span></p>
<p> </p>
<p><span style="font-family: 宋体">计算机中的中断有好几种,根据中断信号产生的来源可以分为:硬件中断和软件中断。硬件中断多由外围设备和计算机系统控制器发出,软件中断一般由软件命令产生。在硬件中断中又有</span>“<span style="font-family: 宋体">可屏蔽中断</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">不可屏蔽中断</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">之分。顾名思义,可屏蔽中断可以由计算机根据系统的需要来决定是否进行接收处理或是延后处理</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">即屏蔽</span><span style="font-family: Arial">)</span><span style="font-family: 宋体">,而不可屏蔽中断便是直接激活相应的中断处理程序,它不能也不会被延误。而</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">中断就是可屏蔽的硬件中断,它的全称为</span><span style="font-family: Arial">interrupt request </span><span style="font-family: 宋体">即</span><span style="font-family: Arial">“</span><span style="font-family: 宋体">中断请求</span><span style="font-family: Arial">”</span><span style="font-family: 宋体">。 </span></p>
<p> </p>
<p><span style="font-family: 宋体">在电脑的系统中,是由一个中断控制器</span>8259<span style="font-family: 宋体">或是</span><span style="font-family: Arial">8259a</span><span style="font-family: 宋体">的芯片</span><span style="font-family: Arial">(</span><span style="font-family: 宋体">现在此芯片大都集成到其他的芯片内</span><span style="font-family: Arial">)</span><span style="font-family: 宋体">来对系统中每个硬件的中断进行控制。目前共有</span><span style="font-family: Arial">16</span><span style="font-family: 宋体">组</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">,去掉其中用来作桥接的一组</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">,实际上只有</span><span style="font-family: Arial">15</span><span style="font-family: 宋体">组</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">可供硬件调用。而这些</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">都有自己建议的配置。 </span></p>
<p> </p>
<p><span style="font-family: 宋体">分配</span>irq<span style="font-family: 宋体">中断 </span></p>
<p> </p>
<p><span style="font-family: 宋体">我们日常所用的操作系统对于</span>irq<span style="font-family: 宋体">的设置也不尽相同,所以在安装新硬件的时候,系统往往并不能自动检测正确的</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">来分配给所需调用的硬件,这就会造成此硬件设备或是原来的旧硬件出现不能正常工作的现象。其实这是系统自动将该硬件的</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">分配给了其他与此</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">相同的硬件上,从而发生冲突使硬件不能正常工作。一般如果遇到这种情况,只要将新旧两个硬件的</span><span style="font-family: Arial">irq</span><span style="font-family: 宋体">配置手动调开就可以解决了。 </span></p>
<p> </p>
<p><span style="font-family: 宋体">对于一些常用的硬件一般都有其默认的</span>irq数值。比如声卡常常使用irq5或7。虽然这些配件使用其他的irq值大多数也能工作,但假如碰到特别“挑剔”的软件或游戏等程序,例如只能识别irq值为5或7的声卡,那么如果将它设成irq9就白费心机了。</p>
<p><strong>8.3.1 <span style="font-family: 宋体">中断的基本概念</span></strong><strong><br></strong><strong> <span style="font-family: 宋体">中断</span><span style="font-family: "Times New Roman"">(Interrupt)</span></strong><span style="font-family: 宋体">是指计算机在实行期间,系统内发生非寻常的或非预期的急需处理事件,使得</span>CPU<span style="font-family: 宋体">暂时中断当前正在执行的程序而转去执行响应的事件处理程序。待处理完毕后又返回原来中断处继续执行或调度新的程序执行的过程。</span><br><br> <span style="font-family: 宋体">现代计算机系统一般都具有处理突发事件的能力。例如:从磁带上读入一组信息,当发现读入信息有错误时,只要让磁带退回重读该组信息就可能克服错误,而得到正确的信息。</span><br><br> <span style="font-family: 宋体">这种处理突发事件的能力是由硬件和软件协作完成的。首先由硬件的中断装置发现产生的事件,然后,中断装置中止现行程序的执行,引出处理该事件的程序来处理。计算机系统不仅可以处理由于硬件或软件错误而产生的事件,而且可以处理某种预定处理伪事件。例如:外围设备工作结束时,也发出中断请求,向系统报告它已完成任务,系统根据具体情况作出相应处理。引起中断的事件称为中断源。发现中断源并产生中断的硬件称中断装置。在不同的硬件结构中,通常有不同的中断源和平不同的中断装置,但它们有一个共性,即:当中断事件发生后,中断装置能改变处理器内操作执行的顺序。</span><strong><br></strong><strong><br></strong><strong> </strong>中断源:引起中断发生的事件被称为中断源。<br> <span style="font-family: 宋体">中断请求:</span><span style="font-family: 宋体">中断源向</span>CPU<span style="font-family: 宋体">发出的请求中断处理信号。</span><br> 中断响应:CPU<span style="font-family: 宋体">收到中断请求后转相应的事件处理程序。</span><br> <span style="font-family: 宋体">禁止中断(关中断):</span>CPU<span style="font-family: 宋体">内部的处理机状态字</span><span style="font-family: "Times New Roman"">PSW</span><span style="font-family: 宋体">的中断允许位已被清除,不允许</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">响应中断。</span><br> 开中断:PSW<span style="font-family: 宋体">的中断允许位的设置。</span><br> 中断屏蔽:在中断请求产生之后,系统用软件方式有选择地封锁部分中断而允许蓁部分的中断仍能得到响应。</p>
<p><strong>8.3.4 <span style="font-family: 宋体">中断处理过程</span></strong><strong><br></strong><strong><br></strong><strong> </strong>中断处理过程:<br> <span style="font-family: 宋体"> </span>(1) CPU<span style="font-family: 宋体">检查响应中断的条件是否满足。</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">响应中断的条件是:有来自于中断源的中断请求、</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">允许中断。如果中断响应条件不满足,则中断处理无法进行。</span><br> <span style="font-family: 宋体"> </span>(2) <span style="font-family: 宋体">如果</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">响应中断,则</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">关中断,使其进入不可再次响应中断的状态。</span><br> <span style="font-family: 宋体"> </span>(3) <span style="font-family: 宋体">保存被中断进程现场。为了在中断处理结束后能使进程正确地返回到中断点,系统必须保存当前处理机状态字</span><span style="font-family: "Times New Roman"">PSW</span><span style="font-family: 宋体">和程序计数器</span><span style="font-family: "Times New Roman"">PC</span><span style="font-family: 宋体">等的值。这些值一般保存在特定堆栈或硬件寄存器中。</span><br> <span style="font-family: 宋体"> </span>(4) <span style="font-family: 宋体">分析中断原因,调用中断处理子程序。在多个中断请求同时发生时,处理优先级最高的中断源发出的中断请求。</span><br> <span style="font-family: 宋体"> </span>(5) <span style="font-family: 宋体">执行中断处理子程序。对陷阱来说,在有些系统中则是通过陷阱指令向当前执行进程发软中断信号后调用对应的处理子程序执行。</span><br> <span style="font-family: 宋体"> </span>(6) <span style="font-family: 宋体">退出中断,恢复被中断进程的现场或调度新进程占据处理机。</span><br> <strong><span style="font-family: 宋体"> </span>(</strong>7) <span style="font-family: 宋体">开中断,</span><span style="font-family: "Times New Roman"">CPU</span><span style="font-family: 宋体">继续执行。</span></p>
<p align="center">1<span style="font-family: 宋体">.什么叫中断?</span><br><span style="font-family: 宋体"> 简单来说,中断是一种使</span>CPU<span style="font-family: 宋体">中止正在执行的程序而转去处理特殊事件的操作。这些引起中断的事件称为中断源,它们可能是来自外设的输入输出请求,也可能是计算机的一些异常事故或其它内部原因。</span><br><span style="font-family: 宋体"> 更具体地,我们定义</span>CPU<span style="font-family: 宋体">中断为这样一个过程:在特定的事件(中断源,也称中断请求信号)触发下引起</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">暂停正在运行的程序(主程序),转而先去处理一段为特定事件而编写的处理程序(中断处理程序),等中断处理程序处理完成后,再回到主程序被打断的地方继续运行。</span></p>
<p align="center">2<span style="font-family: 宋体">.中断的作用</span><br><span style="font-family: 宋体"> 一方面,有了中断功能,</span>PC<span style="font-family: 宋体">系统就可以使</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">和外设同时工作,使系统可以及时地响应外部事件。而且有了中断功能,</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">可允许多个外设同时工作。这样就大大提高了</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">的利用率,也提高了数据输入、输出的速度。</span><br><span style="font-family: 宋体"> 另一方面,有了中断功能,就可以使</span>CPU<span style="font-family: 宋体">及时处理各种软硬件故障。计算机在运行过程中,往往会出现事先预料不到的情况或出现一些故障,如电源掉电、存储出错,运算溢出等等。计算机可以利用中断系统自行处理,而不必停机或报告工作人员。</span></p>
<p align="center">3<span style="font-family: 宋体">.中断类型</span><br><span style="font-family: 宋体"> 在</span>PC<span style="font-family: 宋体">机系统中,根据中断源的不同,中断常分为两大类:硬件中断和软件中断。</span><br><span style="font-family: 宋体"> 硬件中断也称为外部中断,它又可以分为两种:</span><br><span style="font-family: 宋体"> </span>1<span style="font-family: 宋体">).</span><span style="font-family: 宋体">可屏蔽中断:是可以被</span>CPU<span style="font-family: 宋体">屏蔽的由中断电路发出的中断请求信号在</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">的</span><span style="font-family: ˎ̥">INTR</span><span style="font-family: 宋体">端引起的中断,它常常由</span><span style="font-family: ˎ̥">PC</span><span style="font-family: 宋体">机的外设或一些接口功能产生,如键盘、打印机、串行口等。可屏蔽意味着这类型中断可以在</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">要处理其它紧急操作时,被软件屏蔽或忽略。 </span><br><span style="font-family: 宋体"> </span>2<span style="font-family: 宋体">).</span><span style="font-family: 宋体">非屏蔽中断:是由</span>CPU<span style="font-family: 宋体">的</span><span style="font-family: ˎ̥">NMI</span><span style="font-family: 宋体">端引起的中断,如当系统出现掉电、内存奇偶校验错误等,系统都将使用非屏蔽中断。非屏蔽是指</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">不能用软件指令来禁止对这种中断响应,也就是</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">必须响应由</span><span style="font-family: ˎ̥">NMI</span><span style="font-family: 宋体">端送来的中断信号。 </span><br><span style="font-family: 宋体"> 软件中断,又称为内部中断,是指程序中使用</span>INT<span style="font-family: 宋体">中断指令引起的中断。</span></p>
<p align="center">4<span style="font-family: 宋体">.</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">响应中断的条件</span> <br><span style="font-family: 宋体"> 除了非屏蔽中断外,其它中断都可以用软件来屏蔽或开放。系统只有具备如下的中断条件,</span>CPU<span style="font-family: 宋体">才可能对中断请求进行响应。</span><br><span style="font-family: 宋体"> </span>1) <span style="font-family: 宋体">设置中断请求触发器</span><br><span style="font-family: 宋体"> </span>2) <span style="font-family: 宋体">设置中断屏蔽触发器</span><br><span style="font-family: 宋体"> </span>3) <span style="font-family: 宋体">设置中断允许触发器</span></p>
<p align="center">5<span style="font-family: 宋体">.</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">处理中断过程</span> <br><span style="font-family: 宋体"> 当满足了中断的条件后,</span>CPU<span style="font-family: 宋体">就会响应中断,转入中断程序处理。具体的工作过程如下所述。</span><br><span style="font-family: 宋体"> </span>1) <span style="font-family: 宋体">关中断</span><br><span style="font-family: 宋体"> </span>2) <span style="font-family: 宋体">保留断点</span><br><span style="font-family: 宋体"> </span>3) <span style="font-family: 宋体">保护现场</span><br><span style="font-family: 宋体"> </span>4) <span style="font-family: 宋体">给出中断入口,转入相应的中断服务程序</span><br><span style="font-family: 宋体"> </span>5) <span style="font-family: 宋体">恢复现场</span><br><span style="font-family: 宋体"> </span>6) <span style="font-family: 宋体">开中断与返回</span></p>
<p align="center">6<span style="font-family: 宋体">.中断冲突</span> <br><span style="font-family: 宋体"> 虽然现在</span>Windows<span style="font-family: 宋体">操作系统从</span><span style="font-family: ˎ̥">Win9X</span><span style="font-family: 宋体">开始已经支持即插即用功能,大大简化了用户的操作,但是如果不能认出要安装的新设备,那么自动分配中断时就会产生冲突。现在新的硬件产品层出不穷,各种产品又相互兼容,功能类似,这就导致了操作系统常常不能正确检测出新设备,中断冲突也就不可避免了。</span></p>
<p align="center">7<span style="font-family: 宋体">.中断控制器</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">的结构</span><br><span style="font-family: 宋体"> </span>Intel 8259A<span style="font-family: 宋体">是与</span><span style="font-family: ˎ̥">8088/8086</span><span style="font-family: 宋体">系列兼容的可编程的中断控制器。后来的微机系统也沿用这种中断机制及其功能,只是因为集成芯片技术的提高,不单独以</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">芯片的形式出现,而是集成到一个叫做</span><span style="font-family: ˎ̥">"</span><span style="font-family: 宋体">南桥芯片</span><span style="font-family: ˎ̥">"</span><span style="font-family: 宋体">或</span><span style="font-family: ˎ̥">"HUB</span><span style="font-family: 宋体">芯片</span><span style="font-family: ˎ̥">"</span><span style="font-family: 宋体">的芯片里了。</span><br><span style="font-family: 宋体"> </span>8259A<span style="font-family: 宋体">包括以下几个部分:</span><br><span style="font-family: 宋体"> </span>1<span style="font-family: 宋体">).</span><span style="font-family: 宋体">中断请求寄存器</span>IRR<span style="font-family: 宋体">(</span><span style="font-family: ˎ̥">Interrupt Request Register</span><span style="font-family: 宋体">):有</span><span style="font-family: ˎ̥">8</span><span style="font-family: 宋体">条外界中断请求线</span><span style="font-family: ˎ̥">IR0</span><span style="font-family: 宋体">~</span><span style="font-family: ˎ̥">IR7</span><span style="font-family: 宋体">,每一条请求线有一个相应的触发器来保存请求信号。</span><br><span style="font-family: 宋体"> </span>2<span style="font-family: 宋体">).</span><span style="font-family: 宋体">中断服务寄存器</span>ISR<span style="font-family: 宋体">(</span><span style="font-family: ˎ̥">IN Service Register</span><span style="font-family: 宋体">):保存正在服务的中断。</span><br><span style="font-family: 宋体"> </span>3<span style="font-family: 宋体">).</span><span style="font-family: 宋体">优先权电路:对保存在</span>IRR<span style="font-family: 宋体">中的各个中断请求,经过判断确定最高的优先权,并在中断响应周期把它选通至中断服务寄存器。</span><br><span style="font-family: 宋体"> </span>4<span style="font-family: 宋体">).</span><span style="font-family: 宋体">中断屏蔽寄存器</span>IMR<span style="font-family: 宋体">(</span><span style="font-family: ˎ̥">Interrupt Mask Register</span><span style="font-family: 宋体">):寄存器的每一位,可以对</span><span style="font-family: ˎ̥">IRR</span><span style="font-family: 宋体">中的相应的中断源进行屏蔽。但对于较高优先权的输入线实现屏蔽并不影响较低优先权的输入。</span><br><span style="font-family: 宋体"> </span>5<span style="font-family: 宋体">).</span><span style="font-family: 宋体">数据总线缓冲器:是</span>8259A<span style="font-family: 宋体">与系统数据总线的接口,它是</span><span style="font-family: ˎ̥">8</span><span style="font-family: 宋体">位的双向三态缓冲器。凡是</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">对</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">编程时的控制字,都是通过它写入</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">的,</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">状态信息,也是通过它读入</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">的;在中断响应周期,</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">送至数据总线的</span><span style="font-family: ˎ̥">CALL</span><span style="font-family: 宋体">指令或中断向量也是通过它传送的。</span><br><span style="font-family: 宋体"> </span>6<span style="font-family: 宋体">).</span><span style="font-family: 宋体">读</span>/<span style="font-family: 宋体">写控制逻辑:</span><span style="font-family: ˎ̥">CPU</span><span style="font-family: 宋体">能通过它实现对</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">的读出(状态信号)和写入(初始化编程)。</span><br><span style="font-family: 宋体"> </span>7<span style="font-family: 宋体">).</span><span style="font-family: 宋体">级连缓冲器:实现</span>8259A<span style="font-family: 宋体">芯片之间的级连,使得中断源可由</span><span style="font-family: ˎ̥">8</span><span style="font-family: 宋体">级扩展至</span><span style="font-family: ˎ̥">64</span><span style="font-family: 宋体">级。</span><br><span style="font-family: 宋体"> </span>8<span style="font-family: 宋体">).</span><span style="font-family: 宋体">控制逻辑部分:对芯片内部的工作进行控制,使它按编程的规定工作。</span></p>
<p align="center">8<span style="font-family: 宋体">.</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">的级连</span><br><span style="font-family: 宋体"> 在一个系统中,</span>8259A<span style="font-family: 宋体">可以级连,有一个主</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">,若干个从</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">,最多可以有</span><span style="font-family: ˎ̥">8</span><span style="font-family: 宋体">个从</span><span style="font-family: ˎ̥">8259A</span><span style="font-family: 宋体">,把中断源扩展到</span><span style="font-family: ˎ̥">64</span><span style="font-family: 宋体">个。</span></p>
<p> </p>
<p> </p>
<p class="pre"><span style="font-family: 宋体">非</span> <span style="font-family: 宋体">法</span> <span style="font-family: 宋体">传</span> <span style="font-family: 宋体">送</span> <span style="font-family: 宋体">种</span> <span style="font-family: 宋体">种</span></p>
<p class="pre">1<span style="font-family: 宋体">.两个操作数的类型不一致 </span><span style="font-family: Arial">–-----</span><span style="font-family: 宋体">例如源操作数是字节,而目的操作数是字;或相反</span></p>
<p class="pre">• <span style="font-family: 宋体">绝大多数双操作数指令,除非特别说明,目的操作数与源操作数必须类型一致,否则为非法指令 </span><span style="font-family: Arial">MOV AL , 050AH</span><span style="font-family: 宋体">;非法指令:</span><span style="font-family: Arial">050Ah</span><span style="font-family: 宋体">为字,而</span><span style="font-family: Arial">AL</span><span style="font-family: 宋体">为字节</span></p>
<p class="pre">• <span style="font-family: 宋体">寄存器有明确的字节或字类型,有寄存器参与的指令其操作数类型就是寄存器的类型</span></p>
<p class="pre">• <span style="font-family: 宋体">对于存储器单元与立即数同时作为操作数的情况,必须显式指明;</span></p>
<p class="pre">byte ptr <span style="font-family: 宋体">指示字节类型 , </span><span style="font-family: Arial">word ptr </span><span style="font-family: 宋体">指示字类型。</span></p>
<p class="pre">2<span style="font-family: 宋体">.两个操作数不能都是存储器 </span><span style="font-family: Arial">–------</span><span style="font-family: 宋体">传送指令很灵活,但主存之间的直接传送却不允许</span></p>
<p class="pre">• 8086<span style="font-family: 宋体">指令系统不允许两个操作数都是存储单元(除串操作指令),要实现这种传送,可通过寄存器间接实现</span></p>
<p class="pre">mov ax , buffer1<span style="font-family: 宋体">;</span><span style="font-family: Arial">ax←buffer1</span><span style="font-family: 宋体">(将</span><span style="font-family: Arial">buffer1</span><span style="font-family: 宋体">内容送</span><span style="font-family: Arial">ax</span><span style="font-family: 宋体">)</span></p>
<p class="pre">mov buffer2 , ax<span style="font-family: 宋体">;</span><span style="font-family: Arial">buffer2←ax</span><span style="font-family: 宋体">;这里</span><span style="font-family: Arial">buffer1</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">buffer2</span><span style="font-family: 宋体">是两个字变量、;实际表示直接寻址方式</span></p>
<p class="pre">3<span style="font-family: 宋体">.段寄存器的操作有一些限制 </span><span style="font-family: Arial">–----</span><span style="font-family: 宋体">段寄存器属专用寄存器,对他们的操作能力有限</span></p>
<p class="pre">• <span style="font-family: 宋体">不允许立即数传送给段寄存器 </span><span style="font-family: Arial">MOV DS,100H</span><span style="font-family: 宋体">;非法指令:立即数不能传送段寄存器</span></p>
<p class="pre">• <span style="font-family: 宋体">不允许直接改变</span><span style="font-family: Arial">CS</span><span style="font-family: 宋体">值 </span><span style="font-family: Arial">MOV CS, </span><span style="font-family: 宋体">;不允许使用的指令</span></p>
<p class="pre">• <span style="font-family: 宋体">不允许段寄存器之间的直接数据传送 </span><span style="font-family: Arial">MOV DS,ES</span><span style="font-family: 宋体">;非法指令:不允许段寄存器间传送 </span></p>
<p class="pre">MOV BL,AX<span style="font-family: 宋体">(数据长度不匹配)</span></p>
<p class="pre">MOV DS,2000H(<span style="font-family: 宋体">不允许给段存储器用立即数赋值</span><span style="font-family: Arial">)</span></p>
<p class="pre">MOV CS,AX(<span style="font-family: 宋体">禁止用</span><span style="font-family: Arial">MOV</span><span style="font-family: 宋体">指令给</span><span style="font-family: Arial">CS</span><span style="font-family: 宋体">赋值</span><span style="font-family: Arial">)</span></p>
<p class="pre">MOV ,(<span style="font-family: 宋体">禁止直接在存储器间传送</span><span style="font-family: Arial">)</span></p>
<p class="pre">MOV ,20H(<span style="font-family: 宋体">数据长度不确切</span><span style="font-family: Arial">,</span><span style="font-family: 宋体">应改为</span></p>
<p class="pre">MOV BYTE PTR ,20H)</p>
<p> </p>
<p>1、(1)状态标志:CF-进位标志,ZF-零标志,SF-符号标志,PF-奇偶标志</p>
<p> OF-溢出标志,AF-辅助进位标志。</p>
<p> (2)控制标志:DF-方向标志,IF-中断允许标志,TF-陷井标志。</p>
<p>2、8086机器代码格式一般是:</p>
<p>操作码 寻址方式 偏移量 立即数。</p>
<p>3、(1)源操作数为立即寻址,目的操作数为寄存器寻址。</p>
<p> (2)源操作数为寄存器相对寻址,目的操作数为寄存器寻址。</p>
<p> (3)源操作数为寄存器寻址,目的操作数为寄存器间接寻址。</p>
<p> (4)源操作数和目的操作数均为固定寻址。</p>
<p>4、此题要求出物理地址,物理地址的计算公式为:</p>
<p>段地址(段首地址)*10H+偏移地址(有效地址)</p>
<p>(1)源操作数为立即寻址方式,操作数地址就在本条指令中。</p>
<p>(2)源操作数为直接寻址方式,其物理地址为</p>
<p> DS*10H+100H=20100H</p>
<p>(3)源操作数为寄存器间接寻址,其物理地址为</p>
<p> SS*10H+BP=15010H</p>
<p>(4)源操作数为基址变址寻址,其物理地址为</p>
<p> DS*10H+BX+SI+VAL=201E0H</p>
<p> </p>
<p> </p>
<p>8086 有14个16位寄存器,这14个寄存器按其用途可分为(1)通用寄存器、(2)指令指针、(3)标志寄存器和(4)段寄存器等4类。<br> (1)通用寄存器有8个, 又可以分成2组,一组是数据寄存器(4个),另一组是指针寄存器及变址寄存器(4个).<br> 数据寄存器分为:<br> AH&AL=AX(accumulator):累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据.<br> BH&BL=BX(base):基址寄存器,常用于地址索引;<br> CH&CL=CX(count):计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器.<br> DH&DL=DX(data):数据寄存器,常用于数据传递。<br> 他们的特点是,这4个16位的寄存器可以分为高8位: AH, BH, CH, DH.以及低八位:AL,BL,CL,DL。这2组8位寄存器可以分别寻址,并单独使用。<br> 另一组是指针寄存器和变址寄存器,包括:<br> SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置;<br> BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置;<br> SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针;<br> DI(Destination Index):目的变址寄存器,可用来存放相对于 ES 段之目的变址指针。<br> 这4个16位寄存器只能按16位进行存取操作,主要用来形成操作数的地址,用于堆栈操作和变址运算中计算操作数的有效地址。<br> (2) 指令指针IP(Instruction Pointer)<br> 指令指针IP是一个16位专用寄存器,它指向当前需要取出的指令字节,当BIU从内存中取出一个指令字节后,IP就自动加1,指向下一个指令字节。注意,IP指向的是指令地址的段内地址偏移量,又称偏移地址(Offset Address)或有效地址(EA,Effective Address)。<br> (3)标志寄存器FR(Flag Register)<br> 8086有一个18位的标志寄存器FR,在FR中有意义的有9位,其中6位是状态位,3位是控制位。<br> OF: 溢出标志位OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。<br> DF:方向标志DF位用来决定在串操作指令执行时有关指针寄存器发生调整的方向。 <br> IF:中断允许标志IF位用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下: <br> (1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求; <br> (2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。 <br> TF:跟踪标志TF。该标志可用于程序调试。TF标志没有专门的指令来设置或清楚。<br> (1)如果TF=1,则CPU处于单步执行指令的工作方式,此时每执行完一条指令,就显示CPU内各个寄存器的当前值及CPU将要执行的下一条指令。<br> (2)如果TF=0,则处于连续工作模式。<br> SF:符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。 <br> ZF: 零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。 <br> AF:下列情况下,辅助进位标志AF的值被置为1,否则其值为0: <br> (1)、在字操作时,发生低字节向高字节进位或借位时; <br> (2)、在字节操作时,发生低4位向高4位进位或借位时。 <br> PF:奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。 <br> CF:进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。) <br> 4)段寄存器(Segment Register)<br> 为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:<br> CS(Code Segment):代码段寄存器;<br> DS(Data Segment):数据段寄存器;<br> SS(Stack Segment):堆栈段寄存器;<br> ES(Extra Segment):附加段寄存器。<br> 当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器 CS,DS,SS 来指向这些起始位置。通常是将DS固定,而根据需要修改CS。所以,程序可以在可寻址空间小于64K的情况下被写成任意大小。 所以,程序和其数据组合起来的大小,限制在DS 所指的64K内,这就是COM文件不得大于64K的原因。8086以内存做为战场,用寄存器做为军事基地,以加速工作。</p>
<p> </p>
<p> </p>
<p><span style="font-family: 宋体">由于</span>16<span style="font-family: 宋体">位</span><span style="font-family: Arial">/32</span><span style="font-family: 宋体">位</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">是微机</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">的两个重要代表,所以,在此只介绍它们内部寄存器的名称及其主要功能。</span></p>
<p> 1<span style="font-family: 宋体">、 </span><span style="font-family: Arial">16</span><span style="font-family: 宋体">位寄存器组</span></p>
<p> 16<span style="font-family: 宋体">位</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">所含有的寄存器有</span></p>
<p> 4<span style="font-family: 宋体">个数据寄存器</span><span style="font-family: Arial">(AX</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">BX</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">CX</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">DX)</span></p>
<p> 2<span style="font-family: 宋体">个变址和指针寄存器</span><span style="font-family: Arial">(SI</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">DI) 2</span><span style="font-family: 宋体">个指针寄存器</span><span style="font-family: Arial">(SP</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">BP) </span></p>
<p> 4<span style="font-family: 宋体">个段寄存器</span><span style="font-family: Arial">(ES</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">CS</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">SS</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">DS)</span></p>
<p> 1<span style="font-family: 宋体">个指令指针寄存器</span><span style="font-family: Arial">(IP) 1</span><span style="font-family: 宋体">个标志寄存器</span><span style="font-family: Arial">(Flags) </span></p>
<p> 2<span style="font-family: 宋体">、 </span><span style="font-family: Arial">32</span><span style="font-family: 宋体">位寄存器组</span></p>
<p> 32<span style="font-family: 宋体">位</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">除了包含了先前</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">的所有寄存器,并把通用寄存器、指令指针和标志寄存器从</span><span style="font-family: Arial">16</span><span style="font-family: 宋体">位扩充成</span><span style="font-family: Arial">32</span><span style="font-family: 宋体">位之外,还增加了</span><span style="font-family: Arial">2</span><span style="font-family: 宋体">个</span><span style="font-family: Arial">16</span><span style="font-family: 宋体">位的段寄存器:</span><span style="font-family: Arial">FS</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">GS</span><span style="font-family: 宋体">。</span></p>
<p> 32<span style="font-family: 宋体">位</span><span style="font-family: Arial">CPU</span><span style="font-family: 宋体">所含有的寄存器有</span></p>
<p> 4<span style="font-family: 宋体">个数据寄存器</span><span style="font-family: Arial">(EAX</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">EBX</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">ECX</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">EDX)</span></p>
<p> 2<span style="font-family: 宋体">个变址和指针寄存器</span><span style="font-family: Arial">(ESI</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">EDI) 2</span><span style="font-family: 宋体">个指针寄存器</span><span style="font-family: Arial">(ESP</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">EBP) </span></p>
<p> 6<span style="font-family: 宋体">个段寄存器</span><span style="font-family: Arial">(ES</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">CS</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">SS</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">DS</span><span style="font-family: 宋体">、</span><span style="font-family: Arial">FS</span><span style="font-family: 宋体">和</span><span style="font-family: Arial">GS)</span></p>
<p> 1<span style="font-family: 宋体">个指令指针寄存器</span><span style="font-family: Arial">(EIP) 1</span><span style="font-family: 宋体">个标志寄存器</span><span style="font-family: Arial">(EFlags) </span></p>
<p> <span style="font-family: 宋体">具有一个输入端口和两个输出端口。</span></p>
<p><span style="font-family: 宋体">宏与子程序的区别</span><br><span style="font-family: 宋体">宏和子程序都是为了简化源程序的编写,提高程序的可维护性,但是它们二者之间存在着以下本质的区别:</span><br>1<span style="font-family: 宋体">、在源程序中,通过书写宏名来引用宏,而子程序是通过</span><span style="font-family: "Times New Roman"">CALL</span><span style="font-family: 宋体">指令来调用;</span><br>2<span style="font-family: 宋体">、汇编程序对宏通过宏扩展来加入其定义体,宏引用多少次,就相应扩展多少次,所以,引用宏不会缩短目标程序;而子程序代码在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化;</span><br>3<span style="font-family: 宋体">、宏引用时,参数是通过</span><span style="font-family: "Times New Roman"">“</span><span style="font-family: 宋体">实参</span><span style="font-family: "Times New Roman"">”</span><span style="font-family: 宋体">替换</span><span style="font-family: "Times New Roman"">“</span><span style="font-family: 宋体">形参</span><span style="font-family: "Times New Roman"">”</span><span style="font-family: 宋体">的方式来实现传递的,参数形式灵活多样,而子程序调用时,参数是通过寄存器、堆栈或约定存储单元进行传递的;</span><br>4<span style="font-family: 宋体">、宏引用语句扩展后,目标程序中就不再有宏引用语句,运行时,不会有额外的时间开销,而子程序的调用在目标程序中仍存在,子程序的调用和返回均需要时间。</span><br><span style="font-family: 宋体">总之,当程序片段不长,速度是关键因素时,可采用宏来简化源程序,但当程序片段较长,存储空间是关键因素时,可采用子程序的方法来简化源程序和目标程序。</span></p>
<p> </p>
<p>DATA SEGMENT</p>
<p>MSG1 DB </p>
<p>MSG2 DW</p>
<p>DATA ANDS</p>
<p>CODE SEGMENT</p>
<p>ASSUME CS:CODE<span style="font-family: 宋体">,</span><span style="font-family: "Times New Roman"">DS:DATA</span></p>
<p>START:MOV AX, DATA</p>
<p> MOV DS, AX</p>
<p> MOV DX OFFSET MSG1</p>
<p>( MOV BX</p>
<p>MOV AH, 4CH</p>
<p>INT 21H</p>
<p>CODE ENDS</p>
<p>END START</p>
<p><br clear="all"><span style="font-family: 宋体">关于</span>assume<span style="font-family: 宋体">的作用,许多人都简单的解释说,这是告诉编译器哪一个段和哪一个段寄存器相关联。举个简单例子来说:</span><span style="font-family: "Times New Roman""> </span><br>assume cs:code, ds:data <br><span style="font-family: 宋体">这是告诉编译器</span>cs<span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">code</span><span style="font-family: 宋体">关联,</span><span style="font-family: "Times New Roman"">ds</span><span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">关联,后来又看到这样的代码</span><span style="font-family: "Times New Roman""> </span><br>mov ax, data <br>mov ds, ax <br><span style="font-family: 宋体">让许多人一头雾水,既然</span>ds<span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">关联了,怎么又要把</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">的值送到</span><span style="font-family: "Times New Roman"">ds</span><span style="font-family: 宋体">,这到底是怎么回事?</span><span style="font-family: "Times New Roman""> </span><br><span style="font-family: 宋体">这里,先不做过多的说明,我们先看看下面这个例子:</span> <br><br><span style="font-family: 宋体">下面的程序,把</span>data<span style="font-family: 宋体">段中的字符串拷贝到</span><span style="font-family: "Times New Roman"">dseg</span><span style="font-family: 宋体">段中,并且调用</span><span style="font-family: "Times New Roman"">dos</span><span style="font-family: 宋体">的</span><span style="font-family: "Times New Roman"">21h</span><span style="font-family: 宋体">中断的</span><span style="font-family: "Times New Roman"">9</span><span style="font-family: 宋体">号功能来显示</span><span style="font-family: "Times New Roman""> </span><br>dseg<span style="font-family: 宋体">段中的字符串:</span><span style="font-family: "Times New Roman""> </span><br><br>;segtest.asm <br>data segment <br> msg db 'Hello, how are you ?', 0dh, 0ah, 24h <br>data ends <br><br>dseg segment <br> hello db 32 dup(0) <br> db 0dh, 0ah, 24h <br>dseg ends <br><br>code segment <br> assume cs:code, ds:dseg, es:data <br>start: <br> mov ax, dseg <br> mov ds, ax ; <span style="font-family: 宋体">把</span><span style="font-family: "Times New Roman"">dseg</span><span style="font-family: 宋体">段的段地址送入</span><span style="font-family: "Times New Roman"">ds </span><br><br> mov ax, data <br> mov es, ax ; <span style="font-family: 宋体">把</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">段的段地址送入</span><span style="font-family: "Times New Roman"">es </span><br><br> mov si, offset msg ; <span style="font-family: 宋体">把源字符串的偏移送入</span><span style="font-family: "Times New Roman"">si </span><br> mov di, offset hello ; <span style="font-family: 宋体">把目标字符串的偏移送入</span><span style="font-family: "Times New Roman"">di </span><br>cploop: <br> mov al, msg; (1)<span style="font-family: 宋体">这里是一个寄存器相对寻址,那么这个物理地址是怎么形成的呢?</span><span style="font-family: "Times New Roman""> </span><br> cmp al, 24h <br> jz ok <br> mov hello, al; (2)<span style="font-family: 宋体">这里又是一个寄存器相对寻址,这个物理地址又是怎么形成的?</span><span style="font-family: "Times New Roman""> </span><br> inc si <br> inc di <br> jmp short cploop <br><br>ok: <br> mov dx, offset hello <br> mov ah, 9h <br> int 21h <br><br> mov ax, 4c00h <br> int 21h <br>code ends <br> end start <br><br><span style="font-family: 宋体">对于(</span>1<span style="font-family: 宋体">)和(</span><span style="font-family: "Times New Roman"">2</span><span style="font-family: 宋体">)中两个地址的形成我们来分析一下:</span><span style="font-family: "Times New Roman""> </span><br><span style="font-family: 宋体">这两个都是寄存器相对寻址,即有效地址都是一个寄存器加上一个</span>16<span style="font-family: 宋体">位的偏移量</span><span style="font-family: "Times New Roman""> </span><br><span style="font-family: 宋体">对于(</span>1<span style="font-family: 宋体">)</span><span style="font-family: "Times New Roman""> EA = (si) + msg</span><span style="font-family: 宋体">的偏移地址</span><span style="font-family: "Times New Roman""> </span><br> <span style="font-family: 宋体">物理地址就是</span><span style="font-family: "Times New Roman"">: (</span><span style="font-family: 宋体">段寄存器</span><span style="font-family: "Times New Roman"">)</span><span style="font-family: 宋体">×</span><span style="font-family: "Times New Roman"">16+EA </span><br> <span style="font-family: 宋体">段寄存器有四个</span><span style="font-family: "Times New Roman"">cs, ds, es, ss, </span><span style="font-family: 宋体">那么编译器怎么知道用哪一个呢?</span><span style="font-family: "Times New Roman""> </span><span style="font-family: 宋体">这里就显示出了</span><span style="font-family: "Times New Roman"">assume</span><span style="font-family: 宋体">的作用,是</span><span style="font-family: "Times New Roman"">assume</span><span style="font-family: 宋体">告诉了编译器</span><span style="font-family: "Times New Roman"">,data</span><span style="font-family: 宋体">段中的标号的段地址要从</span><span style="font-family: "Times New Roman"">es</span><span style="font-family: 宋体">中取得,即这一句:</span><span style="font-family: "Times New Roman""> </span><br>es:data <span style="font-family: 宋体">告诉了编译器在</span><span style="font-family: "Times New Roman"">data segment</span><span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">data ends</span><span style="font-family: 宋体">之间的所有的标号都要使用</span><span style="font-family: "Times New Roman"">es</span><span style="font-family: 宋体">作为段寄存器来寻址,于是当编译器看到这个</span><span style="font-family: "Times New Roman"">msg</span><span style="font-family: 宋体">标号的时候,它就知道了这里物理地址的形成是用</span><span style="font-family: "Times New Roman"">(es)</span><span style="font-family: 宋体">×</span><span style="font-family: "Times New Roman"">16+EA </span><br><span style="font-family: 宋体">同理,对于(</span>2<span style="font-family: 宋体">),当编译器看到</span><span style="font-family: "Times New Roman"">hello</span><span style="font-family: 宋体">这个标号的时候,它就知道要取</span><span style="font-family: "Times New Roman"">ds</span><span style="font-family: 宋体">中的值作为段地址。如果没有</span><span style="font-family: "Times New Roman""> </span><br>assume<span style="font-family: 宋体">说明哪一个段和哪一个寄存器关联,那么,编译器就无法确定到底用哪一个段寄存器来计算物理地址。</span><span style="font-family: "Times New Roman""> </span><br><br><span style="font-family: 宋体">从这里,我们也可以看出,</span>assume<span style="font-family: 宋体">的作用仅仅是告诉编译器,我碰到一个标号,要计算它的物理地址的时候,从哪一个段寄存器里面取出段值,至于这个段寄存器的值对不对,那它就不管了,这是程序员的事情,反正它只管根据</span><span style="font-family: "Times New Roman"">assume</span><span style="font-family: 宋体">里面的设定来用段寄存器,所以,对于程序员来说,不仅要用</span><span style="font-family: "Times New Roman"">assume</span><span style="font-family: 宋体">告诉编译器计算物理地址的时候要从哪一个段寄存器取值,而且要在指令中明确的把对应段的段值送到设定好的段寄存器中。</span><span style="font-family: "Times New Roman""> </span><br><span style="font-family: 宋体">用伪指令</span>assume<span style="font-family: 宋体">告诉编译器,</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">段中的标号的段地址要从</span><span style="font-family: "Times New Roman"">es</span><span style="font-family: 宋体">中取值,而指令</span><span style="font-family: "Times New Roman""> </span><br>mov ax, data <br>mov es, ax <br><span style="font-family: 宋体">则把</span>data<span style="font-family: 宋体">段的段地址送入</span><span style="font-family: "Times New Roman"">es</span><span style="font-family: 宋体">中,这样编译器计算</span><span style="font-family: "Times New Roman"">msg</span><span style="font-family: 宋体">标号的物理地址的时候,才能得到正确的段地址。</span><span style="font-family: "Times New Roman""> </span><br><br><span style="font-family: 宋体">当然,如果你不用</span>assume<span style="font-family: 宋体">指明哪一个段和哪一个寄存器相关联,比如我把</span><span style="font-family: "Times New Roman"">assume cs:code, ds:dseg, es:data</span><span style="font-family: 宋体">改为</span><span style="font-family: "Times New Roman""> </span><br>assume cs:code<span style="font-family: 宋体">这也可以,即我不把</span><span style="font-family: "Times New Roman"">ds</span><span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">dseg</span><span style="font-family: 宋体">关联,也不把</span><span style="font-family: "Times New Roman"">es</span><span style="font-family: 宋体">和</span><span style="font-family: "Times New Roman"">data</span><span style="font-family: 宋体">关联,但是你必须在指令中明确的告诉编译器使用哪一个段寄存器</span><span style="font-family: "Times New Roman""> </span><br><span style="font-family: 宋体">指令</span>mov al, msg<span style="font-family: 宋体">必须改为</span><span style="font-family: "Times New Roman""> mov al, es:msg</span><span style="font-family: 宋体">,</span><span style="font-family: "Times New Roman""> </span><span style="font-family: 宋体">而指令</span><span style="font-family: "Times New Roman"">mov hello, al</span><span style="font-family: 宋体">也必须改为</span><span style="font-family: "Times New Roman"">mov ds:hello, al</span><span style="font-family: 宋体">,这样编译器才能知道使用哪一个段寄存器计算物理地址。如果编译器无法确定标号的段地址,那么程序编译就不会通过。</span><span style="font-family: "Times New Roman""> </span></p>
</div>
<div id="MySignature">支持原创,转发请附链接:https://www.cnblogs.com/Sumarua/</div>
<div class="clear"> </div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/easy51/p/15558013.html
頁:
[1]