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

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

例题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

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