8086汇编——循环程序设计

一、循环指令

LOOP

格式: LOOP OPR
执行的操作: (CX) ←(CX)-1。 若CX≠0,跳转到标号OPR处循环执行;若CX=0,则退出循环,执行LOOP的下一条指令。

8086汇编——循环程序设计_第1张图片
LOOPZ/LOOPE

格式: LOOPZ/LOOPE OPR

执行的操作: (CX) = (CX)-1。 若CX≠0,并且ZF=1,则跳转到标号OPR处循环执行; 若CX=0,或者ZF=0,则执行下一条指令。

功能:结果为0或相等循环。当执行到LOOPZ/LOOPE时,如果之前的指令结果为0或者相等继续循环,如果结果不为0或者不相等,提前退出循环,即使计数值CX还未减为0。

如果CMP条件不成立,则跳出循环。
8086汇编——循环程序设计_第2张图片

LOOPNZ/LOOPNE

格式: LOOPNZ/LOOPNE OPR

执行的操作: (CX) = (CX)-1。 若CX≠0,并且ZF=0,则跳转到标号OPR处循环执行;若CX=0,或者ZF=1,则执行下一条指令。

说明:结果不为0或不相等循环。当执行到LOOPNZ/LOOPNE时,如果之前的指令结果不为0或者不相等继续循环,如果结果为0或者相等,提前退出循环,即使计数值CX还未减为0。

如果CMP条件成立,则跳出循环。
8086汇编——循环程序设计_第3张图片

二、串处理

在前面,我们多次用到查ASCII码表、求数组元素的累加值、在字符串中查找字母等操作。这些操作都可归结为对数据串的处理,在此之前我们利用其他指令编程实现了串操作。利用汇编语言提供的专门的串处理指令,可以简化程序、方便编程,使程序清晰易读。

串传送

MOVS DST, SRC
MOVSB
MOVSW

执行的操作:串中的数据按字节传送或按传送。

格式要求:

  • 串传送指令要求源串的偏移地址由SI寄存器指出,目的串的偏移地址由DI寄存器指出,传送次数由CX指出。串传送指令要求和重复前缀REP连用。
  • REP 前缀功能为:重复串操作直到(CX) = (CX) -1=0。
  • 串的传送方向由方向标志DF指出。若DF=0,传送时存储单元地址SI和DI自动加1(字节单元)或自动加2 (字单元);若DF=1, SI 和DI自动减量。CLD 指令使DF =0,STD指令使DF=1。

功能:和REP连用时以字节或字的形式重复传送,直到CX为0为止。

REP MOVS BYTE PTR ES :[DI],DS:[SI]

这种格式的双操作数要显式地指出源和目的操作数的地址和属性,例如,传送字节数据串。

REP MOVSB 以字节形式重复传送
REP MOVSW 以字形式重复传送

两种格式隐含地指出源和目的串的地址和属性,即指令中没有操作数,只有操作码:

串比较

CMPS DST, SRC
CMPSB
CMPSW

分别从源串和目的串中逐个取出字节数据或字数据做相减操作,结果不回送,根据比较结果改变标志位。

说明:第一种格式的双操作数要显式地指出源和目的操作数的地址和属性。后两种格式隐含地指出源和目的串的地址和属性。CMPSB为字节串比较,CMPSW为字串比较。

格式要求:

  • 源串的偏移地址由SI寄存器指出,目的串的偏移地址由DI寄存器指出,比较次数由CX指出。串比较指令和重复前缀REPZ/ REPE或REPNZ/REPNE连用。
  • REPZ/ REPE前缀功能为:结果为0或相等则重复操作。若CX≠0,且ZF=1,则重复,(CX) = (CX)-1,直到CX =0。 如果结果不为0或者不相等,提前退出重复操作,此时CX还没有减为0,SI 和DI已经增量。
  • REPNZ/REPNE 前缀:结果不为0或不相等则重复。若CX≠0,且ZF=0,则重复,(CX) = (CX)-1, 直到CX=0。如果结果为0或者相等,提前退出重复操作,同样CX还没有减为0,SI和DI已经增量。

串扫描

SCAS DST
SCASB
SCASW

在目的串DST中查找与AL或AX相同(或不相同)的字节或者字,结果不保存,根据查找结果改变标志位。SCASB为字节串扫描,SCASW 为字串扫描。

格式要求:

  • 目的串在附加段中,偏移地址由DI寄存器指出,扫描次数由CX指出;
  • 每扫描一次,DI自动增量或减量,CX 减1;
  • 串扫描指令和重复前缀REPZ/ REPE或REPNZ/REPNE连用。

注意:

  • 和REPZ/REPE连用时,扫描结果为0或相等则在串中重复扫描,直到找到与AL或AX不相同的数退出扫描。此时CX没有减为0,DI 已经增量。
  • 和REPNZ/ REPNE连用时,扫描结果不为0或不相等则在串中重复扫描,直到找到与AL或AX相同的数退出扫描。同样CX没有减为0, DI已经增量。

8086汇编——循环程序设计_第4张图片

串获取

LODS SRC
LODSB
LODSW

从源串SRC中取出一字节或者字,放入AL或AX中。

源串在数据段定义,偏移地址由SI指出。如果与REP连用,则连续取出字节或字。取出次数由CX指出。

串存入

STOS DST
STOSB
STOSW

将AL或AX内容存人附加段的目的串中。

格式要求:

  • 目的串在附加段定义,偏移地址由DI指出。
  • 如果与REP连用,则将AL或AX中的内容连续存人目的串。存入次数由CX指出。

三、多重循环

在多重循环程序编写过程中,要注意循环体内条件转移指令的转移方向。一般来说,可以从内循环跳入外循环,或者跳出外循环,不允许从外循环跳入内循环或者直接从循环外跳入循环内。

8086汇编——循环程序设计_第5张图片
8086汇编——循环程序设计_第6张图片

四、样例

判断学号末位数并按下述要求进行累加操作后输出结果。根据学号长度在数据段中定义类型为字节的存储单元stu_no;从键盘输入个人学号,保存至stu_no;对个人学号最后一位进行判断;如果是偶数,则对stu_no内偏移地址为偶数的字节单元进行求和;如果是奇数,则对stu_no内偏移地址为奇数的字节单元进行求和;

个人思路,有两个思路,一是在输入时将偏移地址为偶数和奇数地分别相加,看最后一位地输出相应结果。第二是输入完毕后再判断相加。

在此写一下第二种情况地代码:

DATAS SEGMENT
    stu_no DB 20 DUP(?)
    LL DW 2 DUP(?)
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    MOV AH,01H
    MOV BX,0000H
    MOV CX,0020H
SS1: 
    INT 21H
    MOV stu_no[BX],AL
    INC BX
    CMP AL,0DH ;如果是回车则退出
    LOOPNE SS1
    SUB BX,01H
    MOV stu_no[BX],0H
    SUB BX,01H ;最后一位数偏移地址为BX-2
    MOV LL,BX
    MOV AL,stu_no[BX]
    SUB AL,30H
    TEST AL,01H
    JZ EVENNUMBER
    MOV BX,0001H
    MOV AX,0000H
     ;对于偶数奇数两种情况而言只是起始位置不一样而已
EVENNUMBER:  
    MOV AX,0000H
    MOV BX,0000H
SS2:
    ADD AL,stu_no[BX]
    SUB AL,30H
    ADD BX,02H
    CMP BX,LL
    JA OUT1  ;如果大于则转移到out1
    LOOPNE SS2
   OUT1:
    AAM 
    MOV BX,AX
    ADD BX,3030H
    MOV AH,02H
    MOV DL,BH
    INT 21H
    MOV DL,BL
    INT 21H
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START

你可能感兴趣的:(8086汇编程序设计)