汇编语言基础--汇编操作指令概述
本文是接续"汇编语言基础--机器级数据存储",主要介绍汇编指令的构造、寻址和指令主要分类。
操作指令
指令的基本要素:
在"计算机处理器(CPU)基础"介绍了一条完整可执行指令包括指令码和操作数。由于同一功能的指令要处理不同数据类型的操作数,这样指令的长度判读、计算的复杂度等存在差别,所以即使是同一功能的指令也存在不同的版本和编码。如针对不同数据类型,mov(传送数据)指令,有movb(传送字节),movw(传送字),movl(传送双字)三种不同的版本(这里都是基于AT&T的GAS)。
指令寻址:
指令中存在三种寻址方式,使用立即数、寄存器和储存器引用,GAS汇编代码书写有特殊的方法区分这三种寻址方式。立即数是直接存储在完整指令代码中的数据,如movl $0x1a, %eax,这里就是将16进制的1a存储到eax寄存器中(GAS要求立即数前需要有$, 寄存器前有%)。movl $0x1a, %eax 语句中的%eax就是寄存寻址,意味着会使用该寄存器中的值或者是将某个值存储到寄存器中。
存储器寻址是指读取存储器中某个位置上值或者将某个值存储在存储器中的某个位置。存储器寻址又包括多种寻址方式。
1.绝对寻址:GAS中书写汇编代码时,常数前没有$符号时,如movl 0x104, %eax,这里就不是讲0x104移动到eax寄存器中,而是指将存储器绝对地址0x104中的值移动到eax寄存器中
2.间接寻址:使用寄存器中存储的值作为存储器的地址读取或者写入数据。书写时只需要加上括号即可,如movl $20, (%esp), 这里代表将立即数存储在存储地址为寄存器esp中值的存储器位置中。
3.基址+偏移量寻址:寄存器中存储的值作为基地址,立即数作为基地址的偏移量,两者的和作为存储器地址。书写方式是在间接寻址的书写寄存上,括号前写上常数偏移量。如movl $20, -3(%esp),是将立即数20存储在%esp-3的存储器位置。
4.一般化的变址寻址(加上伸缩因子):变址寻址的不同之处在于,取两个寄存器,一个作为基址寄存器,另一个作为变址寄存器,一个常数作为伸缩因子,一个立即数作为偏移,内存地址的确定由基址+变址与伸缩因子的积+偏移。书写方式如9(%eax ,%edx ,4),9位偏移量,4为伸缩因子。其中不同部分可以为空,构成不同类型的变址。
tips:这里所指的内存地址是指地址空间的地址,使用虚拟内存的机制,实际访问内存时,还会有一步转换为物理地址,一般由MMU按照TLB或者内存中页表的映射转换为物理地址,从内存中取出数据。
指令分类:
指令系统中,主要有四种类型的指令,分别是数据传输指令、算数与逻辑操作、控制指令和转移指令。
1.数据传输指令
数据传输指令主要用来实现数据的移动。参考指令有:
指令 |
效果 |
描述 |
movl S, D |
D <- S |
传送双字 |
movw S, D |
D <- S |
传送字 |
movb S, D |
D <- S |
传送字节 |
movsbl S, D |
D <- 符号扩展 |
传送字节,符号扩展为双字 |
movzbl S, D |
D <- 零扩展 |
传送字节,零扩展为双字 |
pushl S |
R[%esp] <- R[%esp]-4 M[R[%esp]] <- S |
压栈 |
popl D |
D <- M[R[%esp]]; R[%esp] <- R[%esp]+4 |
出栈 |
2.算数和逻辑操作(注意这些指令都存在w和b版本)
这类操作符主要用来实现算数与逻辑运算。参考指令有:
指令 |
效果 |
描述 |
|
计算有效地址 |
leal S, D |
D <- &S |
将S的地址移动到D中(movl是将S地址中的值移动到D中) |
一元操作符 |
incl D decl D negl D notl D |
D <- D+1 D <- D-1 D <- -D D <- ~D |
加一 减一 取负 去补 |
二元操作符 |
addl S, D subl S, D imull S, D xorl S, D orl S, D andl S, D |
D <- D + S D <- D - S D <- D*S D <- D^S D <- D|S D <- D&S |
加 减 乘 异或 与 |
移位操作 |
sall k, D shll k, D sarl k, D shrl k, D |
D <- D<<k D <- D<<k D <- D>>k D <- D>>>k |
左移 左移 算数右移 逻辑右移 |
特殊操作 |
imull S mull S cltd S idivl S divl S |
R[%edx]:R[%eax] <- SxR[%eax] R[%edx]:R[%eax] <- SxR[%eax] R[%edx]:R[%eax] <- R[%eax] R[%edx] <- R[%edx]:R[%eax] mod S R[%eax] <- R[%edx]:R[%eax] / S R[%edx] <- R[%edx]:R[%eax] mod S R[%eax] <- R[%edx]:R[%eax] / S |
有符号全64位乘法 无符号全64位乘法 符号扩展转换为64位 有符号除法 (两步是同时,eax没变) 无符号除法 |
3.控制指令
通过条件码(psw程序状态字)和跳转指令实现if...else和循环。
A.程序状态字
可以参考8086的程序状态字,如图:
绿色是三个控制标志位,控制cpu的操作:
DF:derection flag, 方向标志位,它指定字符串处理的方向,当该标志为1时,字符串以递减顺序处理,即由高字位向低字位处理,反之,则递增顺序处理。
IF:Interrupt enable flag, 它指定cpu能否响应外部中断请求,如果为1,则接受外部中断请求,否则,则不接受。
TF:trap flag,跟踪标志位,是为程序调试设置的陷阱控制位,当为1时,cpu处于单步状态,每执行一条指令,就会产生一个内部中断,复位时则cpu正常工作。
黄色是六个状态标志位:
OF: overflow flag, 当补码运算有溢出时,OF=1,否则,OF=0。
SF:sign flag, 符号标志位,为1时表示最近的运算结果为负数。
ZF:zore flag, 零标志位,若当前结果是0,则ZF等于1,否则为0。
CF: carry flag, 进位标志位,无符号数运算产生溢出时,设置为1,否则设置为0,。
AF: Auxiliary cary flag, 辅助进位标识位.
PF:Parity Flag, 辅助进位标志位。
B.会设置条件码的指令:
1.上面提到的运算指令。
2.比较指令
指令 |
效果 |
描述 |
coml(comb, comw) S2, S1 |
S1 - S2 |
比较字节(相等,零标志位设置1,其他标志大小可以判断大小关系) |
testl(testb, testw) S2, S1 |
S1&S2 |
测试字节(通过与运算来设置零标志位或者负数标志位) |
C.会访问条件码的指令
(1).根据条件码设置值
指令 |
同义指令 |
效果 |
设置条件 |
sete D setne D |
setz setnz |
D <- ZF D <- ~ZF |
相等/零 不等/非零 |
sets D setns D |
D <- SF D <- ~SF |
负数 非负数 |
|
setg D setge D setl D setle D |
setnle setnl setnge setng |
D <- ~(SF ^OF) & ZF D <- ~(SF ^OF) D <- SF ^ OF D <- (SF ^ OF) | ZF |
大于(有符号>) 小于等于(有符号>=) 小于(有符号<) 小于等于(有符号<=) |
seta D setae D setb D setbe D |
setnbe setnb setnae setna |
D <- ~CF & ~ZF D <- ~CF D <- CF D <- CF | ZF |
超过(无符号>) 超过或等于(无符号>=) 低于(无符号<) 低于或等于(无符号<=) |
(2).根据条件码跳转
根据条件码跳转,跳转目的地用一个label指明(类似于c中goto标签):
指令 |
同义名 |
跳转条件 |
描述 |
jmp Label jmp *Operand |
1 1 |
直接跳转,跳转指令中给出位置 间接跳转,跳转位置由寄存器给出 |
|
je Label jne Label |
jz jnz |
ZF ~ZF |
等于/零 不等/非零 |
js Label jns Label |
SF ~SF |
负数 非负数 |
|
jg Label jge Label jl Label jle Label |
jnle jnl jnge jng |
~(SF^OF) & ~ZF ~(SF ^ OF) SF ^ OF (SF ^ OF) | ZF |
大于(有符号>) 大于等于(有符号>=) 小于(有符号<) 小于等于(有符号<=) |
ja Label jae Label jb Label jbe Label |
jnbe jnb jnae jna |
~CF & ~ZF ~CF CF CF | ZF |
超过(无符号>) 超过或等于(无符号>=) 低于(无符号<) 低于或等于(无符号<=) |
4.转移指令(过程控制)
实现函数过程调用和返回相关指令。
指令 |
描述 |
call label |
过程调用 |
call *operant |
过程调用 |
leave |
为返回准备栈 |
ret |
从过程调用中返回 |
至此,CPU硬件和汇编相关的概述已经完全介绍完全了,下一部分将是底层相关的多级存储的一些知识总结。
本系列文章:
计算机底层架构(偏硬件)综述
计算机处理器(CPU)基础
汇编语言基础--机器级数据存储
汇编语言基础--汇编操作指令概述
计算机多级存储模型
外设IO原理
汇编语言基础--汇编操作指令概述相关推荐
- 【操作系统基础】操作系统核心概述
一.何为操作系统 操作系统(OS,Operating System)是配置在计算机硬件上的第一层软件,是对硬件系统的首次扩充.它在计算机系统中占据了重要地位,汇编程序.编译程序.数据库管理系统等系统软 ...
- 【ARM】数据操作指令(下)
00. 目录 文章目录 00. 目录 01. 数据操作指令概述 02. RSC指令 03. TST测试指令 04. TEQ指令 05. CMP 指令 06. CMN 指令 07. ORR 指令 08. ...
- 【ARM】数据操作指令(上)
00. 目录 文章目录 00. 目录 01. 数据操作指令概述 02. MOV指令 03. MVN指令 04. AND指令 05. EOR 指令 06. SUB指令 07. RSB 指令 08. AD ...
- [逆向]汇编JCC指令举例
一前言 今天文章的主要内容是逆向基础汇编JCC指令举例,JCC指令就是满足条件跳转指令,上一篇文章已经给大家介绍了基本用法,如有不明白的可以先看看我的上一篇文章,今天主要为大家举例加强巩固. 二JCC ...
- 汇编8086复习——基础知识、指令汇总、上机实验踩坑
8086处理器基础知识 汇编语言是大小写不敏感的低级语言,意思就是mov和MOV是汇编语言来说是一样的,当然大小写混用也是可以的,如Mov 在8086汇编语言里,数字默认是十进制的,如果是其他进制数字 ...
- 汇编中的字符串操作指令
每一种语言都有一些字符串操作函数,反汇编后的代码也不例外.网上讲的都比较零碎,我将它们收集起来,并配上自己的理解,形成本文. 一.字节操作指令:lodsb和stosb 1. lodsd需要寄存器esi ...
- 微机原理8086汇编语言上机——Masm环境搭建与常用汇编调试指令
学校的微机原理与接口技术课,最近开始 考古 上机实验了. 1.弯路 为什么不用宇宙最强大的IDEL--Visual Studio呢? 在我的Visual Studio专栏中有一篇文章介绍Visual ...
- 汇编中的串操作指令(MOVS,CMPS,SCAS,LODS,STOS)
学汇编的都知道,汇编中很多问题都是对字符串进行的操作,但是我们操作时总是重复相同的操作,用多个指针进行记录,不断判断只针对位置,这样确实很麻烦,于是汇编提供了一种对字符串进行操作的指令, ...
- 出栈(释放栈)和引用栈内数据意义不等同,和嵌套有关系但不是等同关系,局部变量进栈操作,不是局部变量自动带有进栈指令。汇编语言后局部变量操作是包含进栈操作指令PUSH和栈内地址存储数据调用,出栈。
出栈(释放栈)和引用栈内数据意义不等同,和嵌套有关系但不是等同关系,局部变量进栈操作,不是局部变量自动带有进栈指令.汇编语言后局部变量操作是包含进栈操作指令PUSH和栈内地址存储数据调用,出栈. 2. ...
最新文章
- java事务设计iofo,Spring事务最佳实践
- python利器怎么编程-Python实现翻译小工具!几行代码搞定!装逼利器有没有!
- 多进程和多线程的区别
- 在D-Bus适配器中声明信号
- 【git】【eclipse】记住密码/密码保存在哪里?
- linux useradd 数字,详解linux useradd用户组合权限管理等
- 关于数据库的设计的一点思路
- 前端开发基础知识整理--web综合篇
- Presto 日期和时间函数
- 2007年7月23日旅游
- 解决windows下的mysql匿名登陆无法使用mysql数据库的问题
- Delphi 10.3 Rio实现FMX应用APP增加Android“应用程序快捷方式”
- NVIDIA显卡刷BIOS教程,秒变超频显卡,将显卡性能发挥到极致!
- 985硕士程序员年薪80万!邻居眼中不如一个老师?你怎么看?
- 清除当前目录下的.svn文件 linux/windows
- 北京智和信通受邀出席2022IT运维大会,荣获“2022智能运维星耀榜最具影响力企业”
- 广度优先搜索——动态类迷宫问题
- c#设计一个Windows应用程序,模拟一个简单的银行账户管理系统。完成“创建账A款”“存款”和“查询余额”的模拟操作。程序功能如下:
- Taro 牵手腾讯有数,助力小程序数据化运营
- 市政管网检测机器人收费标准_迁安市政下水道机器人检测费用多少