分支程序的设计
分支程序结构有单分支if-then和双分支if-then-else两种基本形式,如果分支处理中又嵌套有分支,或者说具有多个分支走向时,即为逻辑上的多分支形式。
一、用转移指令实现分支
条件转移jcc和无条件转移JMP指令用于实现程序的分支结构,JMP指令仅实现了转移到指定位置,Jcc指令则根据条件转移到指定位置或不转移而顺序执行后续指令序列。如下流程图:
注意的是转移指令实现了转移,但在第一个分支执行完后不会自动跳过第二个分支体,而是根据程序的顺序继续执行指令。若要实现两分支中执行一支,前一个(第一个)分支体后,必须有一条无条件转移指令跳到第二个分支体之后,即分支汇点处。
条件转移语句不支持一般的条件表达式,它是根据当前某些标志位的设置情况实现转移或不转移。
一个典型的单分支结构如下:
mov ax,X
sub ax,Y
jns nonneg
neg ax
nonneg:
mov result,ax
例25.1:判断方程
是否有实根,若有实根则将字节变量tag置1,否则置0(假设a、b、c均为字节变量,表达-127——+127的数据)。
分析:二元一次方程有根的条件是:
。依据题意,首先计算出b的平方和4ac,然后比较两者大小,根据比较的结果分别给tag赋不同的值。
.model small
.stack 256
.data
_a db ?
_b db ?
_c db ?
tag db ?
.code
.startup
mov al,_b
imul al
mov bx,ax
mov al,_a
imul _c
mov cx,4
imul cx
cmp bx,ax
jge yes
mov tag,0
jmp done
yes: mov tag,1
done: .exit 0
end
如果分支较多,我们可以借鉴中断向量表的工作原理,构造一个入口地址表,如下例:
例25.2:程序根据键盘输入的1——8数字转向不同的处理程序段
分析:在数据段定义一个存储区,顺序存放8个处理程序段的起始地址。由于所有程序都在一个代码段,所以用字定义伪指令dw存入偏移地址。如果输入的不是1——8数字,系统自动重新提示输入,如果数字有效,则形成表中的正确偏移,并按地址表跳转。
.model small
.stack 256
.data
msg db 'input number(1--8):',0dh,0ah,'$'
msg1 db 'chapter1:11111111111111111111',0dh,0ah,'$'
msg2 db 'chapter2:22222222222222222222',0dh,0ah,'$'
msg3 db 'chapter3:33333333333333333333',0dh,0ah,'$'
msg4 db 'chapter4:44444444444444444444',0dh,0ah,'$'
msg5 db 'chapter5:55555555555555555555',0dh,0ah,'$'
msg6 db 'chapter6:66666666666666666666',0dh,0ah,'$'
msg7 db 'chapter7:77777777777777777777',0dh,0ah,'$'
msg8 db 'chapter8:88888888888888888888',0dh,0ah,'$'
table dw disp1,disp2,disp3,disp4,disp5,disp6,disp7,disp8
.code
.startup
start:
mov dx,offset msg
mov ah,9
int 21h
mov ah,1
int 21h
cmp al,'1'
jb start
cmp al,'8'
ja start
and ax,000fh
dec ax
shl ax,1
mov bx,ax
jmp table[bx]
start2:
mov ah,9
int 21h
.exit 0
;
disp1:
mov dx,offset msg1
jmp start2
disp2:
mov dx,offset msg2
jmp start2
disp3:
mov dx,offset msg3
jmp start2
disp4:
mov dx,offset msg4
jmp start2
disp5:
mov dx,offset msg5
jmp start2
disp6:
mov dx,offset msg6
jmp start2
disp7:
mov dx,offset msg7
jmp start2
disp8:
mov dx,offset msg8
jmp start2
end
二、用条件控制伪指令实现分支
MASM60引入.IF、.ELSEIF、.ELSE和.ENDIF伪指令,他们类似高级语言中的IF、THEN、ELSE和ENDIF,这些伪指令在汇编时要展开,自动生成对应得比较和条件转移指令序列,实现程序的分支,利用条件控制伪指令可以简化分支结构的编程。
条件控制伪指令的格式如下:
.IF 条件表达式 ;条件为真(值非0),执行分支
分支体
[.ELSEIF 条件表达式 ;前面IF[以及前面ELSEIF]条件为假(值为0),
;并且当前ELSE条件为真,执行分支体
分支体 ]
[.ELSE ;前面IF[以及前面ELSEIF]条件为假,
;执行分支体
分支体 ]
.ENDIF ;分支体结束
方括号内的部分可选,条件表达式允许的操作符如下表:
如上面的典型单分支结构,可以修改如下:
mov ax,X
sub ax,Y
.IF AX <0
neg ax
.ENDIF
mov result,ax
汇编程序在翻译相应条件表达式时,将生成一组功能等价的比较、测试和转移指令,值得一提的是要注意条件表达式比较的两个数值是作为无符号数还是作为有符号数,因为他们将影响产生的条件转移指令。对于条件表达式中的变量,若是用db、dw、dd定义的,则一律作为无符号数,若需要进行带符号数的比较时,这些变量在定义时须用相应的带符号数定义语句来定义,依次为SBYTE、SWORD、SDWORD。采用寄存器或常数作为表达式的数值参加比较时,默认也是无符号数,如果作为有符号数,可以利用sbyte ptr 或 sword ptr 操作符指明。若其中一个数值为有符号数,则条件表达式强制另一个数作为有符号数进行比较。
例25.3:用条件控制伪指令实现有根判断的源程序。
.model small
.stack 256
.data
_a sbyte ?
_b sbyte ?
_c sbyte ?
tag byte ?
.code
.startup
mov al,_b
imul al
mov bx,ax
mov al,_a
imul _c
mov cx,4
imul cx
.if sword ptr bx >=ax
mov tag,0
.else
mov tag, 1
.enif
.exit 0
end
其生成的lst文件如下:
Microsoft (R) Macro Assembler Version 6.11 04/09/06 11:41:54
l25-3.asm Page 1 - 1
.model small
.stack 256
0000 .data
0000 00 _a sbyte ?
0001 00 _b sbyte ?
0002 00 _c sbyte ?
0003 00 tag byte ?
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 A0 0001 R mov al,_b
001A F6 E8 imul al
001C 8B D8 mov bx,ax
001E A0 0000 R mov al,_a
0021 F6 2E 0002 R imul _c
0025 B9 0004 mov cx,4
0028 F7 E9 imul cx
.if sword ptr bx >= ax
002A 3B D8 * cmp sword ptr bx, ax
002C 7C 07 * jl @C0001
002E C6 06 0003 R 00 mov tag,0
.else
0033 EB 05 * jmp @C0003
0035 :
0035 C6 06 0003 R 01 mov tag, 1
.endif
003A :
.exit 0
003A B8 4C00 * mov ax, 04C00h
003D CD 21 * int 021h
end
Microsoft (R) Macro Assembler Version 6.11 04/09/06 11:41:54
l25-3.asm Symbols 2 - 1
Segments and Groups:
N a m e Size Length Align Combine Class
DGROUP . . . . . . . . . . . . . GROUP
_DATA . . . . . . . . . . . . . 16 Bit 0004 Word Public 'DATA'
STACK . . . . . . . . . . . . . 16 Bit 0100 Para Stack 'STACK'
_TEXT . . . . . . . . . . . . . 16 Bit 003F 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
_a . . . . . . . . . . . . . . . Byte 0000 _DATA
_b . . . . . . . . . . . . . . . Byte 0001 _DATA
_c . . . . . . . . . . . . . . . Byte 0002 _DATA
tag . . . . . . . . . . . . . . Byte 0003 _DATA
0 Warnings
0 Errors