学习内核,学习写操作系统,我们要了解掌握两门语言,分别是汇编语言和C语言,汇编语言是低级语言,由许许多多看不懂的指令组成,而我们的C语言就不一样了,他是介于高级语言与低级语言之间的一种语言,现在在世界语言排行榜上C语言已经跃居世界第一,他的效率是毋庸置疑的。
本人初学乍练,在这里也献丑了,就是把平时学习和积累的东西拿出来和大家分享一下,希望大家多多指正,须向学习,共同进步!
这篇文章是内核学习入门汇编语言,以后还会专门写一些C语言方面的博客跟大家分享交流。
1、寄存器register(有限存贮容量的高速存贮部件)
8086 有14个16位寄存器,我们先来认识一下这14个寄存器:通用寄存器((数据寄存器,由(XH&XL)组成)AX、BX、CX、DX,(指针寄存器和变址寄存器)SP,BP,SI,DI)、 段寄存器(CS代码段,SS堆栈段,DS数据段,ES附加段)、指令指针寄存器(IP)、 标志寄存器(FLAGS)。
通用寄存器:
1、数据寄存器:AX(accumulator)、累加寄存器,常用于运算。
BX(base)、基址寄存器,常用于地址索引。
作为偏移地址与DS配合!
CX(count)、计数寄存器,常用于计数。
loop 和 Cx 合作!
DX(data)、数据寄存器,常用于数据传递。
下面来看一下16位寄存器分为两个8位寄存器:
2、指针寄存器和变址寄存器: SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。
BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置。
SI(Source Index):源变址寄存器,可用来存放相对于DS段之源变址指针。
DI(Destination Index):目的变址寄存器,可用于存放相对于ES段之目的变址指针。
段寄存器:
8086设有4个段寄存器,专门用来保存段地址。在程序要执行的时候,我们需要确定各代码等在内存中的位置,通过这些寄存器来指向这些起始位置。
8086CPU用“基地址(段地址×16)+偏移地址=物理地址”方式给出内存段元的物理地址,我们就可以用分段的方式来管理内存。
1、CS(Code Segment)、代码段寄存器
2、DS(Data Segment)、数据段寄存器
mov ax, 1233H
mov ds, ax
mov bx, [0]
上面的代码意思是我们把12330(1233:0)中的数据送到了bx这个寄存器中。
3、SS(Stack Segemt)、堆栈段寄存器
堆栈这个概念相信学过高级语言(C/C++等)的同学都应该知道,栈是一个后进先出的数据结构,先进来的最后出去,和他对比的是队列,队列是先进先出的数据结构,先进来的最后出去。
在栈中常见的漏洞是溢出错误,这里不是介绍数据结构,大家去参考一下数据结构的教材详细的了解一下。
在这里要说的就是SS:SP,他在任意时刻总是指向栈顶元素。在这里,栈顶的段地址存放在SS中,偏移地址存放在SP中。
说到栈,汇编中涉及到两个指令,分别是push和pop。
入栈:push ax,它分为两步完成:1、SP = SP - 2, SS:SP指向当前栈顶最前面的单元。
2、将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。
出栈: pop ax, 它也是分两步来完成:1、将SS:SP指向的内存单元处的数据送入ax中。
2、SP = SP+2, SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元作为新的栈顶.
这里需要注意的是:pop出栈后,栈内的数据还是存在的,并没有删除掉.
4、ES(Extra Segment)、附加段寄存器
指令指针寄存器IP:
需要知道的是,IP是指令地址的段内地址偏移量,即偏移地址,有时候也叫他是有效地址。
我们拿CS:IP来说一下:
CS:IP是指向内存单元。即:段地址:偏移地址,我们算出内存中的物理地址。
如果我们要修改CS:IP的值,我们不能像修改AX一样用:mov ax,100(mov指令下面会介绍)。我们必须用jmp指令来修改。
先来看看同时修改CS:IP: jmp 段地址:偏移地址
如:jmp 23E4:3 执行后CS = 23E4H , IP = 0003H CPU 会从 23E43H处读取数据。
现在我们就想修改IP的值: 我们可以用:jmp 某一合法寄存器
如:jmp ax 执行前是:ax = 1000H, cs = 2000H , IP = 3000H
执行后是:ax = 1000H, CS = 2000H, IP = 1000H
我们可以这么理解 jmp 某一合法寄存器: mov IP, ax
标志寄存器FR:
来看一下标志寄存器的结构图:
2、汇编指令集合(这里部分常用的指令会讲解,主要是查询使用)
(1)、数据传送指令
通用数据传送指令
mov 传送字或数据(这个指令比较常用,大家需掌握)
格式: MOV OPRD1,OPRD2
功能: 本指令将一个源操作数送到目的操作数中,即OPRD1<--OPRD2.
mov ax, [2]
我们可以这样描述: (ax) = ((ds)*16+2) 表示将ds:0处的数据送入al中!(应为内存单元是一个字节8位,ax是一个16位的,同位的进行存储)
push 入栈指令
pop 出栈指令
格式:push ax pop ax
功能:实现压入操作的指令是push指令,弹出操作的指令是pop指令
push和pop的操作过程在上文有图示,大家可以参阅。
xchg 交换字或字节(至少有一个操作数为寄存器,段寄存器不可作为操作数)
格式: XCHG OPRD1, OPRD2 目的操作数,源操作数
功能:将两个操作数相互交换位置,该指令把源操作数OPRD2与目的操作数OPRD1交换
xlat 字节查表转换
格式:XLAT TABLE table为一待查表格的手地址
功能:把待查表格的一个字节内容送到AL累加器中
目的地址传送指令
lea 装入有效地址 lea dx,string ; 把偏移地址存到dx中
功能:将源操作数给出的有效地址送到指定的寄存器中
LEA BX,DATA1
上面指令的功能是将变量DATA1的地址送至BX,而不是将变量DATA1的值送BX,它等价于:
mov bx,offset data
lds 传送目标指针,吧指针内容装入ds lds si,string ; 把段地址:偏移地址存到 ds:si
功能:从存储器中取出32位地址的指令
LDS DI,[BX]
上面的指令的功能是把BX所指的32位地址指针的段地址送入DS,偏移地址送入DI
les 传送目标指针,把指针内容装入ES les di,sring ; 把段地址:偏移地址存到es:di
功能:从存储器取出32位地址的指令
LES DI,[BX]
上面的指令的功能是把BX所指的32位地址指针的段地址送入ES,偏移地址送入DI
标志传送指令
lahf 标志寄存器传送,把标志装入AH
功能:取FLAG标志寄存器低8位至AH寄存器。他不影响FLAG的原来内容,AH只是复制了原FLAG的低8位内容。
sahf 标志寄存器传送,把AH内容装入标志寄存器
功能:将AH存至FLAG低8位。 用AH的内容改写FLAG标志寄存器中的SF,ZF,AF,PF,CF标志,从而改变原来的标志位。
pushf 标志入栈
功能:可以把标志寄存器的内容保存到堆栈中去
popf 标志出栈
功能:与pushf相反,在子程序调用和终端服务程序中,往往用pushf指令保护FLAG的内容,用popf指令将保护的FLAG内容恢复。
pushd 32位标志入栈
popd 32位标志出栈
(2)、逻辑运算指令
AND 逻辑与运算指令
功能:对两个操作时实现按位逻辑与运算,结果送到目的操作数中。
指令影响标志位PF、SF、ZF,使CF=0、OF=0.
AND AL,0FH ;(AL)<--(AL) AND 0FH
AND AX,BX ;(AX)<--(AX) AND (BX)AND DX,BUFFER[SI+BX]
AND BETA[BX],00FFH
注意:两个数与运算,有一个数为假则值为假。
OR 逻辑或指令
功能:按位或运算。
注意:两个数或运算,有一个数为真则结果为真。
XOR 逻辑异或运算指令
功能:实现两个操作数按位异或运算。结果送到目的操作数中
相异为真,相同为假。
NOT 逻辑非运算指令
功能:完成对操作数按位求饭运算。结果返回原操作数。
TEST 测试指令
功能:其中寄存器的含义和AND指令相同。也是对两个操作数进行按位与运算。唯一不同的是不讲与的结果送到目的操作数。即本指令对两个操作数的内同均不进行修改,仅在逻辑与操作后对标志位重新置位。
SHL 逻辑左移指令
功能:对给定的目的操作数左移COUNT次,每次移位时最高位移入标志位CF中,最低位补0.
SHL AL,1
SHL CX,1 ;都是左移1位
SHL ALFA[DI] 或者:
MOV CL,3
SHL DX,CL
SHL ALFA[DI],CL ;都是左移3位
SHR 逻辑右移指令
功能能:同SHL想法。 它每次移位时,最高位补0,最低位移至标志位CF中。
影响标志位:OF, PF, SF, ZF CF.
SAL 算术左移指令
功能:与SHL功能相同,因为逻辑左移指令与算术左移指令所要完成的操作是一样的。
SAR 算术右移指令。
功能:本指令通常用于对带符号数减半的运算中,因为在每次右移时保持最高位不变,最低位右移到CF中。
ROL 循环移位指令
功能:循环移位指令时指操作数首位相连的移位操作,按进位标志CF是否参加循环移位,又可分为不带CF的循环移位和带CF的循环移位两类,每一类都进行左移或右移,循环移位的次数由count操作数给出。
例:将AL中的组合的两个BCD分解为两个未组合的BCD数,存于BH及BL寄存器中 程序为:
MOV AH,AL ;保存AL内容至AH中
MOVCL,4 ;循环次数4送CL
SHR AL,CL ;将AL右移4次,高4位移至低4位
MOV BH,AL ;高位BCD送BH中
AND AH,0FH ;得到低位BCD数
MOV BL,AH ;低位BCD数送BL中注意: 以上程序中的指令SHR AL,CL如改为SAR AL,CL,虽然最高4位可移入低4位 ,但最高位不为0,故应加入一条指令AND AL,0FH.否则,若最高位不为0时,将得到错误结果.
ROR 循环移位指令
RCL 循环移位指令
RCR 循环移位指令
这些指令只影响标志CF,OF. 由移入CF的内容决定,OF取决于移位一次后符号位是否改变,如改变则OF=1
ROL OPRD1,COUNT ;不含进位标志位CF在循环中的左循环移位指令.
RCL OPRD1,COUNT ;带进位的左循环移位指令.
RCR OPRD1,COUNT ;带进位的右循环移位指令.
(3)、算术运算指令
.组合的十进制数和未组合的十进制数:在计算中,十进制数可用四位二进制数编码,称为BCD码.当一个节(8位)中存放一位BCD码,且放在字节的低4位, 高4位称为未组合的BCD码.显然,一个字节中也可以存放两位BCD码,称一个字节中的两位BCD数为组合的BCD数.
ADD 加法指令
功能:两数相加
加法指令运算的结果对CF、SF、OF、PF、ZF、AF都会有影响.
ADC 带进位加法指令
格式:ADC OPRD1,OPRD2
功能:OPRD1<--OPRD1 + OPRD2 + CF
OPRD1为任一通用寄存器或存储器操作数,可以是任意一个通用寄存器
OPRD2为立即数,也可以是任意一个通用寄存器操作数.立即数只能用于源操作数
ADC AL,CL ; (AL)<--(AL)+(CL)+CF
ADC AX,SI ; (AX)<--(SI)+CF
ADC DX,MEMA ;(DX)<--(DX)+[(DS)*16+MEMA]+CF
ADC CL,15 ; (CL)<--(CL)+15+CF
ADC WORD PTR[BX][SI],25
INC加1指令
功能:相当于C中的++操作符
这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位.
INC SI ;(SI)<--(SI)+1
SUB减法指令
功能:两个操作数的相减,即从前一个寄存器中减去后一个寄存器,结果放在前一个寄存器中,指令的类型及对标志位的影响与ADD指令相同,注意立即数不能用于目的操作数,两个存储器操作数之间不能直接相减,操作数可为8位或16位的无符号数或带符号数。
SBB 带借位减法指令
功能:是进行两个操作数的相减再减去CF进位标志位。即AX<--AX - BX - CF,其结果放在AX中,指令的类型及对标志位的影响与ADD指令相同,注意立即数不能用于目的操作数,两个寄存器操作数之间不能直接相减,操作数可为8位或16位的无符号数或带符号数。
DEC 减一指令
功能:相当于C中的--操作符。
这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF标志位.
NEG 取补指令
格式:NEG OPRD
功能:对操作数OPRD进行取补操作,然后将结果送回OPRD,取补操作也叫做求补操作,就是求一个数的相反数的补。
(AL)=44H,取补后,(AL)=0BCH(-44H).本指令影响标志位CF、OF、SF、PF、ZF及AF.
CMP 比较指令
功能:对两个数进行比较,该指令不改变寄存器的值,只是用于改变标志位。
以CMP DX,CX为例,对标志位的影响如下:
(1) (DX)=(CX)时,则ZF=1;(2) 两相无符号数比较:
若(DX)>=(CX)时,则CF=0,即无借位.
若(DX)<(CX)时,则CF=1.(3) 两个带符号数比较
对带符号数判断大小可通过溢出标志OF及符号标志SF共同判断.
当 OF=0,即无溢出时,若SF=0,则(DX)>(CX)
若SF=1,则(DX)<(CX)
当 OF=1,即有溢出时,若SF=1,则(DX)>(CX)
若SF=0,则(DX)<(CX)
MUL 无符号数乘法指令
功能:乘法操作
本指令影响标志位CF及OF.
操作过程:字节相乘:(AX)<--(AL)*OPRD,当结果的高位字节(AH)不等于0时,则 CF=1、OF=1.
字相乘:(DX)(AX)<--(AX)*OPRD,当(DX)不等0时,则CF=1、OF=1
IMUL 带符号数乘法指令
功能:完成两个带符号数的相乘
DIV 无符号数除法指令
功能:实现两个无符号二进制数除法运算
DIV BETA [BX]
DIV CX;商在AX中,余数在DX中
DIV BL;商在AL中,作数在AH中
IDIV 带符号数除法制定
功能:是想两个带符号数的二进制除法运算
CBW 字节扩展指令
功能:将字节扩展为字,即把AL寄存器的符号位扩展到AH中
两个字节相除时,先使用本指令形成一个双字节长的被除数。
MOV AL,25
CBWIDIV BYTE PTR DATA1
CWD字扩展指令
功能:将字扩展为双字长,即把AX寄存器的符号位扩展到DX中。
两个字或字节相除时,先用本指令形成一个双字长的被除数。
例:在B1、B2、B3字节类型变量中,分别存有8位带符号数a、b、c,实现(a*b+c)/a运算。
MOV AL,B1 ; a-->(AL)
IMUL B2 ; 实现a*b-->(AX)
MOV CX,AX ; (AX)-->(CX)
MOV AL,B3 ; c-->(AL)
CBW ; 扩展符号位至AH中
ADD AX,CX ; (AX)+(CX)-->(AX),完成a*b+c
IDIV B1 ; 完成(a*b+c)/a,商-->(AL),余数-->(AH)
AAA 未组合十进制加法调整指令
功能:对两个组合的十进制数相加运算(存于AL中)的结果进行调整,产生一个未组合的十进制数放在AN中。
调整操作: 若(AL) and 0FH>9 或 AF=1,则调整如下:
(AL)<--(AL)+6,(AH)<--(AH)+1,AF=1,CF<--AF,(AL)<--(AL) and 0FH
DAA 组合的十进制加法调整指令
功能:对AL中的两个组合进制数相加的结果进行调整,调整结果仍放在AL中,进位标志放在CF中
调整操作:若(AL) and 0FH>9 或 AF=1,则(AL)<--(AL)+6,AF<--1,对低四位的调整.
若(AL) and 0F0H>90H 或 CF=1,则(AL)<--(AL)+60H,CF<--1.
列:
(AL)=18H,(BL)=06H
ADD AL,BL ; (AL)<--(AL)+(BL)
; (AL)=1EH
DAA ; (AL)=24H,AF=1注意: 本指令影响标志位AF,CF,SF,ZF
DAS 组合十进制减法调整指令
功能:对两个组合十进制数相减后存于AL中的结果进行调整,调整后产生一个组合的十进制数且仍存于AL中。
调整操作:若(AL) and 0FH > 9 或 AF=1,则(AL)<--(AL)-6,AF=1
若(AL) and 0F0H > 90H 或 CF=1,则(AL)<--(AL)-60,CF=1
AAS 未组合十进制减法调整指令
功能:对两个未组合十进制数相减后存于AL中的结果进行调整,调整后产生一个未组合的十进制数,且仍存于AL中。
注意:本指令影响标志位CF,AF
调整操作: 若(AL) and 0FH > 9 或 AF=1
则(AL)<--(AL)-6,(AH)<--(AH)-1,CF<--AF,(AL)<--(AL) and 0FH,否则 (AL)<--(AL) and 0FH
AAM 未组合十进制数乘法调整指令
功能:对来年改革未组合的十进制数相乘后存于ax中的结果进行调整,产生一个未组合的十进制数存于AL中。
乘积: (AH)<--(AL)/10
(AL)<--(AL)MOD10注意:本指令应跟在MUL指令后使用。乘积的两位十进制结果,高位放在AH中,地位放在AL中。
本指令影响标志为:PF,SF,ZF
AAD 未组合十进制数除法调整指令
功能:在除法指令前对AX中的两个未组合十进制数进行调整,以便能用DIV指令实现两个未组合的十进制数的除法运算,其结果为未组合的十进制数,商(在AL中)和余数(在AH中)。
AAM与AAD不同是,AAD指令在执行除法DIV之前使用的,以便得到二进制结果存于AL中。
调整操作: (AL)<--(AH)*10+(AL),(AH)<--0
注意:ADD指令执行后,AL中的内容已成为二进制数。
本指令影响标志为PF,SF,ZF
(4)、控制转移指令
无条件转移指令 (长转移)
JMP 无条件转移指令
功能:jmp指令将无条件地控制程序转移到目的地址去执行,当目的地址仍在同一个代码段内,成为段内转移。当目标地址不在同一个代码段内,称为段间转移,这两种情况都将产生不同的指令代码。以便能正确地生成目的地址。在段内转移时指令只要能提供目的地址的段内便宜量即够了。而在段间转移时,指令能提供目的地址的段地址及段内便宜地址值。
段内直接转移指令: JMP NEAR 标号
即: JMP NEAR 标号; (IP)<--disp16+(IP)
JMP SHORT 标号; (IP)<--disp8+(IP)段内间接转移指令: JMP OPRD
例如: JMP BP ; 转向(SS):(BP)
JMP JNEAR[BX] ; 转向(CS):(BX)+JNEAR
JMP WORD PTR[BX][DI] ; 转向(CS):(BX)+(DI)段间直接转移指令: JMP FAR 标号
段间间接转移指令:JMP OPRD
CALL 过程调用
功能:过程调用指令
过程调用可分为段内调用和段间调用两种.寻址方式也可以分为直接寻址和间接 寻址两种.
段内直接调用: CALL NEAR类型的过程名
段内间接调用: CALL OPRD
段间直接调用: CALL FAR 类型的过程名
段间间接调用: CALL DWOPRD
RET/RETF过程返回.
功能:当调用的过程结束后实现从过程返回到原调用程序的下一条指令,本指令不影响标志位。
条件转移指令 (短转移,-128到+127的距离内)
JA/JNBE不小于或不等于时转移.
功能:为高于/不低于等于的转移指令
该指令用于无符号数进行条件转移
例如两个符号数a,b比较时,a>b(即CF=0,ZF=0)时转移.因为单一标志位CF=0,只 表示a>=b.
JAE/JNB大于或等于转移.
功能:为高于等于/不低于的转移指令
该指令用于无符号数进行条件转移
JB/JNAE小于转移.
功能:低于/不高于等于时转移
该指令用于无符号数的条件转移
JBE/JNA 小于或等于转移.
功能:低于等于/不高于时转移
该指令用于无符号数的条件转移
JG/JNLE大于转移.
功能:大于/不小于等于时转移
用于带符号数的条件转移指令
JGE/JNL大于或等于转移.
功能:大于等于/不小于时转移
用于带符号数的条件转移指令
JL/JNGE小于转移.
功能:小于/不大于等于时转移
用于带符号数的条件转移指令
JLE/JNG小于或等于转移.
功能:小于等于/不大于时转移
用于带符号数的条件转移指令
JE/JZ 等于转移.
功能:ZF=1转至标号处执行
根据标志位ZF来进行转移,他们是一条指令的两种助记符表示方法。
JNE/JNZ不等于时转移.
功能:ZF=0转至表好处执行。
JC有进位时转移.
功能:CF=1转至标号处执行
JNC无进位时转移.
功能:CF=0转至标号处执行
JNO不溢出时转移.
功能:OF=0转至标号处执行
JNP/JPO奇偶性为奇数时转移.
功能:PF=0转至标号处执行
JNS符号位为 "0" 时转移.
功能:SF=0转至标号处执行
JO溢出转移.
功能:OF=1转至标号处执行
JP/JPE 奇偶性为偶数时转移.
功能:OF=1转至标号处执行
JS符号位为 "1" 时转移.
功能:SF=1转至标号处执行
循环控制指令(短转移)
LOOP CX不为零时循环.
功能: (CX)<--(CX)-1,(CX)<>0,则转移至标号处循环执行, 直至(CX)=0,继续执行后继指令.
它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
功能: (CX)<--(CX)-1,(CX)<>0 且ZF=1时,转至标号处循环
它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
功能: (CX)<--(CX)-1,(CX)<>0 且ZF=0时,转至标号处循环
它属于段内SHORT短类型转移,目的地址必须距本指令在-128到+127个字节的范围内.
JCXZCX为零时转移.
JECXZE CX为零时转移.
中断指令
INT中断指令
功能:本指令将产生一个软中断,把控制转向一个类型号为r的软中断,该中断处理程序入口地址在中断向量表的n*4地址处的两个存储器字(4个单元)中。
他的操作过程与INTO指令雷同,只需要将10H改为n*4即可, ,本指令也将影响标志位IF及TF.
INTO溢出中断
功能:本指令检测OF标志位,当OF=1时,说明已发生溢出,立即产生一个中断类型4的中断,当OF=0时,本指令不起作用。
操作过程: 如果OF=1,则(SP)<--(SP)-2, 标志寄存器入栈,IF、TF清0, (SP)<--(SP)-2,将当前CS入栈,00010H地址的第二个字的内容送入CS,即 00013H及00012H单元内容送CS,(SP)<--(SP)-2,IP内容入栈,将00010H的第一个字的内容送IP, 从而实现向中断类型4中断处理程序的转移.如果CF=0,则立即执行一条指令.
这条指令影响标志位IF,TF
当用于溢出处理,当OF=1时,产生一个类型4的软中断,在中断处理程序中完成溢出的处理操作。
IRET中断返回
功能:用于中断处理程序中,从中断程序的断点处返回,继续执行原程序。
操作过程: 将当前堆栈弹出一个字送IP,(SP)<--(SP)+2,再弹出一个字送CS,(SP)<--(SP)+2,最后从堆栈弹出一个字送FLAG寄存器,(SP)<--(SP) +2.
它影响所有的标志位。
无论是软中断,还是硬中断,本指令均可使其返回到中断程序的断点处继续执行 原程序.
(5)、串操作指令
MOVS串传送.
将存储器中变量A开始的200个数据串传送至B开始的存储区,可用以下程序段实现:
MOV SI,OFFSET A ; SI指向源串首址
MOV DI,OFFSET B ; DI指向目的串首址
MOV CX,200 ; 字节串或字串长度200送CX
CLD;0-->DF
ATOB:MOVS B,A ; 对字节串传送可用MOVSB
DEC CX ; (CX)<--(CX)-1
JNZ ATOB ; (CX)<>0,转至ATOB
用指令MOVS B,A究竟是字节传送,还是字传送,取决于A,B的类型定义.若DF=0,则在字传送时,(SI)<--(SI)+2,(DI)<--(DI)+2.
CMPS串比较.
功能: 由SI寻址的源串中数据与由DI寻址的目的串中数据进行比较,比较结果送标志位,而不改变操作数本身.同时SI,DI将自动调整.
例如: 对两个字节串进行比较,若一致,则AL内容置为0;若不一致,则AL内容置为0FFH.程序段如下:
MOV SI,OFFSET ST1
MOV DI,OFFSET ST2
MOV CX,N
CLD
NEXT:CMPSB
JNZ FIN
DEC CX
JNZ NEXT
MOV AL,0
JMP OVR FIN:MOV AL,0FFH
OVR:MOV RSLT,AL
与MOVS相似,CMPS指令也可以不使用操作数,此时可用指令CMPSB或CMPSW分别表示字节串比较或字串比较.
SCAS串扫描
功能: 把AL(字节串)或AX(字串)的内容与由DI寄存器寻址的目的串中的数据相减,结果置标志位,但不改变任一操作数本身.地址指针DI自动调整.
指令中不使用操作数时,可用指令格式SCASB,SCASW,分别表示字节串或字串搜索指令.
LODS装入串.
功能: 把SI寻址的源串的数据字节送AL或数据字送AX中去, 并根据DF的值修改地址指针SI进行自动调整.
STOS保存串.
功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去,指针DI将根据DF的值进行自动调整.
(6)、伪指令
DB定义字节(1字节)
DW定义字(2字节).
DD定义双字(4字节)
DB: 定义字节变量
DW: 定义字变量DD: 定义双字变量
DF: 定义6字节变量
DQ: 定义四字变量
DT: 定义10字节变量
格式: [<变量名>]{DB|DW|DD|DF|DQ|DT}<表达式>,<表达式>
PROC定义过程.
ENDP 过程结束.
格式: <过程名>PROC[NEAR或FAR]
RET
<过程名>ENDP
ASSUME建立段寄存器寻址.
格式: ASSUME<段寄存器>:<段名>[,<段寄存器>:<段名>]
例如: ASSUME CS:CSEGH,DS:DSEG,SS:SSEG,ES:ESEG
SEGMENT定义段.
功能: SEGMENT和ENDS伪操作命令可用来把程序分成若干逻辑段,这些逻辑段按用途不同,通常包括代码段、数据段、堆栈和附加段,它分别装入由CS、DS、SS和ES寄存器所指定的物理段中。
ENDS段结束.
格式:<段名>SEGMENT[<定位类型>],[<组合类型>],[<'类别名'>]
---- …:段体
<段名>ENDS功能:SEGMENT和ENDS伪操作命令可用来把程序费城若干逻辑段,这些逻辑段按用途不同,通常包括代码段,数据段,堆栈段,附加段。它分别装入由CS,DX,SS
,ES寄存器所指定的物理段中。
END程序结束.
格式: [NAME<模块名>]
---- ...
END[标号]