汇编语言的分支程序设计与循环程序设计

汇编语言的分支程序设计:

例题1:比较三个无符号数的大小,按照从大到小的顺序排列

关键的语句是:无符号数,因此所用语句是JAE实现跳转:

此外比较两个操作数所用的是CMP,交换两个操作数的是XCHG

书上的代码:

代码1:这样写法比较占用寄存器,但是寄存器之间交换数值比较快

;程序名称:实现三个无符号数的由小到大的排序
DATAS  SEGMENT
BUFFER   DB   87,234,123
DATAS  ENDS

CODES   SEGMENT
                    ASSUME  CS:CODES,DS:DATAS
START:    MOV   AX,DATAS
                    MOV    DS,AX
                    
                    MOV    SI,OFFSET  BUFFER;把buffer的 偏移量交给变址寄存器SI
                    MOV    AL,[SI]
                    MOV    BL,[SI+1]
                    MOV    CL,[SI+2]
                    CMP        AL,BL  ;比较AL,和BL的大小
                    JAE            NEXT1  ;如果AL>BL转移到next1
                    XCHG   AL,BL;交换AL,和BL
NEXT1:   CMP     AL,CL  ;比较AL和CL的大小
                    JAE            NEXT2
                    XCHG    AL,CL
NEXT2:   CMP     BL,CL
                    JAE       NEXT3
                    XCHG    BL,CL
NEXT3:   MOV      [SI],AL    
                    MOV      [SI+1],BL
                    MOV      [SI+2],CL
                    MOV           AH,4CH
                    INT                21H
CODES    ENDS
                    END    START
View Code

 代码2:这样的写法只用了AL,但是寄存器与存储器操作数指教的操作比较慢

 1 ;程序功能,实现三个数的大小排序
 2 DATAS     SEGMENT
 3 BUFFER   DB    87,234,123
 4 DATAS     ENDS
 5 
 6 
 7 CODES      SEGMENT
 8 ASSUME  CS:CODES,DS:DATAS
 9 START:    MOV   AX,DATAS
10                     MOV   DS,AX
11                     
12                     MOV     SI,OFFSET  BUFFER
13                     MOV     AL,[SI]
14                     CMP     AL,[SI+1]
15                     JAE       NEXT1
16                     XCHG   AL,[SI+1]
17                     MOV     [SI],AL
18 NEXT1:   CMP      AL,[SI+2]
19                     JAE        NEXT2
20                     XCHG    AL,[SI+2]
21                     MOV      [SI+1],AL
22 NEXT2:   MOV       AL,[SI+1]
23                CMP      AL,[SI+2]
24                JAE        NEXT3
25                XCHG     AL,[SI+2]
26                MOV       [SI+1],AL
27 NEXT3:   MOV        AH,4CH
28                     INT         21H
29 CODES    ENDS
30                    END        START
View Code

例题2:写一个实现一位十六进制的数转换为对应的ASCII码的程序 

;程序功能,实现16进制数值转换成对应的ASCII码
;原理:但十六进制数值为0到9的时候,对应的ASCII=x+30H
; 当十六进制为10到15的时候,对应的ASCII = x+37H

这里关键的语句是 JA,大于9的话,转移

之后便是程序跳转指令:JMP,但标号很多的时候,可以用LAB1,LAB2,LAB3这种类型的标号

 1 ;程序功能,实现16进制数值转换成对应的ASCII码
 2 ;原理:但十六进制数值为0到9的时候,对应的ASCII=x+30H
 3 ;            当十六进制为10到15的时候,对应的ASCII = x+37H
 4 DATAS            SEGMENT
 5 XX         DB      4
 6 ASCII     DB      ?
 7 DATAS   ENDS
 8 ;
 9 
10 CODE     SEGMENT 
11 ASSUME       CS:CODE,DS:DATAS
12                      MOV   AX,DATAS
13                      MOV   DS,AX
14                      
15 START:         MOV   AL,XX
16                           AND    AL,0FH
17                     CMP   AL,9
18                     JA     LAB1
19                     ADD    AL,30H
20                     JMP    LAB2
21 LAB1:          ADD     AL,37H
22 LAB2:          MOV    ASCII,AL
23                           MOV    AH,4CH
24                           INT      21H
25 CODE           ENDS
26                     END     START
View Code

 例题3:写一个程序实现ASCII转换成对应的十六进制

 1 ;ASCII 转换为16进制数
 2 DATA     SEGMENT
 3 XX          DB       ?
 4 ASCII      DB      'a'
 5 DATA      ENDS
 6 ;
 7 
 8 CODE      SEGMENT
 9          ASSUME    CS:CODE,DS :DATA
10 START:            MOV   AX,DATA
11                         MOV   DS,AX
12                          MOV    AL,ASCII
13                          CMP   AL,0
14 LAB:           JB      LAB5
15                         MOV   AH,AL
16                         SUB    AH,'0'
17                         CMP   AL,'9'
18                         JBE     LAB6
19                         CMP   AL,'A'
20                         JB       LAB5
21                         MOV   AH,AL
22                         SUB    AH,'A' -10
23                         CMP    AL,'F'
24                         JBE      LAB6
25                         CMP     AL,'a'
26                         JB        LAB5
27                         MOV    AH,AL
28                         SUB      AH,'a' -10
29                         CMP      AL,'f'
30                         JBE        LAB6
31                         ;
32 LAB5 :         MOV      AH,-1
33 LAB6:                          MOV       XX,AH
34                           MOV       AH,4CH
35                           INT         21H
36                           CODE      ENDS
37                                          END         START
View Code

利用地址表实现多向分支

当要根据某个变量的值,进行多种不同的处理时,就会产生了多向分支,多向分支在高级语言中常常用switch实现,在汇编语言中是使用地址表实现的

DSEG    SEGMENT

……………………

COMTAB  DW  COMA,COMB,COMC,COMD

              DW  COME,COMF,COMG,COMH

DSEG      ENDS

……………………

计算如果地址表内的地址,之后调用路口地址表即可

之后跳转指令用这个 JMP   COMTAB[BX]

循环程序设计:

例题1:用计数法控制循环

 1 ;程序功能,说明根据计数法控制循环体
 2 DSEG        SEGMENT
 3 SUM         DW            ?
 4 DSEG        ENDS
 5 
 6 CSEG            SEGMENT
 7 ASSUME         CS:CSEG
 8 
 9 START:     MOV    AX,40H
10                     MOV DS,AX
11                     MOV    SI,0
12                     MOV CX,1024
13                     XOR    AX,AX
14 AGAIN:        ADD  AX,[SI]
15                     INC        SI
16                     INC     SI
17                     LOOP        AGAIN
18                     ;
19                     ASSUME  DS:DSEG
20                     MOV    BX,DSEG
21                     MOV    DS,BX
22                     MOV    SUM,AX
23                     MOV    AH,4CH
24                     INT       21H
25                     CSEG    ENDS
26                                     END    START
View Code

本例程中所用的关键指令为LOOP,LOOP指令使用的方法是在初始化CX的初值,每次执行一次LOOP,CX寄存器会减一

此外,还用了SI这个源地址指针,因为定义的变量时字,所以SI在循环的时候,调用了两次INC,在得到校验和的时候,重新设置了

数据段寄存器,以便于保存校验和

例题2:不用乘法指令实行乘法运算

假设乘法时234*125,不用乘法指令,可以有移位和累加两种方法

方法一:累加,可以看成是125个234相加,因此循环的时候,循环次数是CX=125

 1 ;程序功能,说明根据计数法控制循环体
 2 DSEG        SEGMENT
 3 SUM         DW            ?
 4 DSEG        ENDS
 5 
 6 CSEG            SEGMENT
 7 ASSUME         CS:CSEG
 8 
 9 START:     MOV    AX,40H
10                     MOV DS,AX
11                     MOV    SI,0
12                     MOV CX,1024
13                     XOR    AX,AX
14 AGAIN:        ADD  AX,[SI]
15                     INC        SI
16                     INC     SI
17                     LOOP        AGAIN
18                     ;
19                     ASSUME  DS:DSEG
20                     MOV    BX,DSEG
21                     MOV    DS,BX
22                     MOV    SUM,AX
23                     MOV    AH,4CH
24                     INT       21H
25                     CSEG    ENDS
26                                     END    START
View Code

这里用的指令时XOR,自己和自己异或等于0,还有JCXZ这条指令,JCXZ表示但cx寄存器为0的时候跳转

例题3:把16位的二进制数转换为5位十进制数值,为了简单,设二进制数时无符号的,采用8421BCD码表示十进制数

 1 ;程序功能,实现十六位二进制数转换为十进制数
 2 DSEG        SEGMENT
 3 DATA         DW        23456
 4 BUFFER    DB         5    DUP(0)
 5 JM                DW        10000,1000,100,10,1
 6 DSEG        ENDS
 7 
 8 CSEG            SEGMENT
 9                     ASSUME    CS:CSEG,DS:DSEG
10         START:MOV AX,SEG    DATA
11                         MOV DS,AX
12                         MOV DI,OFFSET  JM
13                         MOV SI,OFFSET BUFFER
14                         MOV CX,5
15                         MOV AX,DATA
16                         XOR DX,DX
17         NEXT: MOV BX,[DI]
18                      ADD DI,2
19                      DIV BX
20                      MOV [SI],AL
21                      INC SI
22                      MOV AX,DX
23                      XOR DX,DX
24                      LOOP NEXT
25                      MOV AX,4C00H
26                      INT 21H
27                      CSEG ENDS
28                                      END START
View Code

这里用了两个比较重要的概念,因为是16位的数值,因此必须明白,在进行16位的除法运算时,商保存在AX中,余数保存在DX中

在进行8位的除法运算时,AL保存商,AH保存余数

SEG可以返回变量所在的段值,OFFSET返回变量的偏移值,因此经常可以看到 MOV DI,OFFSET JM等等

在进行除法运算时,DIV BX隐含的是AX/BX

例题4

把一个字符串中的大写字母改成小写字母的程序

 1 ;程序功能,把字符串中的大写字母改成小写字母
 2 DSEG        SEGMENT
 3 STRING   DB  'HOW  arR  YOu I',0
 4 DSEG          ENDS
 5 CSEG         SEGMENT
 6                 ASSUME  CS:CSEG,DS:DSEG
 7         START: MOV AX,DSEG
 8                         MOV DS,AX
 9                         MOV SI,OFFSET STRING
10         AGAIN: MOV AL,[SI]
11                         OR   AL,AL
12                         JZ     OK
13                         CMP AL,'A'
14                         JB     NEXT
15                         CMP AL,'Z'
16                         JA        NEXT
17                         OR    AL,20H
18                         MOV [SI],AL
19         NEXT:   INC   SI
20                         JMP  AGAIN
21             OK:   MOV AX,4C00H
22                         INT   21H
23            CSEG  ENDS
24                            END   START
View Code

这里需要注意的是,在字符串后面添加了一个0,这里是用来判断字符串是否为结束完,用OR AL,AL来判断,因为自己和自己相或,得到的是本身,只有和0相或,才能得到0

因此用JZ来转移到OK,

此外

比较CMP AL,'A',如果小的话用的是JB转移,

判断CMP AL 'Z',如果大于的话JA转移,

 经过上面的判断可以得出AL中是大写字母,因此用OR AL,20H,把大写字母转换为小写字母

如果上述条件不满足,则INC SI

例题5

;写一个程序判定从地址0040:0000H开始的2048个内存字节党员中是否有字节A
;如果有字符A,则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移
;送到000:03FEH党员中,如果没有,则把特征值送到0FFFFH送到上述指定单元

 1 ;写一个程序判定从地址0040:0000H开始的2048个内存字节党员中是否有字节A
 2 ;如果有字符A,则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移
 3 ;送到000:03FEH党员中,如果没有,则把特征值送到0FFFFH送到上述指定单元
 4 ;
 5 SEGADDR  = 40H
 6 OFFADDR = 0
 7 COUNT = 2048
 8 KEYCHAR = 'A'
 9 SEGRESU = 0
10 OFFRESU = 3FEH
11 ;
12 CSEG            SEGMENT
13                     ASSUME  CS:CSEG
14                     START:MOV AX,SEGADDR
15                                   MOV DS,AX
16                                   MOV SI,OFFADDR
17                                   MOV CX,COUNT
18                                   MOV AL,KEYCHAR
19                     NEXT: CMP AL,[SI]
20                                   JZ OK
21                                   INC SI
22                                   LOOP NEXT
23                                   MOV SI,0FFFFH
24                     OK:     MOV AX,SEGRESU
25                                   MOV DS,AX
26                                   MOV BX,OFFRESU
27                                   MOV [BX],SI
28                                   MOV AH,4CH
29                                   INT 21H
30                     CSEG   ENDS
31                                     END  START
View Code

代码分析:首先是等号的运用  =  ,常量的定义,类似于define

在查找的时候,调用CMP AL,[SI],这个查找到的话,调用JZ类似于若相等,则跳转

例题6

;设缓冲区中有一组单字节有符号数,以0为结束标志,写一个程序实现如下功能
;把前面5个正数一次送到缓冲区PDATA中,把前面5个负数送到缓冲区MDATA中,
;如果正数或者负数不足,则用0补足

 1 ;设缓冲区中有一组单字节有符号数,以0为结束标志,写一个程序实现如下功能
 2 ;把前面5个正数一次送到缓冲区PDATA中,把前面5个负数送到缓冲区MDATA中,
 3 ;如果正数或者负数不足,则用0补足
 4 
 5 MAX_COUNT  = 5
 6 DSEG         SEGMENT
 7 DATA         DB  3,-4,5,6,-7,8,-9,-10,-1,-32,-132,27,58,44,-12,0
 8 PDATA         DB  MAX_COUNT DUP (?)
 9 MDATA    DB  MAX_COUNT DUP (?)
10 DSEG   ENDS
11 ;
12 CSEG            SEGMENT
13                     ASSUME CS:CSEG,DS:DSEG
14             START: MOV AX,DSEG
15                             MOV DS,AX
16                             MOV CX,MAX_COUNT
17                             MOV SI,OFFSET PDATA
18                             MOV DI,OFFSET MDATA
19                             MOV AL,0
20             NEXT1: MOV [SI],AL
21                             MOV [DI],AL
22                             INC SI
23                             INC DI
24                             LOOP NEXT1
25                             MOV BX,OFFSET DATA
26                             XOR SI,SI
27                             XOR DI,DI
28             NEXT2: MOV AL,[BX]
29                             INC BX
30                             CMP AL,0
31                             JZ OVER
32                             JG PLUS
33                             CMP DI,MAX_COUNT
34                             JAE CONT
35                             MOV MDATA[DI],AL
36                             INC DI
37                             JMP SHORT CONT
38             PLUS:  CMP SI,MAX_COUNT 
39                             JAE  CONT
40                             MOV PDATA[SI],AL
41                             INC SI
42             CONT: MOV AX,SI
43                           ADD AX,DI
44                           CMP AX,MAX_COUNT +MAX_COUNT
45                           JB NEXT2
46             OVER:  MOV AH,4CH
47                             INT 21H
48                 CSEG ENDS
49                             END START
View Code

这个题目考了很多地方,当程序需要三个指针的时候,这个时候BX,SI,DI都可以作为指针

这个题目相当的给力,可以好好看看

版权所有:转载注明链接地址:http://www.cnblogs.com/fengdashen/p/3704148.html

原文地址:https://www.cnblogs.com/fengdashen/p/3704148.html