310 likes | 421 Views
三、逻辑类指令. 1. 逻辑运算指令 ● 运算规则:按位操作,无进 / 借位 ● 对标志位的影响 ( 除 NOT 指令外 ) :. CF OF SF ZF PF AF 0 0 * * * 无定义. 根据运算结果设置. “ 与”运算指令 格式: AND dst, src “ 或”运算指令 格式: OR dst, src “ 非”运算指令 格式: NOT opr “ 异或”运算指令 格式: XOR dst, src 测试指令 格式: TEST dst, src
E N D
三、逻辑类指令 1. 逻辑运算指令 ● 运算规则:按位操作,无进/借位 ● 对标志位的影响(除NOT指令外): CF OF SF ZF PF AF 0 0 * * * 无定义 根据运算结果设置
“与”运算指令 格式:AND dst, src “或”运算指令 格式: OR dst, src “非”运算指令 格式:NOT opr “异或”运算指令 格式:XOR dst, src 测试指令 格式:TEST dst, src 说明:TEST相当于AND运算,但是 不保存结果,仅影响标志。
(1) 逻辑”与” AND 对两个操作数进行按位逻辑“与”操作。 格式:AND dest, src 用途:保留操作数的某几位,清零其他位。 例1:保留AL中低4位,高4位清0。 AND AL, 0FH 例2:AL中有字符’a’~’z’, 将其转换成大写。(‘a’=61h, ‘A’=41h) AND AL, 01001111B
例:测试AL的bit7,bit5,bit2是否都是1。 AND AL, 10100100B CMP AL, 10100100B JZ YES ; if match, go to YES … … ; if not match …… YES: … … ; goes here if all ‘1’
对两个操作数进行按位逻辑”或”操作。 格式:OR dest, src 用途:对操作数的某几位置1;对两操作数 进行组合。 例:把AL中的非压缩BCD码变成相应十进制 数的ASCII码。 OR AL, 30H (2) 逻辑”或” OR
例:把AH和AL中的非压缩BCD码组合成压 缩的BCD码, 放到AL中。 MOV CL, 4 SHL AH, CL OR AL, AH 例:把AL的第5位置为1 OR AL, 00100000B
对操作数进行按位逻辑”非”操作。 格式:NOT mem/reg 例:NOT CX NOT BYTE PTR [DI] (3) 逻辑“非”(取反) NOT
对两个操作数按位进行”异或”操作。 格式:XOR dest, src 用途:对reg清零(自身异或) 把reg/mem的某几位变反(与’1’异或) 例:把AX寄存器清零。 例2:把DH的bit4,3变反 ① MOV AX,0 XOR DH,18H ② XOR AX,AX ③ AND AX,0 ④ SUB AX,AX (4) 逻辑”异或” XOR
操作与AND指令类似,但不将”与”的结果送回,只影响标志位。操作与AND指令类似,但不将”与”的结果送回,只影响标志位。 TEST指令常用于位测试,与条件转移指令一起用。 例:测试AL的内容是否为负数。 TEST AL,80H ;检查AL中D7=1? JNZ MINUS ;是1(负数),转MINUS … … ;否则(正数)不转移 MINUS: … … … … (5) 测试指令TEST
逻辑运算指令常见的用法总结 ⑴ 清进位标志位: AND AX,AX 或 OR AL,AL等 ⑵ 清零操作数:XOR AX,AX 不仅把AX清零,而且也影响了状态标志 ⑶ 把某几位取反:用XOR指令,把要取反的位和1异或,不变的位和0异或 ⑷ 清零或置位某几位:用AND指令清零,用OR指令置位
四、串操作指令 8086/8088指令系统中有一组十分有用的串操作指令,这些指令的操作对象不只是单个的字节或字,而是内存中地址连续的字节串或字串。在每次基本操作后,能够自动修改地址,为下一次操作做好准备。串操作指令还可以加上重复前缀,此时指令规定的操作将一直重复下去,直到完成预定的重复次数。串操作指令共有以下五条: MOVS (Move string) 串传送 CMPS (Compare string) 串比较 SCAS (Scan string) 串扫描 LODS (Load from string) 从串中取数据 STOS (Store in to string) 存数据到串中
串操作指令功能说明 ⑴ MOVS指令 MOVSB或 MOVSW以字节或字为单位在存储单元之间传送数据 可以使用REP前缀 ⑵ LODS指令 LODSB 或LODSW从内存中取出字节或字到累加器AL或AX 可以使用REP前缀,但意义不大。
⑶ STOS指令 STOSB或 STOSW从累加器中存字节或字到存储器 可以使用REP前缀 ⑷ CMPS指令 CMPSB或 CMPSW以字节或字为单位进行两个存储器操作数的比较 可以使用REPE/REPZ前缀 用源操作数-目的操作数
⑸ SCAS指令 SCASB或 SCASW 在数据串中查找AL或AX中的内容。 可以使用REPNE/REPNZ前缀
字符串操作指令的基本操作各不相同,但都具有以下几个共同特点:字符串操作指令的基本操作各不相同,但都具有以下几个共同特点: ⑴ 总是用SI寄存器寻址源操作数,用DI寄存器寻址目的操作数。源操作数常存放在现行的数据段,隐含段寄存器DS,但也允许段超越。目的操作数总是在现行的附加数据段,隐含段寄存器ES,不允许段超越。 ⑵ 每一次操作以后修改地址指针,是增量还是减量取决于方向标志DF。当(DF)=0时,地址指针增量,即字节操作时地址指针加1,字操作时地址指针加2。当(DF)=1时,地址指针减量,即字节操作时地址指针减1,字操作是地址指针减2。 ⑶ 有的串操作指令可加重复前缀,指令按规定的操作重复进行,重复操作的次数由CX寄存器决定。 ⑷ 若串操作指令的基本操作影响零标志ZF(如CMPS、SCAS),则可加重复前缀REPE/REPZ或REPNE/REPNZ,此时操作重复进行的条件不仅要求(CX)0,而且同时要求ZF的值满足重复前缀中的规定(REPE/REPZ要求(ZF)=1,REPNE/REPNZ要求(ZF)=0)。 ⑸ 串操作汇编指令的格式可以写上操作数,也可以只在指令助记符后加上字母“B”(字节操作)或“W”(字操作)。加上字母“B”或“W”后,指令助记符后面不允许再写操作数。
串指令使用的一般方法 MOV SI, 源串首地址 (或LEA SI, 源串) 设置源串地址 MOV DI, 目的串首地址 (或LEA DI, 目的串) 设置目标串地址 MOV CX, 串长度 设置串长度 CLD(或STD) 设置操作方向DF 串指令 具体串指操作指令,如MOVSB/W
data1 segment string1 db 1,2,3,4,5,6,7,8,9,10 data1 ends data2 segment string2 db 10 dup (‘1’) data2 ends code segment assume cs:code,ds:data1,es:data2 start: mov ax,data1 mov ds,ax mov ax,data2 mov es,ax LEA SI,BUFFER1 ;(SI)←源串首地址指针 LEA DI,BUFFER2 ;(DI)←目的串首地址指针 MOV CX,200 ;(CX)←字节串长度 CLD ;清方向标志DF REP MOVSB ;传送200个字节 mov ah,4ch int 21h code ends end start ⒈串传送指令MOVSB / MOVSW 例4.10将数据段中首地址为BUFFER1的200个字节传送到附加数据段首地址为BUFFER2的内存区中。 Li410.asm
执行的操作为:LODS指令是将一个字符串(源串,缺省在数据段中)中的字节或字逐个装入累加器AL或AX。 对字节:(AL)←((DS):(SI)) SI±1 对字:(AX)←((DS):(SI+1)(SI)) SI±2 串装入指令通常不加重复前缀。 LODSB等价于: LODSW等价于: MOV AL,[SI] MOV AX,[SI] INC SI INC SI INC SI 2.串装入指令LODSB / LODSW
例4.11内存中以BUFFER为首址的缓冲区内有10个非压缩型BCD码形式存放的十进制数,它们的值可能是0~9中的任意一个,将这些十进制数顺序显示在屏幕上。例4.11内存中以BUFFER为首址的缓冲区内有10个非压缩型BCD码形式存放的十进制数,它们的值可能是0~9中的任意一个,将这些十进制数顺序显示在屏幕上。 • 在屏幕上显示一个字符的方法(详见本书第五章第5.4节的DOS系统功能调用部分)是: • MOV AH,02H ;(AH)←DOS系统功能号(在屏幕上显示一个字符) • MOV DL,'Y' ;(DL)←待显示字符Y的ASCII码值 • INT 21H ;调用DOS的21H中断 • 根据题意可编程如下: • LEA SI,BUFFER ;(SI)←缓冲区首址 • MOV CX,10 ;(CX)←字符串长度 • CLD ;清状态标志位DF • MOV AH,02H ;(AH)←功能号 • GET: LODSB ;取一个BCD码到AL • OR AL,30H ;BCD码转换为ASCII码 • MOV DL,AL ;(DL)←字符的ASCII码 • INT 21H ;显示 • DEC CX ;(CX)←(CX)-1 • JNZ GET ;未完成10个字符则重复 Li411.asm
指令的操作为:将累加器AL或AX的值送存到内存缓冲区(目的串,缺省在附加数据段中)的某个位置上指令的操作为:将累加器AL或AX的值送存到内存缓冲区(目的串,缺省在附加数据段中)的某个位置上 对字节:((ES):(DI))←(AL) DI±1 对字:((ES):(DI+1)(DI))←(AX) DI±2 本指令用于把一块存储区域填充成某一初始值(即对存储区进行初始化)。 存储区域的首地址要预先设置到ES:DI中。 要存储到串中的数据要预先存到AL(AX)中。 3.串存储指令STOSB / STOSW
例4.12将字符‘#’装入以AREA为首址的100个字节中。例4.12将字符‘#’装入以AREA为首址的100个字节中。 LEA DI,AREA MOV AX,'#' MOV CX,100 CLD REP STOSW HLT Li412.asm
例4.13一个数据块由大写或小写的英文字母、数字和各种其它符号组成,其结束符是回车符CR(ASCII码为0DH),数据块的首地址为BLOCK1。将数据块传送到以BLOCK2为首地址的内存区,并将其中所用的英文小写字母(a~z)转换成相应的大写字母(A~Z),其余不变。例4.13一个数据块由大写或小写的英文字母、数字和各种其它符号组成,其结束符是回车符CR(ASCII码为0DH),数据块的首地址为BLOCK1。将数据块传送到以BLOCK2为首地址的内存区,并将其中所用的英文小写字母(a~z)转换成相应的大写字母(A~Z),其余不变。 前面已经讨论过英文小写字母与相应的大写字母的ASCII码之间有一定的关系,即只需将小写字母的ASCII码减20H,即可得到相应大写字母的ASCII码。程序见下:
lea si,block1 lea di,block2 cld next: lodsb cmp al,0dh jz done cmp al,61h ;cmp al,'a' jc ok cmp al,7bh ;cmp al,'z' jnc ok sub al,20h ok: stosb jmp next done: mov ah,4ch int 21h code ends end start data segment block1 db '123+-*/wW4AaBbCc!@@$ db $Dd##HhJjkKlL',0dh data ends edata segment block2 db 100 dup ('*') edata ends code segment assume cs:code,ds:data,es:edata start: mov ax,data mov ds,ax mov ax,edata mov es,ax Li413.asm
4.串比较指令CMPSB / CMPSW • 指令执行的操作为:将两个字符串中相应的元素逐个进行比较(即相减),但不将比较结果送回目的操作数,而反映在状态标志位上。 • CMPSB: ((DS):(SI))-((ES):(DI)) • SI±1, DI±1 • CMPSW: ((DS):(SI+1)(SI))-((ES):(DI+1)(DI)) • SI±2, DI±2 • 指令也可写成:CMPS dest, src • 比较的结果只反映在标志位上,串本身无变化。 • 本指令可用来检查两个串是否相等。
lea si,string1 lea di,string2 mov cx,letternum cld repe cmpsb jcxz allmatch dec si dec di allmatch: mov ah,4ch int 21h code ends end start data segment string1 db 'THIS IS TO COMPARE THE db TWO STRINGS!' letternum dw $-string1 data ends edata segment string2 db 'THIS IS tO COMPARE THE db TWO STRINGS!' edata ends code segment assume cs:code,ds:data,es:edata start: mov ax,data mov ds,ax mov ax,edata mov es,ax Li414.asm
5.串扫描SCASB / SCASW 执行的操作:在一个字符串中搜索特定的关键字。字符串的起始地址只能放在(ES:DI)中,不允许段超越 对字节:(AL)-((ES):(DI)) DI±1 对字: (AX)-((ES):(DI+1)(DI)) DI±2 • 搜索指令执行的仍是比较(减法)操作,结果只影响标志位。 • 要搜索的关键字放在AL(字节)或AX(字)中。 • 本指令用于在串中查找指定的信息。
SCAS指令加上重复前缀后,可对串进行连续扫描比较:SCAS指令加上重复前缀后,可对串进行连续扫描比较: • 若前缀为REPZ,则表示比较结果相等且(ZF=1)且串未结束(CX≠0),则继续比较。 • 若前缀为REPNZ,则表示比较结果不相等(ZF=0)且串未结束(CX≠0)就继续比较。
ES段 例:在ES段的偏移1000H开始处存有10个ASCII码。搜索’E’,若找到则记下搜索次数及存放地址,并在屏幕上显示’Y’;若未找到则显示’N’。(见右图) 在屏幕上显示一个字符的 指令段如下:(参见附录C.3) MOV DL,<字符> MOV AH,2 INT 21H 实现题目要求的程序段见下页: 41 ’A’ 1000H 42 ’B’ 43 ’C’ 44 ’D’ 45 ’E’ 46 ’F’ . . .
lea di,string mov al,0dh mov cx,letternum cld repne scasb jz match mov dl,'N' jmp dspy match: dec di mov dl,'Y' dspy: mov ah,02h int 21h mov ah,4ch int 21h code ends end start edata segment string db '123pppeewqL‘ db 0dh,'owe123' letternum equ $-string edata ends code segment assume cs:code,es:edata start: mov ax,edata mov es,ax Li415.asm
关于串操作指令的重复前缀、操作数以及地址指针所用的寄存器等关于串操作指令的重复前缀、操作数以及地址指针所用的寄存器等 情况归纳如表4.10所示。