文章目录
顺序结构
- 程序无分支、无循环、无转移, 以直线方式一条指令接着一条指令顺序执行
分支结构
- 运行时, 让机器根据不同情况自动做出判断, 有选择地执行相应的处理程序
- 一般根据标志寄存器的某些位作为判断条件
转移指令
- 转移指令可以改变程序的执行顺序(也就是改变CS:EIP/IP指针的值)
- 转移指令不改变标志寄存器的值
条件转移
调用格式:操作符 标号
如果满足条件,则转移,否则继续执行
分支条件转移特别需要注意以下几点
- 选择合适的转移指令,注意有无符号的区别
- 为每个分支安排好出口
- 把公共部分尽量放到公共段中
简单条件转移
指令名称 | 助记符 | 转移条件 | 功能说明 |
---|---|---|---|
相等/等于0转 | JE/JZ | ZF=1 | 前次操作结果是否相等或等于0 |
不相等/不等于0转 | JNE/JNZ | ZF=0 | 前次操作结果是否不相等或不等于0 |
为负转 | JS | SF=1 | 前次操作结果是否为负 |
为正转 | JNS | SF=0 | 前次操作结果是否为正 |
溢出转 | JO | OF=1 | 前次操作结果是否溢出 |
未溢出转 | JNO | OF=0 | 前次操作结果是否未溢出 |
进位位为1转 | JC | CF=1 | 前次操作结果是否有进位或借位 |
进位位为0转 | JNC | CF=0 | 前次操作结果是否无进位或借位 |
偶转移 | JP/JPE | PF=1 | 前次操作结果中1的个数是否为偶数 |
奇转移 | JNP/JPO | PF=0 | 前次操作结果中1的个数是否为奇数 |
无符号数
无符号数的运算结果有三种情况
- 结果为正:大数-小数,结果为正,无溢出无进位
- 结果为0
- 结果为负:小数-大数,结果为负,高位变成1,产生进位
JA / JNBE
- 大于(above)转移,比较两个无符号数,a>b,则转移
- 条件:CF=0且ZF=0(未进位或借位,运算结果不为0)
JAE / JNB
- 大于等于(above equ)转移,比较两个无符号数,a>=b,则转移
- 条件:CF=0或ZF=1(未进位或借位,或者运算结果为0)
JB / JNAE
- 小于(below)转移,比较两个无符号数,a>b,则转移
- 条件:CF=1且ZF=0(产生了进位或借位,运算结果不为0)
JBE / JNA
- 小于等于(below equ)转移,比较两个无符号数,a>b,则转移
- 条件:CF=1或ZF=1(产生了进位或借位,或者运算结果为0)
有符号数
有符号数的结果比较复杂,分为下面四种
- 不进位,不溢出
- 不进位,溢出
- 进位,不溢出
- 进位,溢出
溢出的情况分两种:
- 负数 - 负数 = 正数
- 正数 + 正数 = 负数
JG / JNLE
- 大于(greater)转移,比较两个有符号数,a>b,则转移
- 条件:SF=OF且ZF=0
JGE / JNL
- 大于等于(greater equ)转移,比较两个有符号数,a>=b,则转移
- 条件:SF=OF或ZF=0
JL / JNGE
- 小于(less)转移,比较两个有符号数,a>b,则转移
- 条件:SF≠OF且ZF=0
JLE / JNG
- 小于等于(less equ)转移,比较两个有符号数,a>b,则转移
- 条件:SF≠OF或ZF=0
无条件转移
无条件转移指令使CPU无条件地转移到指令指明的目的地址处执行,包括JMP、CALL、RET、INT和IRET
- 段内转移:转移指令和目的地址在同一段,只改变EIP
- 段间转移:转移指令和目的地址在不同段,改变EIP,同时改变CS寄存器
JMP有直接和间接寻址两种方式
循环结构
按照一定规律, 多次重复执行一串语句
循环程序的结构
循环程序一般由以下 4 部分组成
- 初值部分:退出条件初值,循环内容初值
- 重复执行部分:重复执行某些操作
- 变量部分:利用变量的增或减,按顺序访问存储器
- 退出条件部分:达到条件时退出循环
循环控制方法
计数控制法
用于循环次数已知的情况,有4种控制循环的指令
一般循环转移指令
LOOP 标号
功能:ECX/CX先减一,然后判断,不为0则跳转到标号处
等于或0循环转移指令
LOOPE/LOOPZ 标号
功能:ECX/CX先减一,然后判断,不为0,并且ZF=1,则跳转到标号处
不等于或0循环转移指令
LOOP 标号
功能:ECX/CX先减一,然后判断,不为0,并且ZF=0,则跳转到标号处
跳转指令
JCXZ/JECXZ 标号
功能:当寄存器ECX/CX的值为0时,跳转到标号
该指令警经常放在循环前,用于跳过循环体
条件控制法
循环次数不确定,但是可以由某些条件确定
子程序设计
子程序的概念
将重复的或者经常用到的功能设计成可供反复调用的独立程序段,在需要的时候调用
子程序的定义
子程序名 PROC NEAR/FAR
…
子程序名 ENDP
如果主程序与子程序在相同段,则定义为NEAR,NEAR可省略,否则定义为FAR
子程序的调用与返回
调用指令CALL
段内直接调用
CALL 过程名
- EIP/IP入栈
- 目的地址 -> EIP/IP
段间直接调用
CALL FAR PTR 过程名
- CS入栈,目的段首址 -> CS
- EIP/IP入栈,目的地址 -> EIP/IP
段内间接调用
CALL WORD/DWORD PTR OPD
- EIP/IP入栈
- OPD -> EIP/IP
段间间接调用
CALL DWORD/FWORD PTR OPD
- CS入栈,( OPD + 2/4 ) -> CS
- EIP/IP入栈,OPD -> EIP/IP
返回指令RET
RET
- EIP/IP出栈
- 如果是段间调用,CS出栈
RET n
- 作用同上,特殊之处在于,在上述操作之后,废除栈顶n/2或者n/4个无用的参数
- 当利用堆栈法传递参数时,常用此法回收空间
- CALL指令和RET指令均不影响标志位
子程序现场保护方法
- 保护现场的工作,一般是在子程序中完成
- 在子程序开始处保护现场PUSH,在退出时恢复现场POP
- 栈中保存,先进后出
传递参数的方式
概念:主程序准备入口参数,子程序提供出口结果,这个过程称为参数传递
寄存器法
速度快,但是寄存器个数有限
约定单元法
- 把入口参数和出口参数都放到事先约定好的内存单元中
- 优点是不易出错,缺点是占用内存空间
堆栈法
- 通过堆栈传递参数
- 优点是不占用寄存器,不占用内存空间,灵活性强
- 缺点是存取参数时要计算堆栈地址,不能有差错
程序设计注意事项
目标:
- 首先保证正确性
- 使程序结构合理,简洁明了,容易阅读和交流
- 便于使用和扩充,能节省存储空间,提高运行速度
方法:
- 依操作数的多少,值的大小,正确分配数据存储区
- 选择合适的指令和寻址方式
- 选择合适的寻址方式
- 选用效率高的指令
- 不要插入不必要的语句
- 合理安排寄存器的使用