汇编语言程序设计

Posted 绀香零八

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编语言程序设计相关的知识,希望对你有一定的参考价值。

文章目录

分支程序结构

改变程序执行顺序、形成分支、循环、调用等程序结构是很常见的程序设计问题。
高级语言采用IF等语句表达条件,并根据条件是否成立转向不同的程序分支。
汇编语言需要首先利用比较CMP、测试TEST、加减运算、逻辑运算等影响状态标志的指令形成条件,然后利用条件转移指令判断由标志表达的条件,并根据标志状态控制程序转移到不同的程序段。

无条件转移指令

程序代码在代码段
CS:指明代码段在主存中的段基地址
EIP:给出将要执行指令的偏移地址
程序顺序执行,处理器自动增量EIP
程序控制转移,EIP随之改变
程序转移到另外的代码段,EIP和CS都改变
控制转移类指令:改变EIP(有些也改变CS),即改变程序执行顺序(实现程序控制转移)的指令

  1. 转移范围
    段内转移
    在当前代码段范围内的程序转移
    不需更改CS,只要改变EIP(偏移地址)
    近转移(Near):32位近转移NEAR32,16位近转移NEAR16
    短转移(Short):转移范围在127~-128字节
    段间转移
    从当前代码段跳转到另一个代码段
    需要更改CS(段地址)和EIP(偏移地址)
    远转移(Far): 48位远转移FAR32,32位远转移FAR16
  2. 指令寻址方式
    相对寻址方式
    提供目标地址相对于当前指令指针EIP的位移量
    目标地址(转移后的EIP)=当前EIP+位移量
    相对寻址都是段内转移,最常用、最灵活
    直接寻址方式
    直接提供目标地址
    目标地址(转移后的CS和EIP)=指令操作数
    间接寻址方式
    指示寄存器或存储单元
    目标地址来自寄存器或存储单元、间接获得
    寄存器间接寻址:用寄存器保存目标地址
    存储器间接寻址:用存储单元保存目标地址
  3. JMP指令
    无条件转移:程序无条件改变执行顺序
    JMP指令相当于高级语言的goto语句

条件转移指令

根据指定的条件确定程序是否发生转移

Jcc  label  ;条件满足,发生转移;否则,顺序执行下条指令

· LABEL表示目标地址,采用段内相对寻址
32位IA-32处理器:达到32位的全偏移量
16位80x86处理器:-128~+127间的短转移
条件转移指令不影响标志,但要利用标志
· cc表示利用标志判断的条件,16种、两类
单个标志状态作为条件、两数大小关系作为条件

  1. 单个标志状态作为条件的条件转移指令
JZ(JE)和JNZ(JNE):利用零位标志ZF
判断结果是零(相等)还是非零(不等)
JS和JNS:利用符号标志SF
判断结果是负还是正
JO和JNO:利用溢出标志OF
判断结果是溢出还是没有溢出
JP(JPE)和JNP(JPO):利用奇偶标志PF
判断结果低字节“1”的个数是偶数还是奇数
JC和JNC:利用进位标志CF
判断结果是有进位(为1)还是无进位(为0)

  1. 单个标志状态作为条件的条件转移指令
无符号数用高(Above)、低(Below)
低于(不高于等于):JB(JNAE)
不低于(高于等于):JNB(JAE)
低于等于(不高于):JBE(JNA)
不低于等于(高于):JNBE(JA)
有符号数用大(Greater)、小(Less)
小于(不大于等于):JL(JNGE)
不小于(大于等于):JNL(JGE)
小于等于(不大于):JLE(JNG)
不小于等于(大于):JNLE(JG)

单分支程序结构

只有一个分支的程序,类似高级语言的IF-THEN语句结构
注意采用正确的条件转移指令
当条件满足(成立),发生转移,跳过分支体;条件不满足,顺序向下执行分支体
条件转移指令与高级语言的IF语句正好相反;IF语句是条件成立,执行分支体

双分支程序结构

双分支程序结构有两个分支,条件为真执行一个分支;条件为假,执行另一个分支,相当于高级语言的IF-THEN-ELSE语句
顺序执行的分支体1最后一定要有一条JMP指令跳过分支体2
JMP指令必不可少,实现结束前一个分支回到共同的出口作用
双分支结构有时可以改变为单分支结构,事先执行其中一个分支(选择出现概率较高的分支)

循环程序结构

三个部分组成:
循环初始——为开始循环准备必要的条件,如循环次数、循环体需要的初始值等;
循环体——重复执行的程序代码,其中包括对循环条件的修改等;
循环控制——判断循环条件是否成立,决定是否继续循环
“先判断、后循环”的循环程序结构,对应高级语言的WHILE语句
“先循环、后判断”的循环程序结构,对应高级语言的DO语句

循环指令

LOOP label
;ECX←ECX-1;若ECX≠0,循环到LABEL
;否则,顺序执行

JECXZ label
;ECX=0,转移;否则顺序执行

目标地址采用相对短转移,实地址存储模型使用CX作为计数器

计数控制循环

通过次数控制循环,利用LOOP指令属于计数控制,常见是“先循环、后判断”循环结构
计数可以减量进行,即减到0结束;计数可以增量进行,即达到规定值结束

条件控制循环

· 根据条件决定是否进行循环
需要使用有条件转移指令实现,多见“先判断、后循环”结构
· 先行判断的条件控制循环程序
很像双分支结构,主要分支需要重复执行多次(JMP的目标位置是循环开始),另一个分支用于跳出这个循环
· 先行循环的条件控制循环程序
类似单分支结构,循环体就是分支体,顺序执行就跳出循环

子程序结构

子程序(Subroutine)=函数(Function)=过程(Procedure)

子程序指令

子程序:与主程序分开的、完成特定功能的一段程序
当主程序(调用程序)执行调用指令CALL调用子程序
子程序(被调用程序)执行返回指令RET返回主程序

MASM利用过程定义伪指令获得子程序信息

	过程名	PROC
		……	;过程体
	过程名	ENDP
	;过程名为符合语法的标识符

PROC后面可加参数:NEAR或FAR
简化段定义源程序格式中,通常不需指定

子程序调用的堆栈

子程序设计

子程序的编写方法与主程序一样
但需要留意几个问题:
· 利用过程定义,获得子程序名和调用属性
· RET指令返回主程序,CALL指令调用子程序
· 压入和弹出操作要成对使用,保持堆栈平衡
· 开始保护寄存器,返回前相应恢复
· 安排在代码段的主程序之外
· 子程序允许嵌套和递归

参数传递

主程序与子程序间通过参数传递建立联系
入口参数(输入参数):主程序→子程序
出口参数(输出参数):子程序→主程序
传递参数的多少反映程序模块间的耦合程度
参数的具体内容:数据本身(传递数值)、数据的存储地址(传递地址,传递引用)
参数传递方法:寄存器、变量、堆栈

  1. 寄存器传递参数
    最简单和常用的参数传递方法
    把参数存于约定的寄存器
    少量数据直接传递数值,大量数据只能传递地址
    带有出口参数的寄存器不能保护和恢复
    带有入口参数的寄存器可以保护、也可以不保护,但最好能够保持一致
  2. 共享变量传递参数
  3. 堆栈传递参数
    主程序将入口参数压入堆栈,子程序从堆栈中取出参数
    出口参数通常不使用堆栈传递
    高级语言进行函数调用时提供的参数,实质也利用堆栈传递
    采用堆栈传递参数是程式化的,它是编译程序处理参数传递、以及汇编语言与高级语言混合编程时的常规方法

以上是关于汇编语言程序设计的主要内容,如果未能解决你的问题,请参考以下文章

go语言-golang基础-流程控制

使用无限循环时,x86中断处理程序被阻止

ARM 程序集中分支上的延迟结果指令会发生啥情况?

java中大量使用二维数组和for循环会发生内存泄露吗?该怎么解决?

有没有办法在汇编中的一行上显示一个循环?

MCS-51单片机汇编语言程序设计