第 5章 分支与循环程序设计
5.1 转移
5.2 分支结构程序设计
5.3 循环程序设计
5.4 跳转表
5.1 转移转移指令分:
无条件转移指令
条件转移指令
5.1.1 无条件转移指令
无条件转移指令 JMP
作用相当于 goto语句,但使用频繁。
分为:
段内转移
段内短转移
段间转移
1.段内转移
格式,JMP SRC
功能:跳转到 SRC指定的位置继续执行
SRC可以是:
程序标号 如,JMP _Done
寄存器 如,JMP EAX
内存操作数 如,JMP [EBX]
2.段内短转移格式,JMP SHORT SRC
JMP指令仅占 2字节
SRC必须是一个程序标号
同 JMP SRC相比,短转移跳转的范围较小
3.段间转移在保护模式下,段间转移指令用来
切换任务
跳转到调用门指定的程序入口
执行另一个代码段内的程序例如,JMP 0060:005B5E20
5.1.2 条件转移指令格式,JCC LABELX
功能:如果条件 CC为真,则转移到 LABELX
处执行,否则顺序执行下一条指令 。
LABELX是程序中的一个标号;
CC是条件标志位,指定了转移的条件 。
条件转移指令 分类
1,依据单个标志位的条件转移指令
2,依据有符号数比较结果的条件转移指令
3,依据无符号数比较结果的条件转移指令
4,依据 CX/ECX是否为 0的条件转移指令
1.依据单个标志位的条件转移指令例如,求 DIST?|A–B|。
MOV EAX,A
SUB EAX,B
JNS A10
NEG EAX
A10:
MOV DIST,EAX
JNS比较 SF的值,如果 EAX是正数或 0,就跳转到 A10,否则执行下一句。
2.依据有符号数比较结果的条件转移指令例如,求有符号数 A和 B的较大值 MAXAB。
MOV EAX,A
CMP EAX,B
JGE a20
MOV EAX,B
a20:
MOV MAXAB,EAX
A大于等于 B时,跳转到 a20处,此时 EAX?A;
A小于 B时,不跳转,EAX?B 。
3.依据无符号数比较结果的条件转移指令例如,求无符号数 A和 B的最大值 MAXAB
MOV EAX,A
cmp EAX,B
JAE a30
MOV EAX,B
a30:
MOV MAXAB,EAX
和前面程序的区别只在于条件跳转指令的选择 。
有符号数判断使用 JGE,而无符号数判断使用 JAE。
4.依据 CX/ECX是否为 0的条件转移指令
格式 1,JCXZ LABELX
格式 2,JECXZ LABELX
功能:如果 CX/ECX等于 0,则转移到
LABELX处执行,否则顺序执行下一条指令 。
5.2 分支结构程序设计
5.2.1 单分支结构和双分支结构
5.2.2 多分支结构
5.2.3 折半查找程序
5.2.4 有序表插入
5.2.1 单分支结构和双分支结构
单分支结构? 双分支结构对于单分支结构的程序,
由条件转移指令来判断条件是否满足:
条件满足时,跳过分支程序
条件不满足时,继续向下执行,执行完分支后汇合 。
这点与 C语言 if语句不同 。
5.2.2 多分支结构
以双分支结构为基础可以写出多分支结构的程序。
下面是求 X的符号的函数的 C程序和汇编程序的片段,sign.c sign.asm
判断是否为闰年的程序片段 leapyear.asm
比较日期大小的程序片段 date.asm
5.2.3 折半查找程序
流程图(数组为 R,元素个数 n,数为 a)
折半查找执行过程
( 1) 设定一个查找范围,下界为 L和上界为 h
( 2) 如果下界 L大于上界 h,则查找范围为空,查找结束 。 算法结束 。
( 3) 取下界 L和上界 h的中点
m?( L+h) /2
( 4) 从数组的中点 m处取出一个数 R[m],
和 a进行比较 。
折半查找执行过程(续)
( 5) 如果 R[m]等于 a,则在数组中找到 a,
下标为 m。 算法结束 。
( 6) 如果 R[m]大于 a,则修改上界 h为
m?1。 然后跳转到第 2步 。
( 7) 如果 R[m]小于 a,则修改下界 l为
m+1。 然后跳转到第 2步 。
实现折半查找的程序样例,split.asm
结果为,Index=5 Count=3 Element=680
5.2.4 有序表插入要插入一个数到有序表中
找到插入位置
把数组的元素逐个向后移动
将这个数写到空出的位置实现有序表插入的程序 样例,insert.asm
5.3 循环程序设计循环程序包含 3部分:
循环初始化部分
循环体
循环控制部分常见的循环控制结构:
while-do结构
do-while结构
while-do结构和 do-while结构
5.3.1 循环指令
LOOP指令
循环次数放在 ECX中,一般用于固定次数
格式,LOOP 标号
功能,ECX先减 1,再检查 ECX:
ECX的值不为 0,则跳转到标号处继续循环;
如果 ECX的值为 0,则循环结束 。
LOOP指令循环的格式为:
MOV ECX,循环次数标号:
循环体
LOOP 标号举例:计算 n!的递归程序 factoria.asm
结果,factorial(5) =120
LOOPZ和 LOOPNZ指令
LOOPZ和 LOOPNZ指令:
循环体执行一次后,不仅要检查 ECX的值,还会检查 ZF。
格式,LOOPZ( LOOPNZ) 标号
功能,ECX先减 1,再检查 ECX和 ZF标志位:
如果 ECX的值不为 0,并且 ZF为 1( 0),则跳转到标号处继续循环;
否则继续执行 LOOPZ后面的下一条指令,循环结束。
样例:数值转换 convert.asm
结果:
hex format = 18ef1365h
dec format = 0418321253d
bin format = 00011000111011110001001101100101b
bits of 1 = 16
5.3.2 不定次数的循环某些循环的执行次数预先并不能完全确定,而是根据执行的情况来决定是否继续循环或退出循环 。
这时,就不再适合用 LOOP指令来构造循环了,而应该利用条件跳转指令来构造和控制循环 。
5.3.3 循环体中操作的控制
可以用数据来描述循环体内部的操作:
每次循环过程中取出数据来决定循环要做的操作。
例如:由 X和 Y数组计算数组 Z的计算公式为:
Z0?X0+Y0 Z1?X1+Y1 Z2?X2-Y2 Z3?X3-Y3 Z4?X4-Y4
Z5?X5+Y5 Z6?X6+Y6 Z7?X7-Y7 Z8?X8+Y8 Z9?X9-Y9
则再设定一个数组 OP,用 0和 1表示加法和减法 。
当 计算 Z的元素时,取出 OP数组中的对应元素,
来决定是做加法还是减法 。
5.3.4 多重循环循环嵌套构成多重循环例如:将数组中的 7个元素从小到大排列好,
冒泡排序例子 bubble.asm,过程如下
5.4 跳转表适合程序中分支很多的情况
C语言使用 switch语句
汇编程序使用跳转表要实现一个简易的计算程序,输入两个操作数和一个运算符,计算结果并显示出来。
C语言举例,equation.c
汇编语言举例,equation.asm
5.1 转移
5.2 分支结构程序设计
5.3 循环程序设计
5.4 跳转表
5.1 转移转移指令分:
无条件转移指令
条件转移指令
5.1.1 无条件转移指令
无条件转移指令 JMP
作用相当于 goto语句,但使用频繁。
分为:
段内转移
段内短转移
段间转移
1.段内转移
格式,JMP SRC
功能:跳转到 SRC指定的位置继续执行
SRC可以是:
程序标号 如,JMP _Done
寄存器 如,JMP EAX
内存操作数 如,JMP [EBX]
2.段内短转移格式,JMP SHORT SRC
JMP指令仅占 2字节
SRC必须是一个程序标号
同 JMP SRC相比,短转移跳转的范围较小
3.段间转移在保护模式下,段间转移指令用来
切换任务
跳转到调用门指定的程序入口
执行另一个代码段内的程序例如,JMP 0060:005B5E20
5.1.2 条件转移指令格式,JCC LABELX
功能:如果条件 CC为真,则转移到 LABELX
处执行,否则顺序执行下一条指令 。
LABELX是程序中的一个标号;
CC是条件标志位,指定了转移的条件 。
条件转移指令 分类
1,依据单个标志位的条件转移指令
2,依据有符号数比较结果的条件转移指令
3,依据无符号数比较结果的条件转移指令
4,依据 CX/ECX是否为 0的条件转移指令
1.依据单个标志位的条件转移指令例如,求 DIST?|A–B|。
MOV EAX,A
SUB EAX,B
JNS A10
NEG EAX
A10:
MOV DIST,EAX
JNS比较 SF的值,如果 EAX是正数或 0,就跳转到 A10,否则执行下一句。
2.依据有符号数比较结果的条件转移指令例如,求有符号数 A和 B的较大值 MAXAB。
MOV EAX,A
CMP EAX,B
JGE a20
MOV EAX,B
a20:
MOV MAXAB,EAX
A大于等于 B时,跳转到 a20处,此时 EAX?A;
A小于 B时,不跳转,EAX?B 。
3.依据无符号数比较结果的条件转移指令例如,求无符号数 A和 B的最大值 MAXAB
MOV EAX,A
cmp EAX,B
JAE a30
MOV EAX,B
a30:
MOV MAXAB,EAX
和前面程序的区别只在于条件跳转指令的选择 。
有符号数判断使用 JGE,而无符号数判断使用 JAE。
4.依据 CX/ECX是否为 0的条件转移指令
格式 1,JCXZ LABELX
格式 2,JECXZ LABELX
功能:如果 CX/ECX等于 0,则转移到
LABELX处执行,否则顺序执行下一条指令 。
5.2 分支结构程序设计
5.2.1 单分支结构和双分支结构
5.2.2 多分支结构
5.2.3 折半查找程序
5.2.4 有序表插入
5.2.1 单分支结构和双分支结构
单分支结构? 双分支结构对于单分支结构的程序,
由条件转移指令来判断条件是否满足:
条件满足时,跳过分支程序
条件不满足时,继续向下执行,执行完分支后汇合 。
这点与 C语言 if语句不同 。
5.2.2 多分支结构
以双分支结构为基础可以写出多分支结构的程序。
下面是求 X的符号的函数的 C程序和汇编程序的片段,sign.c sign.asm
判断是否为闰年的程序片段 leapyear.asm
比较日期大小的程序片段 date.asm
5.2.3 折半查找程序
流程图(数组为 R,元素个数 n,数为 a)
折半查找执行过程
( 1) 设定一个查找范围,下界为 L和上界为 h
( 2) 如果下界 L大于上界 h,则查找范围为空,查找结束 。 算法结束 。
( 3) 取下界 L和上界 h的中点
m?( L+h) /2
( 4) 从数组的中点 m处取出一个数 R[m],
和 a进行比较 。
折半查找执行过程(续)
( 5) 如果 R[m]等于 a,则在数组中找到 a,
下标为 m。 算法结束 。
( 6) 如果 R[m]大于 a,则修改上界 h为
m?1。 然后跳转到第 2步 。
( 7) 如果 R[m]小于 a,则修改下界 l为
m+1。 然后跳转到第 2步 。
实现折半查找的程序样例,split.asm
结果为,Index=5 Count=3 Element=680
5.2.4 有序表插入要插入一个数到有序表中
找到插入位置
把数组的元素逐个向后移动
将这个数写到空出的位置实现有序表插入的程序 样例,insert.asm
5.3 循环程序设计循环程序包含 3部分:
循环初始化部分
循环体
循环控制部分常见的循环控制结构:
while-do结构
do-while结构
while-do结构和 do-while结构
5.3.1 循环指令
LOOP指令
循环次数放在 ECX中,一般用于固定次数
格式,LOOP 标号
功能,ECX先减 1,再检查 ECX:
ECX的值不为 0,则跳转到标号处继续循环;
如果 ECX的值为 0,则循环结束 。
LOOP指令循环的格式为:
MOV ECX,循环次数标号:
循环体
LOOP 标号举例:计算 n!的递归程序 factoria.asm
结果,factorial(5) =120
LOOPZ和 LOOPNZ指令
LOOPZ和 LOOPNZ指令:
循环体执行一次后,不仅要检查 ECX的值,还会检查 ZF。
格式,LOOPZ( LOOPNZ) 标号
功能,ECX先减 1,再检查 ECX和 ZF标志位:
如果 ECX的值不为 0,并且 ZF为 1( 0),则跳转到标号处继续循环;
否则继续执行 LOOPZ后面的下一条指令,循环结束。
样例:数值转换 convert.asm
结果:
hex format = 18ef1365h
dec format = 0418321253d
bin format = 00011000111011110001001101100101b
bits of 1 = 16
5.3.2 不定次数的循环某些循环的执行次数预先并不能完全确定,而是根据执行的情况来决定是否继续循环或退出循环 。
这时,就不再适合用 LOOP指令来构造循环了,而应该利用条件跳转指令来构造和控制循环 。
5.3.3 循环体中操作的控制
可以用数据来描述循环体内部的操作:
每次循环过程中取出数据来决定循环要做的操作。
例如:由 X和 Y数组计算数组 Z的计算公式为:
Z0?X0+Y0 Z1?X1+Y1 Z2?X2-Y2 Z3?X3-Y3 Z4?X4-Y4
Z5?X5+Y5 Z6?X6+Y6 Z7?X7-Y7 Z8?X8+Y8 Z9?X9-Y9
则再设定一个数组 OP,用 0和 1表示加法和减法 。
当 计算 Z的元素时,取出 OP数组中的对应元素,
来决定是做加法还是减法 。
5.3.4 多重循环循环嵌套构成多重循环例如:将数组中的 7个元素从小到大排列好,
冒泡排序例子 bubble.asm,过程如下
5.4 跳转表适合程序中分支很多的情况
C语言使用 switch语句
汇编程序使用跳转表要实现一个简易的计算程序,输入两个操作数和一个运算符,计算结果并显示出来。
C语言举例,equation.c
汇编语言举例,equation.asm