Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226366
  • 博文数量: 45
  • 博客积分: 1850
  • 博客等级: 上尉
  • 技术积分: 473
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-11 10:21
文章分类
文章存档

2006年(17)

2005年(28)

我的朋友

分类:

2006-04-12 20:16:21

需要重复执行某段程序时,就可以利用循环程序结构。循环结构一般是根据某一条件判断为真或假来确定是否重复执行循环体,条件永真或无条件的重复循环就是逻辑上的死循环(永真循环、无条件循环)。
一、用循环或转移指令实现循环。
专门用于循环控制的指令有LOOP、LOOPE/LOOPZ和LOOPNE/LOOPNZ,从某种意义上讲,他们都是计数循环,即用于循环次数已知或最大循环次数已知的循环控制,且需预先将循环次数或最大尊大循环次数植入CX寄存器。
例26.1:计算1~100数字之和,并将结果存入字变量SUM中。
分析:程序要求SUM=1+2+3+...+99+100,这是一个典型的计数循环,完成100次简单加法,循环开始将被加数清0,加数置1,循环体内完成一次累加,每次的加数递增1。LOOP指令要求循环次数预置给CX,每次循环CX递减1,这样,循环体内加数就可以直接用循环控制变量CX,简化循环体,完成与题目等价的100~1的累加。
    .model small
    .stack
    .data
sum  dw ?
    .code
    .startup
    xor ax,ax
    mov cx,100
again:
    add ax,cx
    loop again
    mov sum,ax
    .exit 0
    end

例26.2:确定字变量wordX中为1的最低位数(0~15),并将结果存于变量byteY中;若wordX中没有为1的位,则将-1存入byteY。
分析:对wordX中的16个位,从低向高一次循环测试,第一个为1的位数便是题目所求,设循环的最大次数为16,循环开始前将计位数置-1,循环体内每次对计位数加1后,测试目标最低位,再将目标循环右移1位。由于循环移位指令不影响ZF标志位,故可根据当前ZF的设置情况得到判断:若ZF=0,则测试结果非0,被测位为1,从而找到定位,退出循环;若ZF=1,则被测位不满足要求,应进行下一次循环继续测试目标的次低位。
    .model small
    .stack 256
    .data
wordX dw 56
byteY db ?
    .code
    .startup
    mov ax,wordX
    mov cx,16
    mov dl,-1
again:
    inc dl
    test ax,1
    ror ax
    loope again
    je notfound
    mov byteY,dl
    jmp done
notfound:
    mov byteY,-1
done:
    .exit 0
    end
例26.3:把一个字符串中的所有大写字母改写为小写字母,该字符串以0结尾。
分析:这是一个循环次数不确定的循环程序结构,宜用转移指令决定是否循环结束,循环体判断每个字符,如果是大写字母就转换为小写字母,否则不予处理;循环体中具有分支结构。大小写字母的ASCII码不同之处:大写字母D5=0,而小写字母D5=1。

    .model small
    .stack 256
    .data
string db 'HeLLO,eveRyboDy!',0
    .code
    .startup
    mov bx,offset string
again:
    mov al,[bx]
    or al,al
    jz done
    cmp al,'A'
    jb next
    cmp al,'Z'
    ja next
    or al,20h
    mov [bx],al
next:
    inc bx
    jmp again
done:
    .exit 0
    end
例26.4:采用“冒泡法”把一个长度已知的数组元素按从小到大排序。假设数组元素为无符号字节量。
分析:冒泡法是从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不大于后一个元素,将所有元素比较完后,最大的元素排到了最后;然后,除掉最后一个元素之外的元素依上次方法再进行比较,得到次大的元素排在后面,如此重复,直至完成就实现元素从小到大排序。可见,这是一个双重循环程序结构。外循环由于循环次数已知,可以用LOOP指令实现,内循环次数每次外循环后减少一次,用DX表示。循环体比较两个元素大小,又是一个分支结构。
    .model small
    .stack 256
    .data
count  equ 20
array  db 56h,23h,37h,78h,0ffh,0,12h,90h,64h,0b0h
       db 78h,80h,34h,1,4,0fh,2ah,46h,32h,42h
    .code
    .startup
    mov cx,count
    dec cx
outlp:
    mov dx,cx
    mov bx,offset array
inlp:
    mov al,[bx]
    cmp al,[bx+1]
    jna next
    xchg al,[bx+1]
    mov [bx],al
next:
    inc bx
    dec dx
    jnz inlp
    loop outlp
    .exit 0
    end
二、用循环控制伪指令实现循环
用处理器指令实现的循环控制结构非常灵活,但不易读、容易出错,不小心就会将循环和分支混淆,MASM6.x提供用于循环控制结构的流程控制伪指令:.WHILE和.ENDW、.REPEAT和.UNTIL以及.REPEAT和.UNTILCXZ,另外还有.BREAK和.CONTINUE分别表示无条件退出循环和转向循环体开始。利用这些可以形成两种基本循环结构形式:分别是先判断循环条件的WHILE结构和后判断循环条件的UNYIL结构。如下图:

WHILE结构的循环控制伪指令的格式为:
.WHILE 条件表达式        ;条件为真,执行循环体
    循环体
.ENDW                    ;循环体结束
例26.1实现1~100求和,可以编写如下:
   xor ax,ax
   mov cx,100
   .while cx!=0
      add ax,cx
      dec cx
   .endw
   mov sum,ax
UNTIL结构的循环控制伪指令的格式为:
.REPEAT               ;重复执行循环体
   循环体
.UNTIL 条件表达式     ;直到条件为真
例26.1又可编写为如下:
.repeat
  add ax,cx
  dec cx
.until cx==0
.UNTIL结构还有一种格式:
.REPEAT                 ;重复执行循环体
  循环体
.UNTILCXZ [条件表达式]  ;cx←cx-1 ,直到cx=0或条件为真
不带表达式的.repaet/.untilcxz伪指令将汇编成一条loop指令,即重复执行直到CX减1后,CX=0。带有表达式的.repeat /.untilcxz伪指令的循环结束条件是CX减1后等于0或指定的条件为真。.untilcxz伪指令的表达式只能是比较寄存器与寄存器、存储单元和常数,以及存储单元与常数相等(==)或不等(!=)。
例26.5:设array是100个字元素的数组,试计算其中前若干个非负数之和,直到出现第一个负数为止,并将结果存入result单元(不考虑进位和溢出)。
分析:由于已知array中最多有100个非负数,所以可以采用计数循环。循环开始前置循环计数器CX为100,累加和清零。依据题意,循环体内每取一个元素,都要判断是否大于等于0,若是则累加,否则应立即退出整个循环。循环出口后将累加和存入result单元。
    .model small
    .stack 256
    .data
array sword 100 dup(?)
result sword ?
    .code
    .startup
    mov cx,100
    xor ax,ax
    lea bx,array
    .repeat
      .if sword ptr [bx] >= 0
          add ax,[bx]
      .else
          .break
      .endif
      inc bx
      inc bx
    .untilcxz
    mov result,ax
    .exit 0
    end
相应的LST文件如下:
 
Microsoft (R) Macro Assembler Version 6.11      04/12/06 17:07:55
l26-5.asm           Page 1 - 1

        .model small
        .stack 256
 0000        .data
 0000  0064 [   array sword 100 dup(?)
        0000
       ]
 00C8 0000   result sword ?
 0000        .code
        .startup
 0000      :
 0000  BA ---- R    *     mov    dx, DGROUP
 0003  8E DA     *     mov    ds, dx
 0005  8C D3     *     mov    bx, ss
 0007  2B DA     *     sub    bx, dx
 0009  D1 E3     *     shl    bx, 001h
 000B  D1 E3     *     shl    bx, 001h
 000D  D1 E3     *     shl    bx, 001h
 000F  D1 E3     *     shl    bx, 001h
 0011  FA     *     cli   
 0012  8E D2     *     mov    ss, dx
 0014  03 E3     *     add    sp, bx
 0016  FB     *     sti   
 0017  B9 0064       mov cx,100
 001A  33 C0       xor ax,ax
 001C  8D 1E 0000 R      lea bx,array
        .repeat
 0020      :
          .if sword ptr [bx] >= 0
 0020  83 3F 00     *     cmp    sword ptr [bx], 000h
 0023  7C 04     *     jl     @C0002
 0025  03 07             add ax,[bx]
          .else
 0027  EB 02     *     jmp    @C0004
 0029      :
              .break
 0029  EB 04     *     jmp    @C0006
          .endif
 002B      :
 002B  43         inc bx
 002C  43         inc bx
        .untilcxz
 002D  E2 F1     *     loop   @C0001
 002F      :
 002F  A3 00C8 R      mov result,ax
        .exit 0
 0032  B8 4C00     *     mov    ax, 04C00h
 0035  CD 21     *     int    021h
        end
Microsoft (R) Macro Assembler Version 6.11      04/12/06 17:07:55
l26-5.asm           Symbols 2 - 1
 

Segments and Groups:
                N a m e                 Size     Length   Align   Combine Class
DGROUP . . . . . . . . . . . . . GROUP
_DATA  . . . . . . . . . . . . . 16 Bit  00CA   Word   Public  'DATA' 
STACK  . . . . . . . . . . . . . 16 Bit  0100   Para   Stack   'STACK' 
_TEXT  . . . . . . . . . . . . . 16 Bit  0037   Word   Public  'CODE' 

Symbols:
                N a m e                 Type     Value    Attr
@CodeSize  . . . . . . . . . . . Number  0000h 
@DataSize  . . . . . . . . . . . Number  0000h 
@Interface . . . . . . . . . . . Number  0000h 
@Model . . . . . . . . . . . . . Number  0002h 
@Startup . . . . . . . . . . . . L Near  0000   _TEXT 
@code  . . . . . . . . . . . . . Text     _TEXT
@data  . . . . . . . . . . . . . Text     DGROUP
@fardata?  . . . . . . . . . . . Text     FAR_BSS
@fardata . . . . . . . . . . . . Text     FAR_DATA
@stack . . . . . . . . . . . . . Text     DGROUP
array  . . . . . . . . . . . . . Word  0000   _DATA 
result . . . . . . . . . . . . . Word  00C8   _DATA 
    0 Warnings
    0 Errors
阅读(2476) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~