汇编语言程序设计钱晓捷第五版期末复习参考
汇编语言程序设计钱晓捷第五版期末复习参考
第一章:汇编语言基础知识
1.1 8086的寄存器
处理器内部需要高速存储单元,用于暂时存放程序执行过程中的代码和数据,这些存储单元被称为寄存器(Register)。
通用寄存器:在处理器中数量较多、使用频率较高,具有多种用途。例如,它们可用来存放指令需要的操作数据,可用来存放地址以便在主存或I/O接口中指定操作数据的位置。
专用寄存器:只用于特定目的。例如,8086的指令指针寄存器IP只用于记录将要执行指令的主存地址,标志寄存器保存指令执行的辅助信息。
8086的寄存器组分成8个通用寄存器(AX累加器、BX基址寄存器、CX计数器、DX数据寄存器、SI源地址寄存器、DI目的地址寄存器、BP基址指针、SP堆栈指针)、4个段寄存器(CS代码段寄存器、SS堆栈段寄存器、DS数据段寄存器、ES附加段寄存器)、1个标志寄存器(FLAGS)和1个指令指针寄存器(IP),它们均为16位。
1.2 8086的寻址方式
(1)立即数寻址方式
在立即数寻址方式下,指令中的操作数直接存放在机器码中,紧跟在操作码之后。立即数寻址方式常用来给寄存器或存储单元赋值。
MOV AL, 05H //功能:AL ← 05H,机器代码为B0 05
MOV AX, 0102H //功能:AX ← 0102H,机器代码为B8 02 01
(2)寄存器寻址方式
寄存器寻址方式的操作数存放在CPU的内部寄存器REG中,可以是8位寄存器R8(AH、AL、BH、BL、CH、CL、DH、DL)或者16位寄存器R16(AX、BX、CX、DX、SI、DI、BP、SP)。另外,操作数可以存放在4个段寄存器SEG(CS、DS、SS、ES)中。
MOV AX, 1234H //目的操作数采用寄存器寻址,源操作数为立即数寻址AX ← 1234H
MOV BX, AX //两个操作数均为寄存器寻址,BX ← AX
执行上述两条指令之后,结果是BX = 1234H。
(3)直接寻址方式
在直接寻址方式下,指令中直接包含了有效地址。
MOV AX, [2000H] //AX ← DS:[2000H]
该指令中给定了有效地址2000H,它不是存储器的物理地址。在默认情况下,有效地址要与数据段寄存器DS一起构成操作数所在存储单元的物理地址。在汇编语言中,用[]表示存储单元的内容。
该例指令的执行结果是将DS:[2000H]单元的内容传送至AX寄存器。
数据不仅可以存放于数据段中,也可以根据需要存放于附加段、代码段或堆栈段中,这时指令中应指明段超越前缀,例如:
MOV AX, ES:[2000H] //AX ← ES:[2000H]
(4)寄存器间接寻址方式
在这种寻址方式中,有效地址存放在寄存器中,8086中寄存器只能是基址寄存器BX或变址寄存器SI、DI中。其默认的段地址在DS段寄存器中,但可使用段超越前缀改变。例如:
MOV AX, [SI] //AX ← DS:[SI]
该指令中有效地址存放于SI寄存器中,操作数则存放在数据段主存单元中。假设SI内容设置为2000H,则该指令等同于MOV AX, [2000H]。
(5)寄存器相对寻址方式
在寄存器相对寻址方式下,有效地址是寄存器内容与有符号8位或16位位移量之和,寄存器可以是BX、BP或SI、DI。操作数的EA = BX/BP/SI/DI + 8/16位位移量。其中,BX、SI、DI寄存器默认数据段DS,BP寄存器默认堆栈段SS。当使用非默认段时,可用段超越前缀。
该指令中有效地址存放于SI寄存器中,操作数则存放在数据段主存单元中。假设SI内容设置为2000H,则该指令等同于MOV AX, [2000H]。
(5)寄存器相对寻址方式
在寄存器相对寻址方式下,有效地址是寄存器内容与有符号8位或16位位移量之和,寄存器可以是BX、BP或SI、DI。操作数的EA = BX/BP/SI/DI + 8/16位位移量。其中,BX、SI、DI寄存器默认数据段DS,BP寄存器默认堆栈段SS。当使用非默认段时,可用段超越前缀。
MOV AX, [DI + 06H] //AX ← DS:[DI + 06H]
MOV AX, [BP + 06H] //AX ← SS:[BP + 06H]
MOV AX, [BP] //等同于MOV AX, [BP + 0H]
MOV AX, [SI + i] //i是事先定义的变量或常量
MOV AX, i[SI] //等同于MOV AX, [SI + i]
(6)基址变址寻址方式
基址变址寻址方式是把一个基址寄存器(BX或BP)的内容加上变址寄存器(SI或DI)的内容构成有效地址EA。这样,操作数的EA = BX/BP + SI/DI。若基址寄存器使用BX,其默认段为数据段DS,若基址寄存器使用BP,其默认段为堆栈段SS。
MOV AX, [BX + SI] //AX ← DS:[BX + SI]
MOV AX, [BP + DI] //AX ← SS:[BP + DI]
MOV AX, DS:[BP + DI] //AX ← DS:[BP + DI]
MOV AX, [BX][SI] //等同于MOV AX, [BX + SI]
(7)相对基址变址寻址方式
相对基址变址寻址方式也使用基址寄存器(BX/BP)和变址寄存器(SI/DI),还在指令中指定一个8位或16位的位移量,这三者之和构成操作数的有效地址EA,即EA = BX/BP + SI/DI + 8/16位位移量。
MOV AX, [BX + SI + 06H] //AX ← DS:[BX + SI + 06H]
MOV AX, [BX + SI + i] //i是事先定义的变量或常量
MOV AX, i[BX][SI] //等同于MOV AX, [BX + SI + i]和MOV AX, i[BX + SI]
第二章:8086的指令系统
'Intel 8086指令系统可分为6类:数据传送类指令,算术运算类指令,位操作类指令,控制转移类指令,串操作类指令,处理机控制类指令。
2.1 数据传送类指令
2.1.1 通用数据传送指令
(1)传送指令MOV
MOV DEST, SRC //DEST ← SRC
MOV指令把1字节或字的操作数从源地址SRC传送至目的地址DEST。源操作数可以是立即数、寄存器或主存单元,目的操作数可以是寄存器或主存单元,但不能是立即数。立即数传送例子:
MOV AL, 4 //AL ← 4,字节传送
MOV CX, 0FFH //CX ← 00FFH,字传送
MOV SI, 200H //SI ← 0200H,字传送
MOV BYTE PTR[SI], 0AH //DS:[SI] ← 0AH,BYTE PTR说明是字节操作
MOV WORD PTR[SI + 2], 0BH //DS:[SI + 2] ← 0BH,WORD PTR说明是字操作
在包括传送指令的绝大多数双操作数指令中(除非特别说明),目的操作数与源操作数必须类型一致,或者同为字,或者同为字节,否则为非法指令。例如:
MOV AL, 050AH //非法指令:050AH为字,而AL为字节
8086不允许立即数传送至段寄存器,例如:
MOV DS, 100H //非法指令:不允许立即数至段寄存器的传送
寄存器传送例子:
MOV AX, BX
MOV AH, AL
MOV DS, AX
MOV [BX], AL
存储器传送例子:
MOV AL, [BX]
MOV DX, [BP]
MOV ES, [SI]
8086指令系统除串操作类指令外,不允许两个操作数都是存储单元,所以没有主存至主存的数据传送,要实现这种传送可通过寄存器间接实现。
例如将buffer1单元的数据传送至buffer2单元,buffer1和buffer2是两个字变量:
MOV AX, buffer1
MOV buffer2, AX
不能向CS段传送数据,因为改变CS值将导致程序执行混乱
MOV CS, [SI] //非法指令
段寄存器传送例子:
MOV [SI], DS
MOV AX, ES
MOV DS, AX
不允许段寄存器之间的直接数据传送,例如:
MOV DS, ES //非法指令:不允许seg ← seg传送
(2)交换指令XCHG
交换指令用来将源操作数和目的操作数内容交换,例如:
MOV AX, 1234H //AX = 1234H
MOV BX, 5678H //BX = 5678H
XCHG AX, BX //AX = 5678H, BX = 1234H
XCHG AH, AL //AX = 7856H
XCHG AX, [2000H] //等同于XCHG [2000H], AX
XCHG AL, [2000H] //等同于XCHG [2000H], AL
(3)换码指令XLAT
换码指令用于将BX指定的缓冲区中,AL指定的位移处的数据取出赋值给AL,即AL ← DS:[BX + AL]。
例如将首地址为100H的表格缓冲区的3号数据取出:
MOV BX, 100H
MOV AL, 03H
XLAT
2.1.2 堆栈操作指令
(1)进栈指令PUSH
进栈指令先使堆栈指针SP减2,然后把一个字操作数存入堆栈顶部。堆栈操作的对象只能是字操作数,进栈时,低字节存放于低地址,高字节存放在高地址,SP相应向低地址移动2字节单元。
例如将7812H压入堆栈:
MOV AX, 7812H
PUSH AX
将主存单元DS:[2000H]的一个字压入堆栈:
PUSH [2000H]
(2)出栈指令POP
出栈指令把栈顶的一个字传送至指定的目的操作数,然后堆栈指针SP加2。目的操作数应为字操作数,字从栈顶弹出时,低地址字节送低字节,高地址字节送高字节。
例如将栈顶的一个字的内容弹出送入AX寄存器:
POP AX
将栈顶一个字送入主存DS:[2000H]
POP [2000H]
2.1.3 标志传送指令
(1)标志寄存器传送
标志寄存器传送指令用来传送标志寄存器的内容,包括LAHF/SAHF、PUSHF/POPF指令。
①标志送AH指令LAHF
LAHF指令将标志寄存器FLAGS的低字节送寄存器AH,即状态标志位SF/ZF/AF/PF/CF分别送入AH的第7/6/4/2/0位,而AH的第5/3/1位任意。
LAHF //AH ← FLAGS的低字节
②AH送标志指令SAHF
SAHF将AH寄存器内容送FLAGS的低字节,即SAHF和LAHF是一对功能相反的指令,它们只影响标志寄存器的低8位,而对高8位无影响。
SAHF //FLAGS的低字节 ← AH
③标志进栈指令PUSHF
PUSHF指令将标志寄存器的内容压入堆栈,同时栈顶指针SP减2。这条指令可用来保存全部标志位。
PUSHF
④标志出栈指令POPF
POPF指令将栈顶字单元内容送标志寄存器,同时栈顶指针SP加2.
POPF
(2)标志位操作
标志位操作指令可用来对CF、DF和IF三个标志位进行设置,除影响其所设置的标志外,均不影响其他标志。
CLC //复位进位标志:CF ← 0
STC //置位进位标志:CF ← 1
CMC //求反进位标志:CF ← ~CF
CLD //复位方向标志:DF ← 0
STD //置位方向标志:DF ← 1
CLI //复位中断标志:IF ← 0
STI //置位中断标志:IF ← 1
2.1.4 地址传送指令
(1)有效地址传送指令LEA
LEA指令将存储器操作数的有效地址传送至指定寄存器。
MOV BX, 0400H
MOV SI, 3CH
LEA BX, [BX + SI + 0F62H] //BX ← BX + SI + 0F62H = 0040H + 3CH + 0F62H = 139EH
这里,BX得到的是主存单元的有效地址,不是物理地址,也不是该单元的内容。
(2)指针传送指令
LDS和LES指令将主存中MEM指定的字送至R16,并将MEM的下一字送DS或ES寄存器。实际上,MEM指定了主存的连续4字节作为逻辑地址,即32位的地址指针。
MOV WORD PTR [3060H], 0100H
MOV WORD PTR [3062H], 1450H
LDS SI, [3060H] //DS = 1450H, SI = 0100H
LES DI, [3060H] //ES = 1450H, DI = 0100H
2.2 算术运算类指令
2.2.1 状态标志
CF(进位标志位):当执行一个加法(减法)运算时,最高位产生进位(或借位)时,CF为1,否则为0。
ZF(零标志位):若当前的运算结果为零,则ZF为1,否则为0。
SF(符号标志位):该标志位与运算结果的最高位相同。即运算结果为负,则SF为1,否则为0。
OF(溢出标志位):若运算结果超出机器能够表示的范围称为溢出,此时OF为1,否则为0。判断是否溢出的方法是:进行二进制运算时,最高位的进位值与次高位的进位值进行异或运算,若运算结果为1则表示溢出OF=1,否则OF=0
PF(奇偶标志位):当运算结果的最低16位中含1的个数为偶数则PF=1否则PF=0
AF(辅助进位标志):一个加法(减法)运算结果的低4位向高4位有进位(或借位)时则AF=1否则AF=0
另外还有三个控制标志位用来控制CPU的操作,可以由程序进行置位和复位。
TF(跟踪标志位):该标志位为方面程序调试而设置。若TF=1,8086/8088CPU处于单步工作方式,即在每条指令执行结束后,产生中断。
IF(中断标志位):该标志位用来控制CPU是否响应可屏蔽中断。若IF=1则允许中断,否则禁止中断。
DF(方向标志位):该标志位用来控制串处理指令的处理方向。若DF=1则串处理过程中地址自动递减,否则自动递增。
2.2.2 加法指令
加法指令包括ADD、ADC和INC指令,执行字或字节的加法运算。
(1)加法指令ADD
加法指令ADD将源操作数与目的操作数相加,结果送到目的操作数,支持寄存器与立即数、寄存器、存储单元,以及存储单元与立即数、寄存器间的加法运算。
MOV AL, 0FBH //AL = 0FBH
ADD AL, 07H //AL = 02H
MOV WORD PTR [200H], 4652H //[200H] = 4652H
MOV BX, 1FEH //BX = 1FEH
ADD AL, BL //AL = 00H
ADD WORD PTR [BX + 2], 0F0F0H //[200H] = 3742H
(2)带进位加法指令ADC
ADC指令除完成ADD加法运算外,还要加进位CF,其用法及对状态标志的影响也与ADD指令一样。ADC指令主要用于与ADD指令相结合实现多精度数相加。
MOV AX, 4652H //AX = 4652H
ADD AX, 0F0F0H //AX = 3742H, CF = 1
MOV DX, 0234H //DX = 0234H
ADC DX, 0F0F0H //DX = 0F352H, CF = 0
(3)增量指令INC
INC指令对操作数加1(增量),是一个单操作数指令,操作数可以是寄存器或存储器。
INC BX
INC BYTE PTR [BX]
2.2.3 减法指令
减法指令包括SUB、SBB、DEC、NEG和CMP,执行字或字节的减法运算,除DEC不影响CF标志外,其他减法指令按定义影响全部状态标志位。
(1)减法指令SUB
减法指令SUB使目的操作数减去源操作数,结果送目的操作数,支持的操作数类型同加法指令。
MOV AL, 0FBH //AL = 0FBH
SUB AL, 07H //AL = 0F4H, CF = 0
MOV WORD PTR[200H], 4652H //[200H] = 4652H
MOV BX, 1FEH //BX = 1FEH
SUB AL, BL //AL = 0F6H, CF = 1
SUB WORD PTR[BX + 2], 0F0F0H //[200H] = 5562H, CF = 1
(2)带借位减法指令SBB
带借位减法指令SBB使目的操作数减去源操作数,还要减去借(进)位CF,结果送到目的操作数。SBB指令主要用于与SUB指令相结合,实现多精度数相减。
MOV AX, 4652H //AX = 4652H
SUB AX, 0F0F0H //AX = 5562H, CF = 1
MOV DX = 0234H //DX = 0234H
SBB DX, 0F0F0H //DX = 1143H, CF = 1
(3)减量指令DEC
DEC指令对操作数减1(减量),是一个单操作数指令,操作数可以是寄存器或存储器。
DEC CX
DEC WORD PTR [SI]
INC与DEC指令不影响进位CF标志,但影响其他状态标志。
(4)求补指令NEG
NEG指令也是一个单操作数指令,对操作数执行求补运算,即用零减去操作数(将操作数按位取反后加一),然后将结果返回操作数。
MOV AX, 0FF64H //AX = 0FF64H
NEG AL //AX = 0FF9CH, SF = 1, PF = 1, CF = 1
SUB AL, 9DH //AX = 0FFFFH, SF = 1, PF = 1, CF = 1
NEG AX //AX = 0001H, SF = 0, PF = 0, CF = 1
DEC AL //AX = 0000H, SF = 0, ZF = 1, PF = 1, CF = 1
NEG AX //AX = 0000H, SF = 0, ZF = 1, PF = 1, CF = 0
(5)比较指令CMP
比较指令将目的操作数减去源操作数,但结果不回送目的操作数。也就是说,CMP指令与减法指令SUB执行同样的操作,同样影响标志,只是不改变目的操作数。
例如比较AL是否大于100:
CMP AL, 100 //AL - 100
JB below //若AL < 100,则跳转到below执行
SUB AL, 100 //若AL >= 100,则AL ← AL - 100
INC AH //AH ← AH + 1
below: ...
2.2.4 乘法指令
乘法指令用来实现两个二进制操作数的相乘运算,包括两条指令:无符号数乘法指令MUL和有符号数乘法指令IMUL。乘法指令隐含使用一个操作数AX和DX,源操作数则显式给出。如果是字节量相乘,则AL与R8/M8相乘得到16位的字,存入AX中;如果是字相乘,则AX与R16/M16相乘得到32位的结果,其高字存入DX,低字存入AX。
无符号数0B4H与11H相乘:
MOV AL, 0B4H //AL = 0B4H = 180D
MOV BL, 11H //BL = 11H = 17D
MUL BL //AX = 0BF4H = 3060D, OF = CF = 1(AX高8位不为0)
有符号数0B4H与11H相乘:
MOV AL, 0B4H //AL = 0B4H = -76D
MOV BL, 11H //BL = 11H = 17D
IMUL BL //AX = 0FAF4H = -1292D, OF = CF = 1
2.2.5 除法指令
除法指令执行两个二进制数的除法运算,包括无符号二进制数除法指令DIV和有符号二进制数除法指令IDIV两条指令。除法指令隐含使用DX和AX作为一个操作数,指令中给出的源操作数是除数。如果是字节除法,AX除以R8/M8,8位商存入AL,8位余数存入AH;如果是字除法,DX.AX除以R16/M16,16位商存入AX,16位余数存入DX。
无符号数0400H除以B4H:
MOV AX, 0400H //AX = 400H = 1024D
MOV BL, 0B4H //BL = 0B4H = 180D
DIV BL //商AL = 05H,余数AH = 7CH = 124D
有符号数0400H除以B4H:
MOV AX, 0400H //AX = 400H = 1024D
MOV BL, 0B4H //BL = 0B4H = -76D
IDIV BL //商AL = 0F3H = -13D,余数AH = 24H = 36D
2.2.6 符号扩展指令
8086设计有两条符号扩展指令CBW和CWD。CBW指令将AL的最高有效位D7 扩展至AH,即:如果AL的最高有效位是0,则AH = 00;AL的最高有效位为1,则AH = FFH,AL不变。CWD将AX的内容符号扩展形成DX,即:如果AX的最高有效位D15为0,则DX = 0000H;如果AX的最高有效位D15 为1,则DX = FFFFH。
MOV AL, 80H //AL = 80H
CBW //AX = 0FF80H
ADD AL, 255 //AL = 7FH
CBW //AX = 007FH
2.3 位操作类指令
2.3.1 逻辑运算指令
逻辑运算指令用来对字或字节按位进行逻辑运算,包括5条指令:逻辑与AND、逻辑或OR、逻辑非NOT、逻辑异或XOR和测试TEST。
(1)逻辑与指令AND
AND指令对两个操作数执行按位的逻辑与运算,结果送至目的操作数。在这两个操作数中,源操作数可以是任意寻址方式,目的操作数只能是立即数之外的其他寻址方式,且两个操作数不能同时为存储器寻址方式。
MOV AL, 45H
AND AL, 31H //AL = 01H, CF = OF = 0, SF = 0, ZF = 0, PF = 0
AND指令可用于复位某些位,不影响其他位,例如将BL中D0和D3 清零,其余位不变,则:
AND BL, 11110110B
(2)逻辑或指令OR
OR指令对两个操作数执行按位的逻辑或运算,结果送至目的操作数,所支持的操作数同AND指令。
MOV AL, 45H
OR AL, 31H //AL = 75H, CF = OF = 0, SF = 0, ZF = 0, PF = 0
OR指令可置位某些位,不影响其他位,例如将BL中D0和D3置1,其余位不变,则:
OR BL, 00001001B
(3)逻辑异或指令XOR
XOR指令对两个操作数执行按位的逻辑异或运算,结果送至目的操作数,所支持的操作数同AND指令。
MOV AL, 45H
XOR AL, 31H //AL = 74H, CF = OF = 0, SF = 0, ZF = 0, PF = 1
XOR可用于求反某些位或将寄存器清零:
XOR BL, 00001001B //将BL的第0和3位求反
XOR AX, AX //AX = 0, CF = OF = 0, SF = 0, ZF = 1, PF = 1
(4)逻辑非指令NOT
NOT指令对操作数按位取反,NOT指令是一个单操作数指令,该操作数可以是立即数之外的任何寻址方式,NOT指令不影响标志位。
MOV AL, 45H
NOT AL //AL = 0BAH
(5)测试指令TEST
TEST指令对两个操作数执行按位的逻辑与运算,但结果不返回至目的操作数,只根据结果来设置状态标志。TEST指令通常用于检测一些条件是否满足但又不希望改变原操作数的情况,这条指令之后一般是条件转移指令,目的是利用测试条件转向不同的程序段。
TEST AL, 01H //测试AL的最低位是否为1
JNZ there //如果最低位为1,则ZF = 0,程序转移到there
... //否则最低位为0,则ZF = 1,顺序执行
there: ...
2.3.2 移位指令
移位指令分成逻辑移位指令和算术移位指令,分别具有左移或右移操作。
SHL reg/mem, 1/CL //逻辑左移:reg/mem左移1/CL位,最低位补0,最高位进入CF
SHR reg/mem, 1/CL //逻辑右移:reg/mem右移1/CL位,最高位补0,最低位进入CF
SAL reg/mem, 1/CL //算术左移,功能与SHL相同
SAR reg/mem, 1/CL //算术右移:reg/mem右移1/CL位,最高位不变,最低位进入CF
移位指令的目的操作数可以是寄存器或存储单元。源操作数表示移位位数,当移位位数大于1时,需要用CL寄存器的值来表示。移位指令按照移入的位设置进位标志CF,如果进行1位移动,则按照操作数的最高符号位是否改变,相应设置溢出标志OF:如果移位前的操作数最高位与移位后操作数的最高位不同(有变化),则OF = 1,否则OF = 0。当移位次数大于1时,OF不确定。
MOV CL, 4
MOV AL, 0F0H //AL = 0F0H
SHL AL, 1 //AL = E0H, CF = 1, SF = 1, ZF = 0, PF = 0, OF = 0
SHR AL, 1 //AL = 70H, CF = 0, SF = 0, ZF = 0, PF = 0, OF = 1
SAR AL, 1 //AL = 38H, CF = 0, SF = 0, ZF = 0, PF = 0, OF = 0
SAR AL, CL //AL = 03H, CF = 1, SF = 0, ZF = 0, PF = 1
2.3.3 循环移位指令
循环移位指令类似移位指令,但要从一端移出的位返回到另一端形成循环,分为不带进位循环移位和带进位循环移位,分别具有左移或右移操作。
ROL reg/mem, 1/CL //不带进位循环左移
ROR reg/mem, 1/CL //不带进位循环右移
RCL reg/mem, 1/CL //带进位循环左移
RCR reg/mem, 1/CL //带进位循环右移
前两条指令不将进位CF纳入循环位中。后两条指令将进位标志CF纳入循环为中,与操作数一起构成的9位或17位二进制数一起移位。
循环移位指令的操作数形式与移位指令相同,如果仅移动1次,可以用1表示;如果移位多次,则需用CL寄存器表示移位次数。循环移位指令按照指令功能设置进位标志CF,不影响SF、ZF、PF、AF标志。对OF标志的影响,循环移位指令与前面介绍的移位指令一样。
例如把AL最低位送BL最低位,但保持AL不变:
ROR BL, 1
ROR AL, 1
RCL BL, 1
ROL AL, 1
2.4 控制转移类指令
控制转移类指令通过修改CS和IP寄存器的值来改变程序的执行顺序,包括5组指令:无条件转移指令、有条件转移指令、循环指令、子程序指令和中断指令。
2.4.1 无条件转移指令
无条件转移就是无任何先决条件就能使程序改变执行顺序。处理器只要执行无条件转移指令JMP,就使程序转到指令的目标地址处,从目标地址处开始执行那里的指令。
JMP指令可以将程序转移到1MB存储空间的任何位置。根据跳转的距离,JMP指令分为段内转移和段间转移。
段内转移是指在当前代码段64KB范围内转移,因此不需要更改CS段地址,只要改变IP偏移地址。如果转移范围可以用一个8位数(-128~+127之间的位移量)表达,则可以形成“短地址”(short jump);如果地址用一个16位数表达,则形成“近转移”(near jump),± 32 \pm32±32KB范围内。
段间转移是指从当前代码段跳转到另一个代码段,此时需要更改CS段地址和IP偏移地址,这种转移也称为“远转移”(far jump)。转移的目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址。
(1)段内转移,相对寻址
JMP label //IP ← IP + 位移量
(2)段内转移,间接寻址
JMP r16/m16 //IP ← r16/m16
这种形式的JMP指令,将一个16位寄存器或主存单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容。例如:
JMP AX //IP ← AX
JMP WORD PTR[2000H] //IP ← [2000H]
(3)段间转移,直接寻址
段间直接转移指令是将标号所在段的段地址作为新的CS值,标号在该段内的偏移地址作为新的IP值。这样,程序就能跳转到新的代码段执行。
JMP FAR PTR label //IP ← label的偏移地址,CS ← label的段地址
(4)段间转移,间接寻址
JMP FAR PTR mem //IP ← [mem],CS ← [mem + 2]
段间间接转移指令用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中,其中低位字送IP寄存器,高位字送CS寄存器。例如:
MOV WORD PTR[BX], 0
MOV WORD PTR[BX + 2], 1500H
JMP FAR PTR[BX] //转移到1500H : 0
2.4.2 条件转移指令
条件转移指令中的条件如下表所示:
助记符 | 标志位 | 说明 |
---|---|---|
JZ/JE | ZF=1 | 等于零/相等转移 |
JNZ/JNE | ZF=0 | 不等于零/不相等转移 |
JS | SF=1 | 符号为负转移 |
JNS | SF=0 | 符号为正转移 |
JP/JPE | PF=1 | 1的个数为偶转移 |
JNP/JPO | PF=0 | 1的个数为奇转移 |
JO | OF=1 | 溢出转移 |
JNO | OF=0 | 无溢出转移 |
JC/JB/JNAE | CF=1 | 进位/低于/不高于等于转移 |
JNC/JNB/JAE | CF=0 | 无进位/不低于/高于等于转移 |
JBE/JNA | CF=1或ZF=1 | 低于等于/不高于转移 |
JNBE/JA | CF=0且ZF=0 | 不低于等于/高于转移 |
JL/JNGE | SF≠OF | 小于/不大于等于转移 |
JNL/JGE | SF=OF | 不小于/大于等于转移 |
JLE/JNG | SF≠OF或ZF=1 | 小于等于/不大于转移 |
JNLE/JG | SF=OF且ZF=0 | 不小于等于/大于转移 |
(1)判断单个标志位状态
①JZ/JE和JNZ/JNE利用零标志ZF,判断结果是否为零(或相等)。
例:如果AL最高位为0,则设置AH=0;如果AL最高位为1,则设置AH=FFH(也就是用一段程序实现符号扩展指令CBW的功能)。
TEST AL, 80H //测试最高位
JZ next0 //最高位为0(ZF = 1),转移到next0
MOV AH, 0FFH //最高位为1,顺序执行
JMP done //无条件转向done
next0: MOV AH, 0
done: ...
②JS和JNS利用符号标志SF,判断结果是正是负。
例:计算|X-Y|,X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT中。
②JS和JNS利用符号标志SF,判断结果是正是负。
例:计算|X-Y|,X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT中。
MOV AX, X
SUB AX, Y //AX ← X - Y,下面求绝对值
JNS nonneg //为正数,不需处理,直接转向保存结果
NEG AX //为负数,进行求补,得到绝对值
nonneg: MOV RESULT, AX
③JO和JNO利用溢出标志OF,判断结果是否产生溢出。
例:计算X-Y,X和Y分别为存放于X单元和Y单元中的16位有符号操作数。若溢出,则转移到
OVERFLOW处理。MOV AX, X
SUB AX, Y
JO overflow
... //没有溢出,结果正确
overflow: ... //溢出处理
④JP/JPE和JNP/JPO利用奇偶标志PF,判断结果中“1”的个数是偶数还是奇数。
例:设字符的ASCII编码在AL寄存器中,将字符加上奇校验位。
AND AL, 7FH //最高位置0,同时判断1的个数
JNP NEXT //个数已为奇数,则转向next
OR AL, 80H //否则,最高位置1
next: ...
⑤JC/JB/JNAE和JNC/JNB/JAE,利用进位标志CF,判断结果是否进位或借位。
例:记录BX中1的个数。
XOR AL, AL
again:TEST BX, 0FFFFH //等价于CMP BX, 0JE nextSHL BX, 1JNC againINC ALJMP again...
next: ... //AL保存1的个数
(2)用于比较无符号数高低
例:比较无符号数的大小,将较大的存入RESULT主存单元。
CMP AX, BX //比较AX和BX
JNB next //若AX ≥ BX,转移到next
XCHG AX, BX //若AX < BX,交换
next: MOV RESULT, AX(3)用于比较有符号数大小
例:比较有符号数大小,将较大的存入RESULT主存单元。
CMP AX, BX //比较AX和BX
JNL next //若AX ≥ BX,转移到next
XCHG AX, BX //若AX < BX,交换
next: MOV RESULT, AX
2.4.3 循环指令
JCXZ label //CX = 0,则转移,否则顺序执行
LOOP label //CX ← CX - 1,若CX ≠ 0,循环:IP ← IP + 位移量,否则顺序执行
LOOPZ/LOOPE label //CX ← CX - 1,若CX ≠ 0且ZF = 1,循环:IP ← IP + 位移量,否则顺序执行
LOOPNZ/LOOPNE label //CX ← CX - 1,若CX ≠ 0且ZF = 0,循环:IP ← IP + 位移量,否则顺序执行
JCXZ指令在CX寄存器为0时退出循环;
LOOP指令首先将计数值CX减一,然后判断计数值CX是否为0。CX不为0则继续执行循环体内的指令;CX为0表示循环结束。LOOPZ和LOOPNZ指令中要求同时ZF为1或0才进行循环,用于判断结果是否为0或相等,以便提前结束循环。
JCXZ指令在CX寄存器为0时退出循环;
LOOP指令首先将计数值CX减一,然后判断计数值CX是否为0。CX不为0则继续执行循环体内的指令;CX为0表示循环结束。LOOPZ和LOOPNZ指令中要求同时ZF为1或0才进行循环,用于判断结果是否为0或相等,以便提前结束循环。
例:记录附加段中STRING字符串包含空格字符的个数。假设字符串长度为COUNT字节,结果存入RESULT单元。
MOV CX, COUNT //设置循环次数
MOV SI, OFFSET string
XOR BX, BX //BX清零,用于记录空格数
JCXZ done //如果长度为0则退出
MOV AL, 20H
again:CMP AL, ES : [SI]JNZ next //ZF = 0,不是空格,转移INC BX //ZF = 1,有空格,空格个数加一
next:INC SILOOP again //字符个数减一,不为零则继续循环
done:MOV RESULT, BX //保存结果
2.4.4 子程序指令
子程序由主程序执行子程序调用指令CALL来调用;而子程序执行完后用子程序返回指令RET,返回主程序继续执行。CALL和RET指令均不影响标志位。
2.4.4 子程序指令
子程序由主程序执行子程序调用指令CALL来调用;而子程序执行完后用子程序返回指令RET,返回主程序继续执行。CALL和RET指令均不影响标志位。
例:利用子程序完成将AL低4位中的1位十六进制数转换成对应的ASCII码。
//主程序
MOV AL, 0FH //提供参数AL
CALL htoasc //调用子程序
...
htoasc: //子程序AND AL, 0FH //只取AL的低四位OR AL, 30H //AL高四位变成3CMP AL, 39H //判断是0~9还是a~fJBE htoendADD AL, 7 //若为a~f,其ASCII还要加上7
htoend: ret //子程序返回
第三章:汇编语言程序格式
3.1 汇编语言程序的开发
3.1.1 汇编语言程序的语句格式
(1)标号与名字
执行性语句中,:前的标号表示处理器指令在主存中的逻辑地址,主要用于指示分支、循环等程序的目的地址,可有可无。说明性语句中的名字可以是变量名、段名、子程序名等,反映变量、段和子程序等的逻辑地址。标号采用:分隔处理器指令,名字采用空格或制表符分隔伪指令,据此也分开了两种语句。
(2)助记符
助记符是帮助记忆指令的符号,反映指令的功能。处理器指令助记符可以是任何一条指令,表示一种处理器操作。例如,程序中使用最多的数据传送指令,其助记符是MOV。
(3)操作数和参数
处理器指令的操作数表示参与操作的对象,可以是一个具体的常量,也可以是保存在寄存器的数据,还可以是一个保存在存储器中的变量。在双操作数的指令中,目的操作数写在,前,还用来存放指令操作的结果;对应地,,后的操作数就称为源操作数。
(4)注释
语句中;后的内容是注释,通常是对指令或程序片段功能的说明,是为了程序便于阅读而加上的,不是必须有的。必要时,一个语句行也可以由;开始作为阶段性注释。
3.1.2 汇编语言的源程序框架
(1)简化段定义的源程序框架
MASM各版本支持多种汇编语言源程序格式。MASM 6.x版本的简化段定义典型格式如下:
.model small //定义程序的存储模式(small表示小型模式)
.stack //定义堆栈段(默认是1KB空间)
.data //定义数据段
... //数据定义
.code //定义代码段
.startup //程序起始点,并设置DS和SS内容
... //主程序代码
.exit 0 //程序终止点,返回DOS(0是返回值)
... //子程序代码
end //汇编结束
在简化段定义的源程序格式中,以.开始的伪指令说明程序的结构。首先,必须具有存储模型伪指令.MODEL,随后,.STACK、.DATA和.CODE依次定义堆栈段、数据段和代码段,一个段的开始自动结束上一个段。
例如:显示“Hello Everybody!”,采用简化段定义的源程序框架如下:
.MODEL SMALL
.STACK
.DATAstring DB 'Hello, Everybody!', 0DH, 0AH, '$'
.CODE
.STARTUPMOV DX, OFFSET stringMOV AH, 9INT 21H
.EXIT 0
END
(2)完整段定义的源程序框架
上文中的程序完整段定义的源程序如下:
STACK SEGMENTDB 1024 DUP(?)
STACK ENDSDATA SEGMENTstring DB 'Hello, Everybody!', 0DH, 0AH, '$'
DATA ENDSCODE SEGMENTASSUME CS: CODE, DS: DATA, SS: STACKSTART:MOV AX, DATAMOV DS, AXMOV DX, OFFSET stringMOV AH, 9INT 21HMOV AX, 4C00HINT 21H
CODE ENDSEND START
3.1.3 汇编语言程序的开发过程
略
3.1.4 DOS系统功能的调用
调用DOS操作系统功能的一般方法如下:
(1)在AH寄存器中设置系统功能调用号,说明选择的功能;
(2)在指定寄存器中设置入口参数,以便按照要求执行功能;
(3)用中断调用指令INT 21H执行功能调用;
(4)根据出口参数分析功能调用执行情况。
下表列出了主要使用的基本DOS功能调用:
子功能 号 | 功能 | 入口参数 | 出口参数 |
---|---|---|---|
AH=01H | 从标准输入设备输入一个字符 | 无 | AL=输入字符的ASCII码 |
AH=02H | 向标准输出设备输出一个字符 | DL=字符的ASCII码 | 无 |
AH=09H | 向标准输出设备输出一个字符串 | DS:DX=字符串地址 | 无 |
AH=0AH | 从标准输入设备输入一个字符串 | DS:DX=缓冲区地址 | 无 |
AH=0BH | 判断键盘是否有键按下 | 无 | AL=0表示无,AL=FFH表示有 |
AH=4CH | 程序执行终止 | AL=返回代码 | 无 |
(1)字符输出
使用02H号DOS系统功能调用在显示器输出一个字符:
MOV AH, 02H //设置功能号:AH ← 02H
MOV DL, '?' //提供入口参数:DL ← '?'
INT 21H //DOS功能调用:显示
(2)字符串输出
使用09H号DOS功能要事先将欲显示的字符串保存在主存,设置入口参数DS:DX等于该字符串在主存中的首地址,注意字符串必须以’$’(24H)结束,可以输出回车(0DH)和换行(0AH)字符产生回车和换行的作用。
string DB 'Hello, Everybody!', 0DH, 0AH, '$' //在数据段定义要显示的字符串
MOV AH, 09H //设置功能号:AH ← 09H
MOV DX, OFFSET string //提供入口参数:DX ← 字符串的偏移地址
INT 21H //DOS功能调用:显示
(3)字符输入
调用01H号DOS功能时,若无键按下,则会一直等待,直到按键后才读取该键值,并使用AL保存出口参数,即输入字符的ASCII编码。例如:判断按键是Y还是N(大写)。
getkey:MOV AH, 1 //设置功能号:AH ← 01HINT 21H //DOS功能调用:等待按键CMP AL, 'Y' //分析出口参数是否为YJE yeskeyCMP AL, 'N' //分析出口参数是否为NJE nokeyJNE getkey //不是Y或N,继续输入
(4)字符串输入
用0AH号DOS系统功能调用从键盘输入一个字符串:
buffer //定义缓冲区
DB 81 //第1字节填入可能输入的最大字符数
DB 0 //第2字节将用于存放实际输入的字符数
DB 81 DUP(0) //第3字节开始用于存放输入的字符串
...
MOV AH, 0AH
MOV DX, SEG buffer
MOV DS, DX
MOV DX, OFFSET buffer
INT 21H
(5)按键判断
例如:按任意键继续的程序片段:
... //提示“按任意键继续”
getkey:
MOV AH, 0BH //设置功能号:AH ← 0BH
INT 21H //DOS功能调用:判断按键否
OR AL, AL //分析出口参数:AL = 0 ?
JZ getkey //AL = 0,没有按键,继续等待
3.2 参数、变量和标号
3.2.1 数值型参数
略
3.2.2 变量定义伪指令
变量定义伪指令为变量申请固定长度的存储空间,并可以同时将相应的存储单元初始化,其汇编格式为变量名 伪指令 初值表。
(1)变量名为用户自定义标识符,表示初值表首元素的逻辑地址,即用这个符号表示地址,常称为符号地址。变量名可以没有,在这种情况下,汇编程序将直接为初值表分配空间,无符号地址。
(2)初值表是用,分隔的参数,主要由数值常数、表达式或?、DUP组成。其中?表示初值不确定,即未赋初值;重复初值可以用DUP进行定义。DUP的格式为:重复次数 DUP(重复参数)
(3)变量定义伪指令有DB、DW、DD、DF、DQ、DT,它们根据申请的主存空间单位分类,下面逐一介绍。
(1)定义字节单元伪指令
字节定义伪指令DB,用于分配1字节或多字节单元,并可以将它们初始化为指定值。
.DATAX DB 'a', -5DB 2DUP(100), ?Y DB 'ABC'
利用这些变量的汇编指令示例如下:
MOV AL, X //此处X表示它的第一个数据,故AL ← 'a'
DEC X + 1 //对X为起始的第二个数据减一,故成为-6
MOV Y, AL //现在Y这个字符串成为'aBC'
(2)定义字单元伪指令
一个字单元可用于存放任何16位数据。
.DATACOUNT DW 8000H, ?, 'ab'MAXINT EQU 64HNUMBER DW MAXINTARRAY DW MAXINT DUP(0)
(3)定义双字单元伪指令
一个双字单元可用于存放任何32位数据。
VARDD DD 0, ?, 12345678H
FARPOINT DD 00400078H
(4)其他数据定义伪指令
DF:定义3字伪指令;
DQ:定义4字伪指令;
DT:定义10字节伪指令。
例:定义一个缓冲区,包含33H、34H、35H和36H四个字节字符,把这四个数据依次复制20次,存入接着的存储区,最后显示出复制结果。
//数据段
source DB 33H, 34H, 35H, 36H
target DB 80 DUP(?)
//代码段
MOV SI, OFFSET SOURCE
MOV DI, OFFSET TARGET
MOV CX, 80
again:
汇编语言程序设计钱晓捷第五版期末复习参考相关推荐
- C程序设计谭浩强第五版课后答案 第三章习题答案
C语言程序设计谭浩强第五版课后答案第三章 1.假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比.计算公式为p=(1+r)np = (1+r)^np=(1+r ...
- C程序设计(谭浩强第五版)总结
C程序设计(谭浩强第五版)总结 本篇文章主要是总结谭浩强第五版C语言书上的重点和易漏点的知识点,其目的主要是给高校期末考试的同学们点参考.本文所参考的书籍是谭浩强的<C程序设计(第五版)> ...
- 南邮《汇编语言程序设计》2018/2019 学年第一学期期末考试回忆
2018.12.8 13:30-15:20 <汇编语言程序设计>考试 刚考完,回忆一下题目. 先总结一下:感觉考得还是蛮细的,主要自己复习时间也不多,全凭上学期学过一遍的记忆和笔记复习的. ...
- 数学模型(第五版) PDF 习题参考解答 第5版
数学模型(第五版) (姜启源 谢金星 叶俊) PDF 数学模型 习题参考解答 第5版 (姜启源,谢金星) pdf 无套路直接下载 数学模型(第五版)>是由姜启源.谢金星.叶俊编写,高等教育出 ...
- 数据库系统概论(第五版)复习资料
(配套教材为数据库系统概论第五版王珊) 一.填空题 数据库 P4 数据库是长期存储在计算机内.有组织的.可共享的大量数据的集合. 数据库的数据独立性 P13 数据独立性分为物理独立性和逻辑独立性 ...
- Java数据结构第五版期末考试_数据结构(java)期末复习
[单选题]多基因遗传病的发病风险与下列哪个因素无关 [单选题]一般手锯的往复长度不应小于锯条长度的( ). [判断题]机器上所有;零件都必须进行机械加工. [单选题]一般划线精度能达到( ). [填空 ...
- C语言程序设计谭浩强第五版复习梳理2
第2章 算法--程序的灵魂 前言:前两章都是c语言基础知识,软考还有考研笔试可能会考,下一章开始学的才是真正的编程. 2.1程序=算法+数据结构 算法+数据结构=程序 数据结构: 对数据的描述.在程序 ...
- 数据库系统概论(王珊 第五版)复习要点
本文整理了<数据库系统概论>一书中的要点,并以问答的形式展示出来. 部分章节还未整理,会持续更新. 提示:右侧导航栏有[目录] 如果对您有帮助,请点个赞加个关注呐. 一.绪论 1.解释下列 ...
- 计算机组成与结构第五版期末考试重点
1.冯诺依曼型计算机基本特点 计算机由运算器,控制器,存储器,输入设备和输出设备5部分组成 采用存储程序的方式,程序和数据放在同一个存储器中,并以二进制码表示 指令由操作码和地址码组成 指令在存储器中 ...
最新文章
- node.js浅入深出---fs模块的stat判断是否为文件夹
- 现存问题以及解决方案:在ASP.NET AJAX中从客户端向服务器端传送DataTable
- Thymeleaf读取model里面的对象||Thymeleaf读取model里面的集合||Themeleaf在js中取值||访问带参数的消息||ThymeleafObjects的使用[取三大作域的值
- 时间戳服务——信息安全(二)
- ubuntu交叉编译x264报错:‘X264_VERSION’ undeclared(已解决)运行version.sh
- ICLR 2020 开源论文 | 隐空间的图神经网络:Geom-GCN
- JAVA_WEB--jsp语法
- 使用CocoaPods导入百度地图SDK所遇到的坑
- 微服务架构 性能提升_如何通过无服务器架构提高性能
- Linux基本命令二(帮助命令)
- IDEA中用maven打出的jar包只有一个META-INF文件夹,没有java的源码???
- 算法的定义、特征及其算法设计的要求
- Skype for Linux下载地址
- 操作系统--虚拟内存
- dw怎么在框架中加入网页_Dreamweaver如何用框架建立网站
- Android绕过微信包名限制对接微信登录和支付
- tp5原生SQL:读操作(query方法)
- [vivado系列]Vivado软件的下载
- python 边缘扩充方式
- 哄女朋友利器 —— 赶紧对她说我爱你,程序猿的专属浪漫(附源码)