汇编语言复习提纲
<p><strong>第一章:掌握各进制的转换,有符号数的补码表示</strong></p><p>1.1 各进制的转换</p>
<div> <img src="https://img2018.cnblogs.com/i-beta/1222205/201911/1222205-20191119163353167-1922857024.png"></div>
<p> </p>
<p> </p>
<p> </p>
<p> 十进制数一般用D、二进制数用B、八进制数用O、十六进制数用H来表示。 例如:10101100B,115D ,0075H等。</p>
<p> </p>
<p>例:</p>
<p>(1)N=45D 十进制数转换为二进制数(用除以2取余) </p>
<p style="margin-left: 30px">45/2 = 22 (a0= 1) </p>
<p style="margin-left: 30px">22/2 = 11 (a1= 0) </p>
<p style="margin-left: 30px">11/2 = 5 (a2= 1) </p>
<p style="margin-left: 30px"> 5/2 = 2 (a3= 1)</p>
<p style="margin-left: 30px"> 2/2 = 1 (a4= 0)</p>
<p style="margin-left: 30px"> 1/2 = 0 (a5= 1)</p>
<p style="margin-left: 30px">所以:N=45D=101101B</p>
<p> </p>
<p>(2)N=117D 十进制转换为十六进制数(除以16取余法)</p>
<p style="margin-left: 30px">117/16 = 7 (a0= 5)</p>
<p style="margin-left: 30px"> 7/16 = 0 (a1= 7)</p>
<p style="margin-left: 30px">所以 :N=117D=75H</p>
<p> </p>
<p>(3)将二进制数1011100转换为十进制数(各位二进制数码乘以与其对应的权之和)</p>
<p style="margin-left: 30px">1011100B = 1×2^6 + 0×2^5 + 1×2^4 + 1×2^3 + 1×2^2 + 0×2^1 + 0×2^0 = 92D</p>
<p> </p>
<p>(4)将十六进制数3A4转换为十进制数(各位十六进制数码乘以与其对应的权之和)</p>
<p style="margin-left: 30px">3A4H = 3×16^2 + 10×16^1 + 4×16^0 = 932D</p>
<p> </p>
<p>(5)将二进制数0011010110111111转换为十六进制数</p>
<p style="margin-left: 30px">解析:一个二进制数,把它从低位到高位每4位组成一组,直接用十六进制数来表示</p>
<p style="margin-left: 60px"> 0011 0101 1011 1111</p>
<p style="margin-left: 30px"> 3 5 B F</p>
<p style="margin-left: 30px">即:0011010110111111B = 35BFH</p>
<p> </p>
<p>(6)把十六进制数A19C转换成相应的二进制数</p>
<p style="margin-left: 30px">解析:把十六进制数中的每一位用4位二进制数表示,就形成相应的二进制数</p>
<p style="margin-left: 30px"> A 1 9 C</p>
<p style="margin-left: 30px"> 1010 0001 1001 1100</p>
<p style="margin-left: 30px">即:A19CH = 1010000110011100B</p>
<p> </p>
<p>1.2 数的补码</p>
<p>正数(无符号数)来说,其二进制原码,反码,补码均为相同的,为原码的形式。</p>
<p>例:假设机器字长为8位,则[+1]补 = 00000001,[+127]补 = 01111111,[+0]补 = 00000000</p>
<p> </p>
<p>负数(有符号数)的补码为对该数的原码除符号位外各位取反,然后在最后一位加1 </p>
<p>例:机器字长为16位,写出N= -117D的补码表示</p>
<p> +117D可表示为: 0000 0000 0111 0101</p>
<p> 按位求反后为 : 1111 1111 1000 1010</p>
<p> 末位加1后 : 1111 1111 1000 1011</p>
<p> 十六进制数为 : F F 8 B</p>
<p> 即:[-117D]补 = FF8BH</p>
<p> </p>
<p>1.3 符号扩展</p>
<p>常常需要把一个n位二进制数扩展成m位二进制数(m>n)。</p>
<p>当要扩展的数是无符号数时。只要在最高位前扩展(m-n)个0。</p>
<p>例:21的8位二进制和16位的二进制补码如下:</p>
<p> 00010101 8位 </p>
<p> 0000000000010101 16位</p>
<p> </p>
<p>如果要扩展的数是有符号数,并且采用补码形式表示,进行符号扩展。</p>
<p>例:-3的8位二进制补码和16位二进制补码如下: </p>
<p> 11111101 8位</p>
<p> 1111111111111101 16位</p>
<p> </p>
<p>习题1.以下常用的十进制数转换为二进制数和十六进制数: </p>
<p style="margin-left: 30px">65535/2 = 32767 余1 255/2 = 127 余1</p>
<p style="margin-left: 30px">32767/2 = 16383 余1 127/2 = 63 余1</p>
<p style="margin-left: 30px">16383/2 = 8191 余1 63/2 = 31 余1</p>
<p style="margin-left: 30px"> 8191/2 = 4095 余1 31/2 = 15 余1</p>
<p style="margin-left: 30px"> 4095/2 = 2047 余1 15/2 = 7 余1</p>
<p style="margin-left: 30px"> 2047/2 = 1023 余1 7/2 = 3 余1</p>
<p style="margin-left: 30px"> 1023/2 = 511 余1 3/2 = 1 余1</p>
<p style="margin-left: 30px"> 511/2 = 255 余1 1/2 = 0 余1</p>
<p>65535D = 1111 1111 1111 1111 1111 = FFFF H </p>
<p>32767D = 0111 1111 1111 1111 1111 = 7FFF H</p>
<p> 255D = 1111 1111 = FF H</p>
<p> </p>
<p>习题2.十六进制数表示的8位二进制数,D8H和FFH,请说明当它们被看作是用补码表示的带符号数或无符号数时,它们所表示的十进制数是多少?</p>
<p>(1)D8H = 11011000B</p>
<p style="margin-left: 30px">无符号数时:1×2^7+1×2^6+1×2^4+1×2^3=216D</p>
<p style="margin-left: 30px">有符号数时: 11011000</p>
<p style="margin-left: 30px">按位取反 00100000</p>
<p style="margin-left: 30px">末位加1 00101000</p>
<p style="margin-left: 30px">此数为:40D</p>
<p style="margin-left: 30px">∴ D8H无符号数为216D;有符号数为-40D</p>
<p> </p>
<p>(2)FFH = 1111 1111 B</p>
<p style="margin-left: 30px">无符号数时:1×2^7+1×2^6+1×2^5+1×2^4+1×2^3+1×2^2+1×2^1+1×2^0=255D</p>
<p style="margin-left: 30px">有符号数时:1111 1111</p>
<p style="margin-left: 30px">按位取反0000 0000</p>
<p style="margin-left: 30px">末位加10000 0001</p>
<p style="margin-left: 30px">∴ FFH无符号数为255D;有符号数为-1D</p>
<p> </p>
<p><strong>第二章 8086/8088寻址方式和指令系统</strong></p>
<p>掌握各寄存器及寻址方式、以及数据传送指令、堆栈操作指令、加减、乘除运算指令、逻辑运算、移位指令和转移指令。</p>
<p> </p>
<h3>2.1 寄存器组</h3>
<p> 8位寄存器:AL、AH、BL、BH、CL、CH、DL、DH</p>
<p>16位寄存器:AX、BX、CX、DX、SI、DI、SP、BP、SI、DI、IP、FLAG、CS、DS、SS、ES</p>
<p>其中AX、BX、CX、DX可以分作高8位和低8位的两个独立寄存器。如:AH和AL。我们对其中8位的操作,并不影响另外对应的8位数据。 </p>
<p><img src="https://img2018.cnblogs.com/i-beta/1222205/201911/1222205-20191119163556015-1729990903.png"></p>
<p> </p>
<p> </p>
<p> </p>
<p><strong>标志寄存器</strong></p>
<p><img src="https://img2018.cnblogs.com/i-beta/1222205/201911/1222205-20191119163657969-46709445.png"></p>
<p> </p>
<p> </p>
<p>(1)运算结果标志</p>
<p> ① 进位标志CF(Carry Flag):主要用于反映运算是否产生进位或借位。</p>
<p> ② 零标志ZF(Zero Flag):反映运算结果是否为0。如果运算结果为0,则ZF被置1,否则置0。</p>
<p> ③ 符号标志SF(Sign Flag):用于反映运算结果的符号位。</p>
<p> SF与运算结果的最高位相同,如果运算结果的最高位为1,则SF被置1,否则SF被置0。</p>
<p> ④ 溢出标志OF(Overflow Flag):用于反映有符号数加减运算是否引出溢出。</p>
<p> 如运算结果超出了8位或16位有符号数的表示范围,即在字节运算时大于 127 或小于-128,</p>
<p> 在字运算时大于 32767 或小于-32768,称为溢出。如溢出,则OF被置1,否则被置0。</p>
<p> ⑤ 奇偶标志PF(Parity Flag)</p>
<p> 用于反映运算结果中“1”的个数。如果“1”的个数为偶数,则PF被置1; 否则PF被清0。</p>
<p> ⑥ 辅助进位标志AF(Auxiliary Carry Flag)</p>
<p> 在字或字节操作时,如发生低半字节向高半字节进位或借位,则辅助进位标志AF被置1,否则AF被清0。</p>
<p> </p>
<p>(2)状态控制标志</p>
<p> ① 方向标志DF(Direction Flag)</p>
<p style="margin-left: 30px">方向标志决定着串操作指令执行时有关指针寄存器调整方向。</p>
<p style="margin-left: 30px">当DF为1时,串操作指令按减方式改变有关的存储器指针值;</p>
<p style="margin-left: 30px">当DF为0时,串操作指令按加方式改变有关的存储器指针值。</p>
<p> ② 中断允许标志IF(Interrupt - enable Flag)</p>
<p style="margin-left: 30px">中断允许标志决定着CPU是否响应外部可屏蔽中断请求。</p>
<p style="margin-left: 30px">当IF为1时,CPU能够响应外部的可屏蔽中断请求;</p>
<p style="margin-left: 30px">当IF为0时,则不响应外部的可屏蔽中断请求。</p>
<p> ③ 追踪标志TF(Trap Flag)</p>
<p style="margin-left: 30px">当TF被置1后,CPU进入单步方式。所谓单步方式是指在一条指令执行后,产生一个单步中断。主要用于程序的调试。</p>
<p> </p>
<p>2.2 物理地址</p>
<p>存储单元的逻辑地址由:段值和偏移两部分组成,用如下形式表示:段值<strong>:</strong>偏移</p>
<p>根据逻辑地址可方便地得到存储单元的物理地址,公式:物理地址 = 段值×16(左移4位补0)+偏移</p>
<p> </p>
<p> 例:用16进制表示的逻辑地址1234:3456所对应的存储单元的物理地址为:</p>
<p> 物理地址 = 12340 + 3456 = 15796H</p>
<p> </p>
<p>2.3 寻址方式与物理地址计算</p>
<p><strong>物理地址计算公式:物理地址=(DS/SS/ES) × 10H+(AX/BX/CX/DX/SI/DI/BP/SP)</strong></p>
<p> </p>
<h3><span style="font-size: 15px">立即寻址方式(无物理地址)</span></h3>
<p>• 操作数作为指令的一部分。</p>
<p>• 立即数可以是8位可以是16位,立即数为16位时遵循“高高低低”原则。</p>
<p>• 低位字节存放在存储器低地址单元,高位字节存放在存储器高地址单元。</p>
<p>例:</p>
<p> 8 位寄存器 MOV AH, 34H 则指令执行后,(AH)= 34H</p>
<p>16位寄存器 MOV AX, 1234H则指令执行后,(AX)= 1234H</p>
<p> </p>
<h3><span style="font-size: 15px">寄存器寻址方式 (无物理地址)</span></h3>
<p>• 操作数存放在寄存器中,通过指定寄存器来获取数据。</p>
<p> 8 位寄存器 MOV AL, DH // 8 位寄存器与 8 位寄存器可传送</p>
<p>16位寄存器 MOV AX, SI // 16位寄存器与16位寄存器可传送</p>
<p>例:MOV AX,BX</p>
<p>若(AX)= 3064H,(BX)= 1234H;则指令执行后,(AX)=1234H,(BX)保持不变</p>
<p> </p>
<h3><span style="font-size: 15px">直接寻址方式 (物理地址 = (DS)段地址 * 10H + 偏移地址)</span></h3>
<p>• 指令所要的操作数存放在内存中,在指令中直接给出该操作数的有效地址。</p>
<p>• 在通常情况下,操作数存放在数据段中。所以,默认情况下操作数的物理地址由数据段寄存器 DS 中的值和指令中给出的有效地址直接形成。</p>
<p>✯ 注意区别立即寻址和直接寻址书写表示方法上的不同,直接寻址的地址要放在方括号中。在源程序中,往往用变量名表示。</p>
<p> </p>
<p>用符号地址代替数值地址,此时VALUE为存放操作数单元的符号地址。如下两者是等效的:</p>
<p>MOV AX, VALUE或MOV AX, </p>
<p>如VALUE在附加段(ES)中,则应指定段超越前缀。如下两者是等效的:</p>
<p>MOV AX, ES : VALUE 或 MOV AX, ES:</p>
<p> </p>
<p>例:</p>
<p>MOV AX, // 若(DS)=2000H,物理地址 = (DS) + 8054H = 20000H + 8054H = 28054H</p>
<p>MOV AH, VALUE // 将DS段中VALUE单元的内容送给AH</p>
<p>MOV BX, ES : // 段超越,操作数在附加段。即:物理地址 = (ES) * 10H + 2000H</p>
<p> </p>
<h3><span style="font-size: 15px">寄存器间接寻址方式</span></h3>
<p>• 操作数有效地址在 SI 、 DI 、 BX、 BP 这四个寄存器之一中。</p>
<p>• 在不使用段超越前缀的情况下:</p>
<p> ✯ 如果有效地址在 SI 、 DI 、 BX 中,则以数据段寄存器 DS 中的内容为段值。物理地址 = (DS) * 10H + (SI/DI/BX)</p>
<p> ✯ 如果有效地址在 BP 中,则以堆栈段寄存器 SS 中的内容为段值。物理地址 = (SS) * 10H + (BP)</p>
<p> </p>
<p>例:</p>
<p>MOV AX, // 若有效地址用SI、DI和BX等之一来指定,则其缺省的段寄存器为DS</p>
<p> 设 (DS) = 5000H, (SI) = 1234H。 则物理地址 = (DS) × 10H+(SI) = 50000H + 1234H = 51234H</p>
<p>MOV DL, CS : // 物理地址 = CS * 10H + BX 段超越前缀,此时引用的段寄存器是CS而不是自动引用了DS</p>
<p>MOV AX, // 引用的段寄存器为SS</p>
<p> 设 (SS)=3000H,(BP)=1000H。则物理地址 =(SS) × 10H+(BP) = 31000H</p>
<p> </p>
<h3><span style="font-size: 15px">寄存器相对寻址方式 (物理地址 = (DS)*10H + 基址/变址 + 偏移量)</span></h3>
<p>• 操作数的有效地址是一个基址寄存器( BX 、 BP )或变址寄存器( SI 、 DI )的值加上指令中给定的8位/16位偏移量之和。</p>
<p>即:EA(有效地址)= (BX/BP)/(SI/DI) + 8位位移量/16位位移量</p>
<p>• 在不使用段超越前缀的情况下:</p>
<p> ✯ 如果有效地址在 SI 、 DI、 BX 中,则以段寄存器 DS 中的内容为段值</p>
<p> 物理地址=(DS) * 10H+(BX/SI/DI)+8位位移量/16位位移量</p>
<p> ✯ 如果有效地址在 BP 中,则以段寄存器 SS 中的内容为段值</p>
<p> 物理地址=(SS) * 10H+(BP)+8位位移量/16位位移量</p>
<p>• 在指令中给定的8位或16位偏移量采用补码形式表示。在计算有效地址时,如偏移量是8位,则被带符号扩展成16位。</p>
<p>例:</p>
<p>MOV BX,源操作数采用寄存器相对寻址,引用的段寄存器是SS</p>
<p>MOV ES : ,AL 目的操作数采用寄存器相对寻址,引用的段寄存器是ES</p>
<p>以下书写方式是等价的:</p>
<p>MOV AX, </p>
<p>MOV AX, 3</p>
<p> </p>
<p>习题:MOV AX,</p>
<p>设 (DS) = 5000H,(DI) = 3678H。</p>
<p>则物理地址 = (DS) + (DI) + 1223H = 50000H + 3678H + 1223H = 5489BH</p>
<p> </p>
<h3><span style="font-size: 15px">基址加变址寻址方式 (物理地址 = (DS)*10H + 基址 + 变址)</span></h3>
<p>• 操作数的有效地址由基址寄存器( BX 、 BP )之一的值、变址寄存器( SI 、 DI )之一的值相加得到。</p>
<p>即:EA(有效地址) = (BX/BP) + (SI/DI)</p>
<p>• 在不使用段超越前缀的情况下:</p>
<p>✯ 如果有效地址在 SI 、 DI 、 BX 中,则以段寄存器 DS 中的内容为段值。</p>
<p>✯ 如果有效地址在 BP 中,则以段寄存器 SS 中的内容为段值。</p>
<p> </p>
<p>MOV DS : , AL目的操作数采用基址加变址寻址,引用的段寄存器是DS</p>
<p>MOV AX, ES : 源操作数采用基址加变址寻址,引用的段寄存器是ES</p>
<p>以下三种书写方式是等价的:</p>
<p>MOV AX, MOV AX, MOV AX, </p>
<p> </p>
<p>例:MOV AX, </p>
<p>设 (DS) = 2100H, (BX) = 0158H, (DI) = 10A5H。</p>
<p>则EA(有效地址) = 0158H + 10A5H = 11FDH;物理地址 = 21000H + 11FDH = 221FDH</p>
<p> </p>
<p><span style="font-size: 15px"><strong>相对基址加变址寻址方式 </strong>(物理地址 = (DS)*10H + 基址 + 变址 + 偏移量)</span></p>
<p>• 操作数的有效地址由基址寄存器( BX 、 BP )之一的值、变址寄存器( SI 、 DI )之一的值及指令中给定的8位/16位偏移量之和。</p>
<p>以下 4 种书写方式是等价的:</p>
<p>MOV AX, MOV AX, 1234H MOV AX, 1234H MOV AX, 1234H</p>
<p> </p>
<p>例:MOV AX, </p>
<p>设(DS)=1000H,(BX)=2100H,(SI)=0010H,内存单元12310H的内容为1234H。问该指令执行后,AX的值是什么?</p>
<p>解:</p>
<p>有效地址EA = (BX) + (SI) + 200H = 2100 H+ 0010H + 200H = 2310H</p>
<p>物理地址PA = (DS) × 10H + EA=1000H × 10H + 2310H = 12310H</p>
<p>该指令的执行效果是:把从物理地址为12310H开始的一个字的值传送给AX,所以AX=12310H。</p>
<p> </p>
<p>习题</p>
<p>1.现有(DS)=2000H,(BX)=0100H, (SI)=0002H, (20100)=12H, (20101)=34H, (20102)=56H,</p>
<p>(20103)=78H, (21200)=2AH, (21201)=4CH,(21202)=B7H, (21203)=65H</p>
<p>试说明下列各条指令执行完后AX寄存器的内容</p>
<p>(1) MOV AX, 1200H // (AX) = 1200H 立即寻址</p>
<p>(2) MOV AX, BX // (AX) = 0100H 寄存器寻址</p>
<p>(3) MOV AX, // (AX) = 4C2AH 直接寻址</p>
<p>(4) MOV AX, // (AX) = 3412H 寄存器间接寻址</p>
<p>(5) MOV AX, 1100 // (AX) = 4C2AH 寄存器相对寻址</p>
<p>(6) MOV AX, // (AX) = 7856H 基址加变址寻址</p>
<p>(7) MOV AX, 1100 // (AX) = 65B7H 相对基址加变址寻址</p>
<p> </p>
<p>2.假设(DS)=2000H, (ES)=2100H, (SS)=1500H, (SI)=00A0H, (BX)=0100H,(BP)=0010H,数据段中变量名VAL的偏移地址值为0050H, 试指出下列源操作数字段的寻址方式及物理地址值是多少?</p>
<p>(1) MOV AX, 0ABH // 立即寻址,无物理地址</p>
<p>(2) MOV AX, BX // 寄存器寻址,无物理地址 (AX)=0100H</p>
<p>(3) MOV AX, // 直接寻址,物理地址 = (DS) × 10H +100H = 20100H</p>
<p>(4) MOV AX, VAL // 直接寻址,物理地址 = (DS) × 10H +VAL = 20050H</p>
<p>(5) MOV AX, // 寄存器间接寻址,物理地址 = (DS)×10H + BX = 20100H</p>
<p>(6) MOV AX, ES: // 段跨越前缀寄存器间接寻址,物理地址 = (ES)×10H + BX = 21100H</p>
<p>(7) MOV AX, // 寄存器间接寻址,物理地址 = (SS)×10H + BP = 15010H</p>
<p>(8) MOV AX, // 寄存器间接寻址,物理地址 = (DS)×10H + SI = 200A0H</p>
<p>(9) MOV AX, // 寄存器相对寻址,物理地址 = (DS)×10H + BX + 10H = 20110H</p>
<p>(10) MOV AX,VAL // 寄存器相对寻址,物理地址 = (DS)×10H + BX + VAL = 21050H</p>
<p>(11) MOV AX, // 基址加变址寻址,物理地址 = (DS)×10H + BX + SI = 210A0H</p>
<p>(12) MOV AX, VAL // 相对基址加变址寻址</p>
<p>物理地址 = (DS)×10H + VAL+ BX + SI = 20000H + 0050H + 0100H + 00A0H = 210F0H</p>
<p> </p>
<p> </p>
<p>2.4 8086/8088指令系统</p>
<p><strong>传送指令 </strong>不影响标志位</p>
<p>格式:MOV DST,SRC</p>
<p>(1)CPU内部寄存器之间的数据传送。</p>
<p>例如:MOV AH, AL MOV BP, SP MOV AX, CS</p>
<p>✯ 源和目的操作数不能同时是段寄存器。 如:MOV DS, ES</p>
<p>✯ 代码段寄存器CS不能作为目的操作数。 如:MOV CS, AX</p>
<p>✯ 指令指针IP既不能作为源操作数,也不能作为目的操作数。</p>
<p> </p>
<p>(2)立即数送至通用寄存器或存储单元(各种存储器寻址方式)。</p>
<p>✯ 立即数不能直接传送到段寄存器。 如:MOV DS, 3</p>
<p>✯ 立即数永远不能作为目的操作数。</p>
<p> </p>
<p>(3)寄存器与存储器间的数据传送。</p>
<p>✯ 源操作数和目的操作数类型要一致,即源操作数目的操作数都是8位寄存器或者16位寄存器。</p>
<p>✯ 除了串操作指令外,源操作数和目的操作数不能同时是存储器操作数。</p>
<p> </p>
<p>如果要在两个 存储单元间 或 段寄存器间 传送数据,那么可利用通用寄存器过渡的方法进行。</p>
<p>例1:把字变量VARW1的内容送到字变量VARW2</p>
<p>MOV AX,VARW1 // 先把VARW1的内容送到AX</p>
<p>MOV VARW2,AX // 先把CS的内容送到VARW2</p>
<p>例2:把CS的内容送到DS</p>
<p>MOV AX,CS // 先把CS的内容送到AX</p>
<p>MOV DS,AX // 再把AX的内容送到DS</p>
<p> </p>
<p><strong>交换指令 </strong>不影响标志位</p>
<p>概述:方便地实现 通用寄存器 与 通用寄存器 或 存储单元 间 的数据交换</p>
<p>格式:XCHG OPRD1,OPRD2</p>
<p>✯ 源操作数和目的操作数必须同时是字节或字。 如:XCHG AL, AH XCHG SI, BX</p>
<p>✯ 两个操作数可以是通用寄存器和存储单元。但不包括段寄存器,也不能同时是存储单元也不能有立即数。 如:XCHG AX, VARW XCHG AX, 1234H</p>
<p>例:XCHG BX, </p>
<p>设(BX)=6F30H, (BP)=0200H, (SI)=0046H, (SS)=2F00H, (2F246)=4154H</p>
<p>物理地址 = SS * 10H + BP + SI = 2F000 + 0200 + 0046 = 2F246H</p>
<p>指令执行后: (BX)=4154H (2F246H)=6F30H(BX的内容送到2F246H中)</p>
<p> </p>
<p><strong>地址传送指令 </strong>不影响标志位</p>
<p>(1)指令LEA(Load Effective Address)</p>
<p>格式: LEA REG,OPRD</p>
<p>指令LEA称为传送有效地址指令,该指令把操作数OPRD的有效地址传送到操作数REG。</p>
<p>✯ 操作数OPRD必须是一个存储器操作数。</p>
<p>✯ 操作数REG必须是一个16位的通用寄存器。</p>
<p>例: LEA BX, 相对基址加变址寻址</p>
<p>设指令执行前 (BX)=0400H, (SI)=003CH</p>
<p> 指令执行后 (BX) = BX + SI + 0F62H = 0040H + 003CH + 0F62H = 139EH</p>
<p> </p>
<p>(2)指令LDS(Load pointer into DS)</p>
<p>段值和段内偏移构成32位的地址指针。该指令传送32位地址指针到数据段寄存器DS。</p>
<p>格式:LDS REG,OPRD</p>
<p>执行的操作:</p>
<p> REG ← OPRD // 把偏移部分送到指令给出的通用寄存器REG</p>
<p> DS ← OPRD+2 // 把操作数OPRD中所含的一个32位地址指针的段值部分送到数据段寄存器DS</p>
<p>✯ 目的操作数OPRD必须是一个32位的存储器操作数。</p>
<p>✯ 源操作数REG可以是一个16位的通用寄存器,但实际使用的往往是变址寄存器或指针寄存器。</p>
<p> </p>
<p>例:LDS SI, [ 10H ]</p>
<p>设指令执行前: (DS)= C000H, (C0010H)= 0180H, (C0012H)= 2000H</p>
<p> 指令执行后: (SI)= 0180H, (DS)= 2000H</p>
<p> </p>
<p>(3)指令LES(Load pointer into ES)</p>
<p>该指令传送32位地址指针到附加段寄存器ES。</p>
<p>格式:LES REG,OPRD</p>
<p>执行的操作:</p>
<p> REG ← OPRD // 把偏移部分送到指令给出的通用寄存器REG</p>
<p> ES ← OPRD+2 // 把操作数OPRD中所含的一个32位地址指针的段值部分送到附加段寄存器ES</p>
<p> </p>
<p>例如: LES DI, [ BX ]</p>
<p>如指令执行前:(DS)=B000H,(BX)=080AH,(0B080AH)=05AEH,(0B080CH)=4000H</p>
<p> 指令执行后:(DI)= DS × 10H + BX = 0B080AH = 05AEH , (ES)= 4000H</p>
<p> </p>
<p>习题</p>
<p>1. 如TABLE为数据段中0032单元的符号名,其中存放的内容为1234H,试问以下指令有什么区别?指令执行完后AX寄存器的内容是什么?</p>
<p>MOV AX, TABLE // 直接寻址,把TABLE内容传送给AX。 (AX)= 1234H</p>
<p>LEA AX, TABLE // 将TABLE有效地址与AX交换。(AX)= 0032H</p>
<p>MOV AX,OFFSET TABLE // 将TABLE有效地址传送给AX。(AX)= 0032H</p>
<p> </p>
<p>2. 一个有16个字的的数据区,它的起始地址为70A0:DDF6,请写出这个数据区首末字单元的物理地址。</p>
<p>首地址为:70A00 + DDF6 = 7E7F6H</p>
<p>末地址为:7E7F6 + 1E = 7E814H </p>
<p>因为是16个字,32个字节,首末中间隔着30个字节,末地址 = 首地址 + 1E(30的16进制数)</p>
<p> </p>
<p><strong>堆栈操作指令 </strong>不影响标志位 后进先出</p>
<p>堆栈的段值在堆栈段寄存器SS中,堆栈指针寄存器SP始终指向栈顶。</p>
<p>堆栈的存取必须以字为单位。</p>
<p> </p>
<p>(1)进栈指令PUSH</p>
<p>格式:PUSH SRC</p>
<p>执行的操作: (SP) ← (SP)-2</p>
<p>该指令把源操作数SRC压入堆栈。它先把堆栈指针寄存器SP的值减2,然后把源操作数SRC送入由SP所指的栈顶。</p>
<p>✯ 源操作数SRC可以是通用寄存器和段寄存器,也可以是字存储单元。 </p>
<p>例:PUSH AX PUSH DS PUSH VARW PUSH </p>
<p> </p>
<p>(2)出栈指令POP</p>
<p>格式:POP DST// DST可以是通用寄存器和段寄存器(但CS例外),也可以是字存储单元。</p>
<p>执行的操作: (SP) ← (SP) + 2</p>
<p>该指令从栈顶弹出一个字数据到目的操作数DST。它先把堆栈指针寄存器SP所指的字数据送至目的的操作数DST,然后SP值加2。</p>
<p>✯ 以上两条指令PHSH和POP只能作字操作。</p>
<p>✯ 它们可以使用除立即数以外的其他寻址方式。</p>
<p>✯ POP指令不允许用CS寄存器。</p>
<p> </p>
<p>数据交换的三种方式:传送指令、交换指令、堆栈指令</p>
<p>扩展:将寄存器AX与SI的内容交换</p>
<p>(1)MOV指令,利用通用寄存器过渡的方法</p>
<p> MOV BX, AX</p>
<p> MOV AX, SI</p>
<p> MOV SI, BX</p>
<p>(2)用交换指令XCHG</p>
<p> XCHG AX, SI</p>
<p>(3)用堆栈指令:临时保存寄存器的内容</p>
<p> PUSH AX</p>
<p> PUSH SI</p>
<p> ……</p>
<p> POP AX ;使AX内容与SI相同</p>
<p> POP SI</p>
<p> </p>
<p>习题:假设(SS)= 2250H,(SP)= 0140H,如果在堆栈中存入5个数据,则栈顶的物理地址为多少?如果又从堆栈中取出3个数据,则栈顶的物理地址是多少?</p>
<p>解:未存入数据之前物理地址 = 22500 + 0140 = 22640H</p>
<p>存入5个数据栈顶的物理地址为:22640 - 0A = 22636H</p>
<p>取出3个数据栈顶的物理地址为:22636 + 6 = 2263CH</p>
<p> </p>
<p><strong>标志操作指令</strong></p>
<p>(1)标志传送指令 </p>
<p> ① 指令LAHF(Load AH with Flags)</p>
<p> 指令LAHF采用固定寻址方式,格式:LAHF</p>
<p> 该条指令把标志寄存器的低8位(包括SF、ZF、AF、PF和CF)传送到寄存器AH的指定位。</p>
<p> 这条指令本身不影响这些标志和其他标志。</p>
<p> </p>
<p> ② 指令SAHF (Store AH into Flags)</p>
<p>指令SAHF采用固定寻址方式,格式:SAHF</p>
<p>该条指令与指令LAHF刚好相反,把寄存器AH的指定位送至标志寄存器低8位的SF、ZF、AF、PF和CF标志位。因而这些标志的内容就要受到影响,并取决于AH中相应位的状态。</p>
<p>但这条指令不影响溢出标志OF、方向标志DF、中断允许标志IF和追踪标志TF,也即不影响标志寄存器的高位字节。</p>
<p>例如:</p>
<p>MOV AH,0C1H</p>
<p>SAHF ;CF=1,PF=0,AF=0,ZF=1,SF=1</p>
<p>如图所示: </p>
<p> <img src="https://img2018.cnblogs.com/i-beta/1222205/201911/1222205-20191119164004963-1996436822.png"></p>
<p> </p>
<p> </p>
<p>③ 指令PUSHF</p>
<p>格式:PUSHF</p>
<p>该条指令把标志寄存器的内容压入堆栈,即先把堆栈指针寄存器SP的值减2,然后把标志寄存器的内容送入由SP所指的栈顶。</p>
<p> </p>
<p> ④ 指令POPF</p>
<p>格式: POPF</p>
<p>该条指令把当前堆栈顶的一个字传送到标志寄存器,同时相应地修改堆栈指针,即把堆栈指针寄存器SP的值加2。</p>
<p> </p>
<p>POPF和PUSHF指令一起可以保存和恢复标志寄存器的内容,即保存和恢复各标志的值。另外,这两条指令也可以用来改变追踪标志TF。</p>
<p> </p>
<p>(2)标志位操作指令 仅对指令规定的标志,产生指令规定的影响</p>
<p> ① 清进位标志指令CLC(Clear Carry flag)</p>
<p> 格式:CLC 该指令使进位标志为0。</p>
<p> </p>
<p> ② 置进位标志指令STC(SeT Carry flag)</p>
<p> 格式:STC 该指令使进位标志为1。</p>
<p> </p>
<p> ③ 进位标志取反指令CMC(CoMplement carry flag)</p>
<p> 格式:CMC 该指令使进位标志取反。如CF为1,则使CF为0;如CF为0,则使CF为1。</p>
<p> </p>
<p> ④ 清方向标志CLD(Clear Direction flag)</p>
<p> 格式:CLD 该条指令使方向标志DF为0。</p>
<p> 从而在执行串操作指令时,使地址按递增方式变化。</p>
<p> </p>
<p> ⑤ 置方向标志STD(SeT Direction flag)</p>
<p> 格式:STD 该条指令使方向标志DF为1。</p>
<p> 从而在执行串操作指令时,使地址按递减方式变化。</p>
<p> </p>
<p> ⑥ 清中断允许标志CLI(Clear Interrupt enable flag)</p>
<p> 格式: CLI 该条指令使中断允许标志IF为0,于是CPU就不响应来自外部装置的可屏蔽中断。</p>
<p> 但对不可屏蔽中断和内部中断都没有影响。</p>
<p> </p>
<p> ⑦ 置中断允许标志STI(SeT Interrupt enable flag)</p>
<p> 格式:STI 该条指令使中断允许标志IF为1,则CPU可以响应可屏蔽中断。</p>
<p> </p>
<p>习题:设当前数据段寄存器的内容为1B00H,在数据段的偏移地址2000H单元内,含有一个内容为0FF10H和8000H的指针,它们是一个16位变量的偏移地址和段地址,试写出把该变量装入AX的指令序列。</p>
<p>根据题意可得:(DS)=1B00H, 偏移地址2000H, 段地址8000H: FF10H</p>
<p>物理地址 = 1B000H + 2000H = 1D000H, (1D000H)=0FF10H, (1D002H)=8000H</p>
<p>MOV BX, // (BX) = 0FF10H</p>
<p>MOV ES, // (ES) = 8000H</p>
<p>MOV AX, ES:</p>
<p> </p>
<p><strong>加法指令</strong> 影响标志位</p>
<p>(1)普通加法指令 ADD</p>
<p style="margin-left: 30px">格式:ADD OPRD1, OPRD2</p>
<p style="margin-left: 30px">执行的操作: (OPRD1) ← (OPRD1) + (OPRD2)</p>
<p>例1:</p>
<p> MOV AX,7896H ; AX=7896H,即AH=78H,AL=96H;各标志位保持不变</p>
<p> ADD AL,AH ;AL=0EH,AH=78H,即AX=780EH; CF=1,ZF=0,SF=0,OF=0,AF=0,PF=0</p>
<p> </p>
<p>例2: ADD DX, 0F0F0H 执行前 ( DX ) = 4652H</p>
<p> 执行后 ( DX ) = 3742H, ZF=0,SF=0,CF=1,OF=0</p>
<p> </p>
<p>例3:ADD AX, 4321 执行前 (AX) = 62A0H</p>
<p> 执行后 (AX) = A5C1H SF=1,ZF=0,CF=0,OF=1</p>
<p> </p>
<p>SF 符号标志位根据运算结果最高位决定,若最高位为0则是正数,则SF=0,否则SP=1。如例3 结果最高位是A-1010,第一位是1,表示负数,所以SF=1。</p>
<p>OF 溢出标志位根据操作数的符号及其变化情况来设置,若两个操作数的符号相同而结果的符号与之相反时OF=1,否则OF=0。如例3 正数加正数结果为负数,则溢出OF=1。</p>
<p> </p>
<p>(2)带进位加法指令 ADC</p>
<p style="margin-left: 30px">格式:ADC OPRD1, OPRD2</p>
<p style="margin-left: 30px">执行的操作:(OPRD1) ← (OPRD1) + (OPRD2) + CF</p>
<p> </p>
<p>例:下列指令序列执行两个双精度的加法。</p>
<p>设目的操作数放在DX和AX寄存器中,其中DX存放高位字。源操作数存放在BX、CX中,其中BX存放高位字。如指令执行前:(DX)=0002H, (AX)=0F365H,(BX)=0005H, (CX)=0E024H</p>
<p>指令序列为: ADD AX,CX</p>
<p> ADC DX,BX</p>
<p>执行第一条指令后:</p>
<p>(AX)= (AX) + (CX) = 0F365H + 0E024H = 0D389H, SF=1,ZF=0,CF=1,OF=0</p>
<p>执行第二条指令后:</p>
<p>(DX)= (DX) + (BX) + CF = 0002H + 0005H + 0 = 0007H,SF=0,ZF=0,CF=0,OF=0</p>
<p>则该指令序列执行完后: (DX)=0008H,(AX)=D389H</p>
<p> </p>
<p>(3)加1指令 INC</p>
<p style="margin-left: 30px">格式:INC OPRD</p>
<p style="margin-left: 30px">执行的操作:OPRD ← OPRD + 1</p>
<p style="margin-left: 30px">这条指令执行的结果影响标志ZF、SF、OF、PF和AF,但它不影响CF。</p>
<p> </p>
<p>例1:写出把首地址为BLOCK的字数组的第6个字送到DX寄存器的指令.</p>
<p>要求使用以下几种寻址方式:</p>
<p>(1) 寄存器间接寻址 </p>
<p>MOV BX, OFFSET BLOCK</p>
<p>ADD BX, 000AH ;10个字节</p>
<p>MOV DX, [ BX ]</p>
<p>(2) 寄存器相对寻址 </p>
<p>MOV BX, OFFSET BLOCK</p>
<p>MOV DX, [ BX+000AH ]</p>
<p> </p>
<p>例2:在TABLE数组中依次存储了七个字数据,紧接着是名为ZERO的字单元,表示如下:</p>
<p>TABLE DW 23, 36, 2, 100, 32000, 54, 0</p>
<p>ZERO DW ?</p>
<p>(1) 如果BX包含数组TABLE的初始地址,请编写指令将数据0传送给ZERO单元.</p>
<p>MOV AX , [ BX+0CH ]</p>
<p>MOV ZERO, AX</p>
<p>(2) 如果BX包含数据0在数组中的位移量,请编写指令将数据0传送给ZERO单元</p>
<p>MOV AX, [ TABLE +BX ]</p>
<p>MOV ZERO, AX.</p>
<p> </p>
<p><strong>减法指令</strong></p>
<p> 减法的OF位:若两个数的符号相反(异号相减), 而结果的符号与减数相同则OF=1.</p>
<p>(1)普通减法指令 SUB</p>
<p> 格式:SUB OPRD1, OPRD2</p>
<p> 执行的操作: (OPRD1) ← (OPRD1) - (OPRD2)</p>
<p> 例1:SUB [ SI+14H ] , 0136H</p>
<p>指令执行前 (DS)=3000H , (SI)=0040H,(30054H)=4336</p>
<p>指令执行后 (30054H)=4200H SF=0 , ZF=0 , CF=0 , OF=0</p>
<p> </p>
<p> 例2:SUB DH, [ BP+4 ]</p>
<p>指令执行前 (DH)=41H , (SS)=0000H , (BP)=00E4H , (000E8H)=5AH</p>
<p>指令执行后 (DH)=0E7H , SF=1 , ZF=0 , CF=1, OF=0</p>
<p> </p>
<p>(2)带借位减法指令 SBB</p>
<p> 格式:SBB OPRD1, OPRD2</p>
<p> 执行的操作: (OPRD1) ← (OPRD1) - (OPRD2) - CF</p>
<p> </p>
<p>(3)减1指令 DEC</p>
<p> 格式:DEC OPRD</p>
<p> 执行的操作: (OPRD) ← (OPRD) - 1</p>
<p> </p>
<p>(4)取补指令 NEG(NEGate)</p>
<p> 格式:NEG OPRD</p>
<p> 执行的操作: (OPRD) ← -(OPRD)</p>
<p> 如在字节操作时对-128取补,或在字操作时对-32768取补,则操作数不变,但OF被置1。其它均为0</p>
<p> 操作数为0时,求补运算的结果使CF=0,其它情况则均为1。</p>
<p> </p>
<p>(4)比较指令 CMP(CoMPare)</p>
<p> 格式:CMP OPRD1,OPRD2</p>
<p> 这条指令完成操作数OPRD1减去操作数OPRD2,运算结果不送到OPRD1,</p>
<p> 但影响标志CF、ZF、SF、OF、AF和PF。</p>
<p> </p>
<p> 执行了比较指令后,可根据ZF是否置位,判断两者是否相等;</p>
<p> 如果两者是无符号数,则可根据CF判断大小;</p>
<p> 如果两者是有符号数,则要根据SF和OF判断大小。</p>
<p> </p>
<p> </p>
<p>习1:设X\Y\Z均为双精度数,它们分别存放在地址为X, X+2; Y, Y+2; Z, Z+2的存储单元中,存放时高位字在高地址中,低位字在低地址中。用指令实现W←X+Y+24-Z并用W和W+2单元存放运算结果。</p>
<p>MOV AX, X MOV DX, X+2</p>
<p>ADD AX, Y ADC DX, Y+2 ;低位加完要考虑有没有进位</p>
<p>ADD AX, 24 ADC DX, 0 ;低位加完要考虑有没有进位 </p>
<p>SUB AX, Z SBB DX, Z+2</p>
<p>MOV W, AX MOV W+2, DX</p>
<p> </p>
<p>习2:写出执行以下计算的指令序列,其中X, W, Z均为存放16位带符号数单元的地址。</p>
<p>Z←W + (Z-X)</p>
<p>MOV AX, Z SUB AX, X ADD AX, W MOV Z, AX</p>
<p> </p>
<p>习3:写出对存放在DX和AX中的双字长数求补的指令序列</p>
<p> NEG DX ;先对高位DX求补</p>
<p> NEG AX ;再对地位AX求补</p>
<p> SBB DX,0 ;再看有没有借位</p>
<p> </p>
<p><strong>乘法指令</strong></p>
<p>(1)无符号数乘法指令 MUL(MULtiply)</p>
<p> 格式:MUL OPRD</p>
<p> 隐含的目的操作数必须是累加器。</p>
<p> 若OPRD是字节操作数,则把AL中的无符号数与OPRD相乘,16位结果送到AX中;若OPRD是字操作数,则把AX中的无符号数与OPRD相乘,32位结果送到DX(高16位)和AX(低16位)中。</p>
<p> 如果乘积结果的高半部分(字节相乘时为AH,在字相乘时为DX)不等于零,则标志CF= OF=1(如:1234);否则CF= OF=0(如:0014)。所以如果CF=1和OF=1表示在AH或DX中含有结果的有效数。</p>
<p> </p>
<p>(2)有符号数乘法指令 IMUL(sIgned MULtiply)</p>
<p> 格式:IMUL OPRD</p>
<p> 如果乘积结果的高半部分(字节相乘时为AH,在字相乘时为DX)不是低半部分的符号扩展,则标志CF=1,OF=1;否则CF=0,OF=0(如:FFBB/0014)。</p>
<p> </p>
<p> 例:如(AL)=0B4H,(BL)=11H 求执行指令 IMUL BL 和 MUL BL 后的乘积值</p>
<p>(AL) = 0B4H 为无符号的180D,带符号数的-76D(取反+1)</p>
<p>(BL) = 11H 为无符号的17D,带符号数的17D</p>
<p>执行 MUL BL 的结果为 (AX)= 0B4H × 11H = 0BF4H = 3060D CF=OF=1</p>
<p>执行 IMUL BL 的结果为 (AX)= 0FFB4H × 11H = 0FAF4H = -1292D CF=OF=1</p>
<p> </p>
<p><strong>除法指令</strong></p>
<p>(1)无符号数除法指令 DIV(DIVersion)</p>
<p> 格式:DIV OPRD</p>
<p> 字节操作表示为: ( AL ) → (AX) / (OPRD) 的商;(AH) → ( AX) / (OPRD) 的余数</p>
<p> 字操作表示为:( AX ) → (DX,AX) / (OPRD) 的商;(DX) → ( DX,AX ) / (OPRD) 的余数</p>
<p> 如果除数为0,或者在8位数除时商超过8位。或者在16位除时商超过16位,则认为是除溢出,引起0号中断。</p>
<p> </p>
<p>(2)有符号数除法指令 IDIV(sIgned DIVersion)</p>
<p> 格式:IDIV OPRD</p>
<p> </p>
<p> 例:设(AX)= 0400H,(BL)= 0B4H</p>
<p>即(AX)为无符号数的1024D,带符号数的1024D</p>
<p> (BL)为无符号数的 180 D,带符号数的-76D</p>
<p>执行 DIV BL 的结果是:(AH)= 0400H % 007CH = 124D 余数 (AL)=05H=5D 商</p>
<p>执行 IDIV BL 的结果是:(AH)=24H=36D 余数 (AL)=0F3H= -13D 商</p>
<p> </p>
<p><strong>符号扩展指令 </strong>不影响各标志位</p>
<p>由于除法指令隐含使用字被除数或双字被除数,所以当被除数为字节,或者除数和被除数均为字时,需要在除操作前扩展被除数。</p>
<p> </p>
<p>(1)字节转换为字指令 CBW(Convert Byte to Word)</p>
<p> 格式:CBW // 指令把寄存器AL中的符号扩展到寄存器AH</p>
<p> 例:MOV AX,3487H ;AX=3487H,即AH=34H,AL=87H</p>
<p> CBW ;AH=0FFH,AL=87H,即AX=0FF87H </p>
<p> 10000111 8 位 // 扩充前:78H</p>
<p> 11111111 10000111 16位 // 扩充后:FF87H</p>
<p> </p>
<p>(2)字转换为双字指令 CWD(Convert Word to Double word )</p>
<p> 格式:CWD // 指令把寄存器AX中的符号扩展到寄存器DX</p>
<p> 例: MOV AX,4567H ;AX=4567H</p>
<p> CWD ;AX=4567H,DX=0</p>
<p> 01000101 01100111 16位 // 扩充前:4567H</p>
<p> 00000000 00000000 01000101 01100111 32位 // 扩充后:AX = 4567H, DX = 0H</p>
<p> </p>
<p>习题:计算如下表达式的值:(X*Y+Z-1024)/75。假设其中的X、Y和Z均为16位带符号数,分别存放在名为XXX、YYY和ZZZ的变量单元中。再假设计算结果的商保存在AX中,余数保存在DX中。</p>
<p>MOV AX,XXX</p>
<p>IMUL YYY ;计算X*Y,带符号 16位*16位=32位</p>
<p>MOV CX,AX </p>
<p>MOV BX,DX ;积保存到BX:CX中</p>
<p>MOV AX,ZZZ</p>
<p>CWD ;把ZZZ扩展成32位(AX扩展成DX)</p>
<p>ADD AX,CX ;再计算和</p>
<p>ADC DX,BX</p>
<p>SUB AX,1024 ;再计算差</p>
<p>SBB DX,0</p>
<p>MOV CX,75</p>
<p>IDIV CX ;最后计算商和余数</p>
<p> </p>
<p><strong>逻辑指令</strong></p>
<p>(1)否操作指令 NOT</p>
<p> 格式: NOT OPRD// 该指令把操作数OPRD取反,然后送回OPRD。</p>
<p> 操作数OPRD可以是通用寄存器,也可以是存储器操作数。此指令对标志没有影响。</p>
<p> 例:NOT AL 设 (AL) = 34H 00110100B 取反 11001011 ∴ (AL) = CBH</p>
<p> </p>
<p>(2)与操作指令AND</p>
<p> 格式:AND OPRD1,OPRD2;CF=0,OF=0</p>
<p> 该指令执行以后,标志CF=0,标志OF=0,标志PF、ZF、SF反映运算结果,标志AF未定义。</p>
<p> 某个操作数自己与自己相“与”,则值不变,但可使进位标志CF清0。</p>
<p> 参与运算的两个数据同时为1,则结果值为1。否则为0</p>
<p> 例:AND AL, 0FH 设 (AL) = 34H 执行指令后:(AL) = 04H</p>
<p> 34H --- 00110100B </p>
<p> 0FH --- 00001111B</p>
<p>______________________</p>
<p> 00000100B --- 04H</p>
<p> </p>
<p>(3)或操作指令OR</p>
<p> 格式:OR OPRD1,OPRD2</p>
<p> 这条指令执行以后,标志CF=0,标志OF=0,标志PF、ZF、SF反映运算结果,标志AF未定义。</p>
<p> 某个操作数自己与自己相“或”,则值不变,但可使进位标志CF清0。</p>
<p> 参与运算的两个数据只要有一个值为1,那么结果值为1</p>
<p> 例:OR AL, 20H 设 (AL) = 41H 执行指令后:(AL) = 61H</p>
<p>41H --- 01000001B </p>
<p>20H --- 00100000B</p>
<p>______________________</p>
<p> 01100001B ---61H</p>
<p> </p>
<p>(4)异或操作指令 XOR</p>
<p> 格式:XOR OPRD1,OPRD2</p>
<p> 该指令执行以后,标志CF=0,标志OF=0,标志PF、ZF、SF反映运算结果,标志AF未定义。</p>
<p> 某个操作数自己与自己相“异或”,则结果为0,并可使进位标志CF清0。</p>
<p> 参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。</p>
<p> 例:XOR AL, 0FH 设 (AL) = 34H 执行指令后:(AL) = 3BH</p>
<p> 34H --- 00110100B </p>
<p> 0FH --- 00001111B</p>
<p>______________________</p>
<p> 00111011B --- 3BH</p>
<p> </p>
<p>(5)测试指令 TEST</p>
<p> 格式:TEST OPRD1,OPRD2</p>
<p> 该指令和指令AND类似,也把两个操作数进行按位“与”,但结果不送到操作数OPRD1。</p>
<p> 该指令执行以后,标志ZF、PF和SF反映运算结果,标志CF和OF被清0。</p>
<p> 例:要检查AL中的位6或位2是否有一位为1,可使用如下的指令:</p>
<p> TEST AL,01000100B ;符号B表示二进制</p>
<p> 如果位6和位2全为0,那么在执行上面的指令后,ZF被置1,否则ZF被清0。</p>
<p> </p>
<p>习题1:要求屏蔽0、1两位。</p>
<p> 解析:即将第0位、第1位置0。可用AND指令,若要使某位变0则让其和“0”相与,其余和“1”相与</p>
<p>MOV AL, 0BFH BFH --- 10111111</p>
<p>ADD AL, 0FCHADD ∴ 11111100 --- FCH </p>
<p>∴ (AL) = 0BCH 期望结果 10111100 --- BCH</p>
<p> </p>
<p>习题2:要求第5位置1。</p>
<p> 解析:可用OR指令,若要使某位变1则让其和“1”相或,其余和“0”相或</p>
<p>MOV AX 43H01000001</p>
<p> OR AX 20H OR 00100000 </p>
<p>∴ (AL) = 63H01100001</p>
<p> </p>
<p>习题3:如要测试AL寄存器中第2位 是否为1,如为1则转移到EXIT去执行。</p>
<p> 解析:要测试操作数的某位是否为1,则可先把该操作数求反,然后用TEST指令测试。</p>
<p> MOV DL,AL</p>
<p> NOT DL ;取反</p>
<p> TEST DL,00000100B ;测试第2位是否为1</p>
<p> JE EXIT </p>
<p> </p>
<p><strong>一般移位指令</strong></p>
<p> 如果移位数m=1,可以直接跟在操作指令后(如:SHL AL, 1)</p>
<p> 如果位移数m>1,必须先将m存放在CL寄存器中(如:MOV CL, m)</p>
<p>(1)算术左移或逻辑左移指令SAL/SHL(Shift Arithmetic Letf / Shift logic Left)</p>
<p> 格式:SAL OPRD,m / SHL OPRD,m</p>
<p> 算术左移SAL/逻辑左移SHL指令把操作数OPRD左移m ,每移动一位,右边用0补足一位,移出的最高位进入标志位CF。</p>
<p> 只要左移以后的结果未超出一个字节或一个字的表达范围,那么每左移一次,原操作数每一位的权增加了一倍,也即相当于原数乘2。</p>
<p>逻辑左移SHL1位 → 无符号数 * 2</p>
<p>算术左移SHL1位 → 有符号数 * 2</p>
<p> </p>
<p> 例1:MOV AL,8CH ;8CH -- 10001100B </p>
<p> SHL AL,1 ;左移1位00011000B,AL=18H。CF=1,PF=1,ZF=0,SF=0,OF=1</p>
<p> MOV CL,6 ;CL=6。如果移位是1可以直接写SHL AL,1。大于1都要先传送到CL</p>
<p> SHL AL,CL ;AL左移6位,AL=0。CF=0,PF=1,ZF=1,SF=0,OF=0 </p>
<p> OF 移位次数为1时才有效,左移前后最高位是否发生改变。若改变则OF = 1;否则OF = 0.</p>
<p> </p>
<p> 习题:实现把寄存器AL中的内容(设为无符号数)乘10,结果存放在AX中。</p>
<p>XOR AH,AH ;(AX)=0 因为是AL寄存器,将AH清零</p>
<p>SHL AL,1 ;2X</p>
<p>MOV BX,AX ;暂存2X</p>
<p>SHL AX,1 ;4X</p>
<p>SHL AX,1 ;8X</p>
<p>ADD AX,BX ;8X+2X</p>
<p> </p>
<p>(2)算术右移指令SAR(Shift Arithmetic Right)</p>
<p> 格式: SAR OPRD,m // 算术右移一位相当于自身除以2</p>
<p> 该指令使操作数右移m位,同时每移一位,左边的符号位保持不变,移出的最低位进入标志位CF。</p>
<p> 算术右移指令SAR看最高有效位。若最高有效位为1,则右移补1。</p>
<p> 例1:MOV CL , 5</p>
<p> SAR [ DI ] , CL</p>
<p> 如指令执行前: ( DS )=0F800H, (DI)=180AH, (0F980A)=0064H</p>
<p> 解:物理地址 = (DS) + (DI) = 0F980AH 对 0F980A 右移5位</p>
<p> 指令执行后: (0F980A)=0003H,CF=0</p>
<p> </p>
<p> 例2:MOV DH, 0B9H MOV CL, 3 SAR DH, CL 执行后(DH)=0F7H</p>
<p> B9H --- 10111001B </p>
<p> 右移3位 --- 11110111B -- 0F7H</p>
<p> </p>
<p>(3)逻辑右移指令SHR(Shift logic Right)</p>
<p>逻辑右移指令的格式如下:</p>
<p>格式: SHR OPRD,m // 对于无符号数而言,逻辑右移一位相当于除以2。</p>
<p>该指令使操作数右移m位,同时每移一位,左边用0补足,移出的最低位进入标志位CF。</p>
<p> </p>
<p>例:假设DATA1和DATA2各长4位,分别存放在AL寄存器的低4位和高4位中,现要把它们分别存放到BL寄存器和BH寄存器的低4位中。</p>
<p>解析:(AL) =DATA2DATA1</p>
<p>MOV BL,AL</p>
<p>AND BL,0FH ;低4位和“1”相与,得DATA1</p>
<p>MOV BH,AL</p>
<p>MOV CL,4</p>
<p>SHR BH,CL ;逻辑右移4位(无符号数),得DATA2</p>
<p> </p>
<p><strong>循环移位指令 </strong>只影响标志CF和OF</p>
<p>格式:</p>
<p><strong>ROL OPRD</strong><strong>,m</strong>;循环左移</p>
<p><strong>ROR OPRD</strong><strong>,m</strong>;循环右移</p>
<p><strong>RCL OPRD</strong><strong>,m</strong>;带进位循环左移</p>
<p><strong>RCR OPRD</strong><strong>,m</strong>;带进位循环右移</p>
<p>操作数OPRD可以是通用寄存器,可以是存储器操作数。</p>
<p>循环左移ROL:每移位一次操作数左移,最高位进入最低位,CF即最低位。</p>
<p>循环右移ROR:每移位一次操作数右移,最低位进入最高位,CF即最高位。</p>
<p>RCL:CF移入最高位参与运算(共9位),每移位一次操作数左移,最高位进入最低位,CF即最高位。</p>
<p>RCR:CF移入最低位参与运算(共9位),每移位一次操作数右移,最低位进入最高位,CF即最低位。</p>
<p> </p>
<p>例:MOV AL, 34H MOV CL, 3</p>
<p>(1)ROL AL, CL;执行命令后(AL) = 0A1H</p>
<p>(2)ROR AL, CL;执行命令后(AL) = 86H</p>
<p>(3)RCL AL, CL;设CF = 1。执行命令后(AL) =1DH</p>
<p>(4)RCR AL, CL;设CF = 1。执行命令后(AL) =4DH,CF = 1</p>
<p><strong>34H --------- 00110100B </strong> </p>
<p><strong>ROL --------- 10100001B </strong>-- 循环左移3位后:0A1H,CF=1</p>
<p><strong>ROR --------- 10000110B</strong> -- 循环右移3位后:86H,CF=1</p>
<p><strong>RCL</strong><strong>移动前 --- 101000011B </strong>-- CF加入最高位参与运算</p>
<p><strong>RCL</strong><strong>移动后 ----000011101B </strong>-- 带进位循环左移3位后:1DH,CF = 0</p>
<p><strong>RCR</strong><strong>移动前 --- 001101001B</strong> -- CF加入最低位参与运算</p>
<p><strong>RCR</strong><strong>移动后 ----010011010B</strong> -- 带进位循环右移3位后:4DH,CF = 0</p>
<p> </p>
<p>习题1:(AX)=0012H, (BX)=0034H,要求把它们装配在一起形成(AX)=1234H</p>
<p>MOV CL, 8 ;注意是16位寄存器</p>
<p>ROL AX, CL</p>
<p>AND AX, BX</p>
<p> </p>
<p>习题2:试分析下面的程序段完成什么功能。</p>
<p> MOV CL ,4 ;(CL)= 4</p>
<p> SHL DX ,CL ;DX逻辑左移4位</p>
<p> MOV BL , AH ;(BL) = (AH) BX低8位等于AX高8位</p>
<p> SHL AX , CL ;AX逻辑左移4位</p>
<p> SHR BL , CL ;BL逻辑右移4位</p>
<p> OR DL , BL ;</p>
<p>DX:8765 -- 左移4位7650 --- OR DL, BL (DL) = 54 (DX)=7654</p>
<p>AX:4321 -- 左移4位3210</p>
<p>BL:BL= AX = 43 ---- 右移4位04</p>
<p>该程序功能:把AX,DX中双字左移4位</p>
<p> </p>
<p>习题3:现有程序的如下:</p>
<p>XOR AX, AX ;(AX) = 0,CF = 0</p>
<p>MOV AX, 6C5AH ;(AX) = 6C5AH,(AH) = 6CH,(AL) = 5AH </p>
<p>MOV CX, 0203H ;(CX) = 0203H,(CH) = 02H,(CL) = 03H </p>
<p>RCL AH, CL ;(CL) = 3, CF= 0,AH带位左循环位移3位。(AH) = 61H,CF= 1</p>
<p>XCHG CH,CL ;CH、CL交换,(CH) = 03H,(CL) = 02H </p>
<p>RCR AL,CL ;(CL) = 2, CF= 0,AL带位右循环位移2位。(AL) = 56H,CF= 1</p>
<p>HLT ;停机</p>
<p>求(AX) = 6156H ,(CF)= 1 ,(CX)= 0302H 。</p>
<p> </p>
<p><strong>转移指令</strong></p>
<p>1. 无条件转移指令</p>
<p> ① 无条件段内直接转移指令</p>
<p> 格式:JMP 标号;该指令使控制无条件地转移到标号地址处</p>
<p> 把指令中的地址差加到指令指针IP上,使IP之内容为目标地址,从而达到转移的目的。</p>
<p> 例: </p>
<p>NEXT: MOV AX,CX</p>
<p>……</p>
<p>JMP NEXT ;转NEXT处</p>
<p>……</p>
<p>JMP OVER ;转OVER处</p>
<p>……</p>
<p>OVER: MOV AX,1</p>
<p> </p>
<p> ② 无条件段内间接转移指令</p>
<p> 格式:JMP OPRD;使控制无条件地转移到操作数由OPRD的内容给定的目标地址</p>
<p> 操作数OPRD可以是通用寄存器,也可以是字存储单元。</p>
<p> 例: JMP WORD PTR ;</p>
<p> </p>
<p> ③ 无条件段间直接转移指令</p>
<p> 格式:JMP FAR PTR 标号;把指令中包含的目标地址的段值和偏移分别置入CS和IP</p>
<p> 标号前的符号 “FAR PTR”向汇编程序说明这是段间转移。</p>
<p> 例:JMP FAR PTR EXIT ;EXIT是定义在另一个代码段中的标号</p>
<p> </p>
<p> ④ 无条件段间间接转移指令</p>
<p> 格式:JMP OPRD;操作数OPRD必须是双字存储单元。</p>
<p> 该指令使控制无条件地转移到由操作数OPRD的内容给定的目标地址处。</p>
<p> 例:JMP DWORD PTR ;双字存储单元的低字内容送IP,高字内容送CS </p>
<p> </p>
<p>习题: (IP)=2BC0H,(CS)=0200H,位移量D=5119H,(BX)=1200H,(DS)= 212AH,(224A0)=0600H,(275B9)=098AH,试为以下的转移指令找出转移的偏移地址。</p>
<p>(1)段内直接寻址</p>
<p>(2)使用BX及寄存器间接寻址方式的段内间接寻址</p>
<p>(3)使用BX及寄存器相对寻址方式的段内间接寻址</p>
<p> 解: (1)JMP D</p>
<p> 偏移地址 = D + IP = 5119H + 2BC0H = 7CD9H </p>
<p> (2)JMP BX </p>
<p>(16d×(DS)+(BX))= 212A0 + 1200 =(224A0)= 0600H</p>
<p> (3)JMP [ BX+D] </p>
<p>(16d ×(DS)+(BX)+D)= 212A0 + 1200 + 5119 = 275B9 = 098AH</p>
<p> </p>
<p>2. 条件转移指令 不影响标志</p>
<p>有符号数间的次序关系称为:大于(G)、等于(E)、小于(L);</p>
<p>无符号数间的次序关系称为:高于(A)、等于(E)、低于(B)。</p>
<p>无符号数和有符号数,两数是否相等可由ZF标志的反映。</p>
<p>进位标志CF反映两个无符号比较后的大小关系。</p>
<p>两个有符号数比较后的大小关系,由符号标志SF和溢出标志OF一起来反映。</p>
<p>例1:下面的程序测试AX的低四位是否全是0,如果均是0,那么使CX=0,否则使CX=-1</p>
<p>MOV CX,-1 ;先使CX=-1</p>
<p>TEST AX,0FH ;测试AX的低4位</p>
<p>JNZ NZERO ;不全为0则转移</p>
<p> MOV CX,0 ;全为0时使CX=0 </p>
<p> NZERO:……</p>
<p>例2:设要比较的两个不相等的有符号数a和b,分别存放在寄存器AX和BX中,</p>
<p>执行指令“CMP AX,BX”后,标志SF及OF的设置情况和两数的大小情况如下:</p>
<p>当没有溢出(OF=0)时,若SF=0,则a>b;若SF=1,则a<b</p>
<p>当产生溢出(OF=1)时,若SF=0,则a<b;若SF=1,则a>b</p>
<p> </p>
<p>习题1:设X、Y均为存放在X和Y单元中的16位操作数,先判X >50否,如满足条件则转移到</p>
<p>TOO—HIGH去执行,然后做X-Y,如溢出则转移到OVER去执行,否则计算|X-Y|,并把结果存入RESULT中。</p>
<p>MOV AX, X</p>
<p>MOV BX, 50</p>
<p>CMP AX, BX ;判断X > 50?</p>
<p>JG TOO—HIGH ;如果X > 50则跳转TOO—HIGH</p>
<p>SUB AX, BX ;X-Y</p>
<p>JO OVER ;如果溢出(OF=1)则跳转OVER</p>
<p>JNS NONEG ;X - Y 为正转移到NONE</p>
<p>NEG AX ;AX取补:0-AX</p>
<p>NONEG:MOV RESULT,AX</p>
<p>TOO—HIGH:……</p>
<p>OVER:……</p>
<p> </p>
<p>习题2:假设有100个16位无符号数存放在从1234:5678H开始的内存中,现需要求它们的和。</p>
<p> 设把32位的和保存在DX(高位)和AX寄存器中。</p>
<p> MOV AX,1234H ;不能直接将立即数传送到段寄存器</p>
<p> MOV DS,AX ;置数据段寄存器值</p>
<p> MOV SI,5678H ;置指针初值</p>
<p> MOV AX,0 ;清32位累加和</p>
<p> MOV DX,AX</p>
<p> MOV CX,100 ;置数据个数计数器</p>
<p>NEXT: ADD AX, ;求和</p>
<p> ADC DX,0 ;加上可能的进位</p>
<p> INC SI ;调整指针</p>
<p> INC SI</p>
<p> DEC CX ;计数器减1</p>
<p> JNZ NEXT ;如果不为0,那么就继续累加下一个数据</p>
<p> </p>
<p><strong>循环指令</strong> 不影响各标志位</p>
<p>(1)计数循环指令LOOP </p>
<p> 格式: LOOP 标号 </p>
<p>指令使寄存器CX的值减1,如果结果不等于0,则转移到标号,否则顺序执行;</p>
<p>该指令等同于如下的两条指令: DEC CX</p>
<p> JNZ 标号</p>
<p>通常在利用LOOP指令构成循环时,先要设置好计数器CX的初值,即循环次数。由于首先进行CX寄存器减1 操作,再判结果是否为0,所以最多可循环65536次。</p>
<p>例:如下程序片段实现把从偏移1000H开始的512个字节的数据复制到从偏移3000H开 始的缓冲区中(假设在当前数据段中进行移动)</p>
<p> MOV S1,1000H ;置源指针</p>
<p> MOV DI,3000H ;置目标指针</p>
<p> MOV CX,512 ;置计数初值 </p>
<p>NEXT: MOV AL,[ SI ]</p>
<p> INC SI</p>
<p> MOV [ DI ],AL</p>
<p> INC DI</p>
<p> LOOP NEXT ;控制循环</p>
<p> </p>
<p>(2)等于/全零循环指令LOOPE/LOOPZ</p>
<p>格式:LOOPE 标号 ;等于 / LOOPZ 标号 ;全零</p>
<p>指令使寄存器CX的值减1,当为0或相等时(且ZF=1),那么则转移到标号,否则顺序执行。</p>
<p>例:字符串中查找第一个非‘A’字符。设字符串长度已保存在CX中,并且DS:DI 指向字符串。如果找到,那么使BX指向该非‘A’字符,如果找不到,那么使BX=0FFFFH。</p>
<p>MOV AL,‘A’</p>
<p>DEC DI</p>
<p>NEXT: INC DI</p>
<p>CMP AL,</p>
<p>LOOPE NEXT</p>
<p>MOV BX,DI</p>
<p>JNE OK</p>
<p>MOV BX,-1 </p>
<p>OK: ……</p>
<p> </p>
<p>(3)不等于/非零循环LOOPNE/LOOPNZ</p>
<p>格式:LOOPNE 标号 ;不等于 / LOOPNZ 标号 ;非零</p>
<p>指令使寄存器CX的值减1,如果结果不为0不相等时,并且零标志ZF等于0,那么则转移到标号,否则顺序执行。(CX -1 != 0 且 ZF = 0)</p>
<p> </p>
<p>(4)跳转指令JCXZ </p>
<p>格式: JCXZ 标号 ;CX = 0 则跳转标号,否则顺序执行</p>
<p> </p>
<p>通常该指令用在循环开始前,以便在循环次数为0时,跳过循环体。</p>
<p>例如: ……</p>
<p>JCXZ OK ;如果循环计数为0,就跳过循环</p>
<p>NEXT: …… ;循环体</p>
<p>……</p>
<p>LOOP NEXT ;根据计数控制循环</p>
<p>OK: ……</p>
<p> </p>
<p> </p>
<p>习题1:有一串L字符的字符串存储于首地址为TABLE 的存储器中。如要求在字符串中查找“空格”字符,找到则继续执行,如未找到则转到NOT-FOUND去执行,编制此程序。</p>
<p> MOV CX, L ;将字符串长度L传送给CX</p>
<p> MOV SI,-1 ;使SI = -1,后面比较时将从0 开始比较</p>
<p> MOV AL,20H ;AL表示空格,20H是空格的ASCII码,可写成AL, ' '</p>
<p>NEXT: INC SI ;SI加一 ,第一次为0</p>
<p> CMP AL,TABLE [ SI ]</p>
<p> LOOPNE NEXT ;CX!=0或CMP不相等则继续NEXT循环</p>
<p> JNZ NOT-FOUND ;CX = 0,跳转NOT-FOUND</p>
<p> ……</p>
<p>NOT-FOUND:</p>
<p> …… </p>
<p> </p>
<p>习题2:若自BLOCK开始的内存缓冲区中有100个字节带符号数,要找出其中最大值,把它存放到MAX单元中。</p>
<p>MOV BX,OFFSET BLOCK ;把BLOCK偏移地址送给BX</p>
<p>MOV AX, ;取出来第一个数送给AX</p>
<p>INC BX ;BX = BX+1</p>
<p>MOV CX,99 ;</p>
<p>AGAIN:CMP AX, ;BX 与BX+1相比较</p>
<p> JG NEXT ;AX大于</p>
<p> MOV AX, ;</p>
<p>NEXT : INC BX</p>
<p> LOOP AGAIN</p>
<p> MOV MAX,AX</p>
<p> </p>
<p>习题3:已知存储器中有一个首地址为ARRAY的100个字数组,现要求把数组中的每个数加1(不考虑溢出的可能性),试编制完成此功能的程序段。</p>
<p> MOV CX,100 ;100个字数组,循环100次</p>
<p> LEA BX,ARRAY ;MOV BX,OFFSET ARRAY同理</p>
<p>INCR: INC ;BX内容+1</p>
<p> ADD BX,2 ;BX指针+2</p>
<p> LOOP INCR</p>
<p> </p>
<p><strong>第六章:掌握字符串操作、BCD码的加减法指令</strong></p>
<p>组合BCD码的算术运算调整指令</p>
<p>1、组合的BCD码加法调整指令DAA(Decimal Adjust for Addition)</p>
<p>格式:DAA;该指令必须在加法操作后执行</p>
<p>这条指令对在AL中的和(由两个组合的BCD码相加后的结果)进行调整</p>
<p>调整方法如下:</p>
<p>(1)如AL中的低4位在A~F之间,或AF为1,则AL←(AL)+6,且使AF=1;</p>
<p>(2)如AL中的高4位在A~F之间,或CF为1,则AL←(AL)+60H,且使CF=1。</p>
<p>该指令影响标志AF,CF,PF,SF和ZF,但不影响标志OF。</p>
<p>例1:</p>
<p>MOV AL,34H</p>
<p>ADD AL,47H ;AL = 34H + 47H = 7BH,AF=0,CF=0</p>
<p>DAA ;AL = 7BH + 06H = 81H,AF=1,CF=0</p>
<p>ADC AL,87H ;AL = 81H + 87H = 08H,AF=0,CF=1</p>
<p>DAA ;AL = 08H + 60H = 68H,AF=0,CF=1</p>
<p>ADC AL,79H ;AL = 68H + 79H = 0E1H,AF=1,CF=0</p>
<p>DAA ;AL = 0E1H + 60H + 06H = 47H,AF=1,CF=1</p>
<p> </p>
<p>例2: (BCD3)←(BCD1)+(BCD2)</p>
<p>设(BCD1)=34H,(BCD+1)=18H,(BCD2)=89H,(BCD2+1)=27H。指令如下:</p>
<p>MOV AL,BCD1 ;AL = 34H</p>
<p>ADD AL,BCD2 ;AL = 34H + 89H = 0BDH,AF=0,CF=0</p>
<p>DAA ;AL = 0BDH + 60H + 06H = 23H,AF=1,CF=1</p>
<p>MOV BCD3,AL ;(BCD3) = 23H</p>
<p>MOV AL,BCD1+1 ;AL = 18H</p>
<p>ADC AL,BCD2+1 ;AL = 18H + 27H = 3FH,AF=0,CF=0</p>
<p>DAA ;AL = 3FH + 06H = 46H,AF=1,CF=0</p>
<p>MOV BCD3+1,AL ;(BCD3+1) = 46H</p>
<p>∴ (BCD3)= 4623H AL=46H,CF=0,AF=1</p>
<p> </p>
<p>2、组合的BCD码减法调整指令DAS</p>
<p>格式:DAS;该指令必须在减法操作后执行</p>
<p>这条指令对在AL中的差(由两个组合的BCD码相减后的结果)进行调整,产生一个组合的BCD码</p>
<p>调整方法如下:</p>
<p>(1)如AL中的低4位在A~F之间,或AF为1,则AL←(AL)- 6,且使AF=1; </p>
<p>(2)如AL中的高4位在A~F之间,或CF为1,则AL←(AL)- 60H,且使CF=1。</p>
<p>该指令影响标志AF,CF,PF,SF和ZF,但不影响标志OF。</p>
<p>例1:</p>
<p>MOV AL,45H ;AL = 45H</p>
<p>SUB AL,27H ;AL= 45H - 27H = 1EH,AF=1,CF=0</p>
<p>DAS ;AL = 1EH - 06H = 18H,AF=1,CF=0</p>
<p>SBB AL,49H ;AL = 18H - 49H = 18H + B7H = 0CFH,AF=1,CF=1</p>
<p>DAS ;AL= 0CF - 60H - 06H = 69H,AF=1,CF=1 </p>
<p> </p>
<p>例2;(BCD1)=1234,(BCD2)=4612,试写出指令完成(BCD3)←(BCD1)-(BCD2)</p>
<p>MOV AL,BCD1 ;AL = 34H</p>
<p>SUB AL,BCD2 ;AL = 34H - 12H = 22H,CF=0,AF=0</p>
<p>DAS ;AL = 22H</p>
<p>MOV BCD3,AL ;(BCD3) = 22H</p>
<p>MOV AL,BCD1+1 ;AL = 12H</p>
<p>SBB AL,BCD2+1 ;AL = 12H - 46H = 12H + 0BAH = 0CCH,CF=0,AF=0</p>
<p>DAS ;AL = 0CCH - 60H - 06H = 66H,CF=1,AF=1</p>
<p>MOV BCD3+1,AL ;(BCD3+1) = 66H</p>
<p>∴ (BCD3)= 6622H,CF=1,AF=1</p>
<p> </p>
<p>未组合BCD码的算术运算调整指令</p>
<p>1、未组合的BCD码加法调整指令AAA</p>
<p>格式:AAA;该指令必须在加法操作后执行</p>
<p>这条指令对在AL中的和(由两个未组合的BCD码相加后的结果)进行调整,产生一个未组合</p>
<p>的BCD码。调整方法如下:</p>
<p>( 1) 如AL中的低4位在0~9之间,且AF为0,则转(3);</p>
<p>( 2) 如AL中的低4位在A~F之间,或AF为1,则AL = (AL) + 6,AH = (AH) + 1,且AF位置1</p>
<p>( 3 ) 清除AL的高4位;</p>
<p>( 4 ) AF位的值送CF位。</p>
<p>该指令影响标志AF和CF,对其他标志均无定义。</p>
<p>例1:</p>
<p>MOV AX,7 ;AX = 0007H</p>
<p>ADD AL,6 ;AL = 07H+ 06H = 0DH,AF=0,CF=0</p>
<p>AAA ;AL = 0DH+ 06H = 13H,AL=03H,AH = 01H,AF=1,CF=1</p>
<p>ADC AL,5 ;AL = 03H + 05H + CF = 09H,AH=01H,AF=0,CF=0</p>
<p>AAA ;AL = 09H,AH=01H,AF=0,CF=0</p>
<p>ADD AL,39H ;AL = 09H + 39H = 42H,AH=01H,AF=1,CF=0</p>
<p>AAA ;AL = 42H + 06H = 48H,AL = 08H,AH=02H,AF=1,CF=1</p>
<p> </p>
<p>2、未组合的BCD码减法调整指令的ASS</p>
<p>格式:AAS;该指令必须在减法操作后执行</p>
<p>这条指令对在AL中的差(由两个未组合的BCD码相减后的结果)进行调整,产生一个未组合</p>
<p>的BCD码。调整方法如下:</p>
<p>(1) 如AL中的低4位在0~9之间,且AF为0,则转(3)</p>
<p>(2) 如AL中的低4位在A~F之间,或AF为1,则AL←(AL)- 6,AH←(AH)- 1,且AF位置1;</p>
<p>(3) 清除AL的高4位</p>
<p>(4) AF位的值送CF位。</p>
<p>该指令影响标志AF和CF,对其他标志均无定义。</p>
<p>例1:</p>
<p>MOV AL,34H ;AL = 34H</p>
<p>SUB AL,09H ;AL = 34H + 09H = 2BH,AF=1,CF=0</p>
<p>AAS ;AL = 2BH - 06H = 25H,AL = 05H,AF=1,CF=1 </p>
<p> </p>
<p>3、未组合的BCD码乘法调整指令AAM</p>
<p>格式:AAM;该指令必须在乘法操作后执行</p>
<p>这条指令对在AL中的积(由两个组合的BCD码相乘的结果)进行调整,产生两个未组合的BCD码 。调整方法如下:</p>
<p>(1)AL = AL % 10 (余)</p>
<p>(2)AH = AL / 10 (商)</p>
<p>该指令影响标志SF,ZF和PF,对其他标志无影响。</p>
<p>例:</p>
<p>MOV AL,03H ;AL = 03H</p>
<p>MOV BL,04H ;AL = 04H</p>
<p>MUL BL ;AL = 03H × 04H = 0CH,AH=00H</p>
<p>AAM ;AL = 0CH % 10H = 02H,AH = 0CH / 10H = 01H</p>
<p> </p>
<p>4、未组合的BCD码除法调整指令AAD</p>
<p>格式:AAD;该指令前必须在除法操作前执行</p>
<p>这条指令把存放在寄存器AH(高位十进制数)及存放在寄存器AL中的两位非组合BCD码,</p>
<p>调整为一个二进制数,存放在寄存器AL中。调整的方法如下: </p>
<p>(1)AL = AH × 10 + (AL)</p>
<p>(2)AH = 0</p>
<p>该指令影响标志SF,ZF和PF,对其他标志无影响 。</p>
<p>例:</p>
<p>MOV AH, 04H ;AH = 04H</p>
<p>MOV AL, 03H ;AL = 03H</p>
<p>MOV BL, 08H ;BL = 08H</p>
<p>AAD ;AL= 04H × 10 + 03H = 43D = 2BH , AH=00H</p>
<p>DIV BL ;AL= 2BH / 08H = 05H , AH = 2BH % 08H = 03H</p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p><br><br>
来源:https://www.cnblogs.com/trepverter/p/11890322.html
頁:
[1]