当前位置: 首页 > 编程日记 > 正文

汇编程序设计与计算机体系结构软件工程师教程笔记:指令

《汇编程序设计与计算机体系结构: 软件工程师教程》这本书是由Brain R.Hall和Kevin J.Slonka著,由爱飞翔译。中文版是2019年出版的。个人感觉这本书真不错,书中介绍了三种汇编器GAS、NASM、MASM异同,全部示例代码都放在了GitHub上,包括x86和x86_64,并且给出了较多的网络参考资料链接。这里只摘记了NASM和MASM,测试代码仅支持Windows和Linux的x86_64。

4. 基本指令

4.1 简介:

在很多情况下,MASM会根据上下文来推测指令中的操作数是什么类型,有的时候NASM也是这样。在撰写指令的目标操作数时,如果要对变量解引用(dereference),NASM要求你必须指出大小,也就是必须在变量名的前面写上一个表示尺寸的命令,例如用BYTE表示字节、WORD表示字等,比方说像这样:”mov DWORD [test], eax”

4.2 数据的移动与算术运算:

MOV指令有几条具体的要求:

(1). 两个操作数的大小必须相同;

(2). 两个操作数不能全是内存操作数(也就是说要想在两个内存操作数之间移动数据,必须用寄存器做中介);

(3). 指令指针寄存器(ip/eip/rip)不能用作目标操作数。

使用XCHG指令可令两个位置上的数据彼此交换。和MOV指令类似,XCHG指令的两个操作数也不能全都是内存操作数。

加法与减法:INC、DEC、ADD、SUB

INC与DEC指令可以操作内存操作数(变量)或寄存器,这两个指令的目标很简单,就是给操作数加1或减1。

NASM对待变量的方式有点像C++对待指针的方式:如果直接写出变量名本身,那么它会将其视为内存地址。要想引用该地址中的内容(也就是由变量名所指代的那份数据),必须用一对方括号给变量解引用,如:”INC DWORD [sum]”

ADD与SUB指令可以用字面量来做加减法,也可以用内存或寄存器中的值来计算。

NEG指令可以切换操作数的正负号,也就是对操作数的值求补。

乘法与除法:MUL、IMUL、DIV、IDIV

MUL指令用来给无符号的整数执行乘法。该指令只接受一个操作数即乘数(multiplier)。被乘数保存在与乘数尺寸相对应的累加寄存器中。与被乘数一样,积的保存位置也无须手工指定,因为这是由MUL指令自动指定的,如下表所示:M指内存或变量,R指寄存器,L指字面值,被乘数与积的存放地点是根据乘数的尺寸默认指定的。

带符号的整数相乘要通过IMUL指令执行。与MUL一样,该指令也有单操作数的版本,在这种情况下,它所支持的操作数与上表中所列的相同。这条指令与MUL的主要区别在于它还有双操作数及三操作数的版本。双操作数的版本与ADD及SUB指令类似,也就是会把这两个操作数都当成运算的源数据,并且要将其中一个操作数用作运算的目标,以便存放计算结果。因此对于保存运算结果的目标操作数来说,IMUL与ADD及SUB一样都会将其中原有的值覆盖掉。如果不想让IMUL指令把这个值覆盖掉,那么可以使用三操作数的版本。该版本要求开发者指出乘数、被乘数与积的位置。

与MUL类似,除法也分为无符号与带符号两种。DIV指令用来执行无符号整数的除法运算,它会将结果以商与余数的形式分别保存,如下表所示:

使用DIV指令的时候只需要指定除数就可以了。被除数需要提前加载到与除数尺寸相对应的寄存器里。

带符号的整数需要用IDIV指令来相除。与IMUL指令不同,该指令没有双操作数或三操作数的版本,还是只提供一个操作数,即除数。与乘法指令不同,这两种除法指令都不会通过设定状态标志来反映与运算结果有关的信息,也就是说,相关标志的值是未定义(undefined)的。

移位:左移位(shift left)指令SHL与右移位(shift right)指令SHR都可以把内存操作数或寄存器中的值移动一定的位数,这个位数用字面量来指定。SHL和SHR是逻辑移位(logical bit shift),这会令某些二进制位出现在存储范围之外,同时会令空出来的那些数位都填上0.无符号的数据通常是可以做逻辑移位的。如果想通过左移位或右移位的方式给带符号的整数做乘除法,必须使用算术移位(arithmetic bit shift)指令以便保留其符号位。SAL(Shift Arithmetic Left)是算术左移,SAR(Shift Arithmetic Right)是算术右移。SAL与SAR的语法跟对应的逻辑移位指令类似,都是将内存操作数或寄存器中的值移动一定的位数,这个位数也用字面量来指定。

处理负值:4种能够执行符号扩展(sign extension)的指令,也就是CBW(将BYTE转成WORD)、CWD(将WORD转成DWORD)、CDQ(将DWORD转成QWORD),以及CQO(将QWORD转成OCTA),如下表所示:

4.3 数据的寻址与传输:

数据对齐:CPU访问存放在偶数地址上的数据要比访问存放在奇数地址上的数据更快。每种汇编器都有1条或多条命令用来修改位置计数器。MASM用的是ALIGN命令,NASM则依据不同的程序段分别使用ALIGN或ALIGNB命令。这几种命令的参数都必须是整数,而且应该是2的幂。这些命令会推进位置计数器,直到它的值变为该整数的倍数为止。这可以用来确保数据出现在偶数的内存地址上。

数据寻址:直接寻址(direct addressing)是直接访问某个值,而间接寻址(indirect addressing)则是通过值所代表的内存地址来访问另一个值。NASM的变量表示的就是其内存地址,而不是该地址中的值(如果想使用这个值,要用方括号括起来)。在MASM代码中,操作数的地址可以结合MOV指令及OFFSET命令来获取。LEA(Load Effective Address, 加载有效地址)指令在32位与64位模式之下都可以把操作数的地址加载到目标中。由于实际地址要在程序运行的时候才能够知道,因此,涉及这些地址的操作应该用LEA来完成。就获取内存地址而言,MOV与LEA指令之间的重要区别在于,后者的目标操作数必须是寄存器。

数组:汇编语言里的数组也是由类型相同的一系列数据构成的,这些数据在内存中以相等的间隔存放。数组的名称实际上指的是该数组中的首个元素。访问数组元素时,一定要正确算出该元素距离数组开头有多少个字节。汇编器不会自动检查你所做的访问是否与元素之间的边界相合。字符串(也就是由字符所构成的数组)的长度可以通过当前位置计数器(current location counter)来计算。其实不只是字符串,其它数组所占据的字节数也可以用这个办法求出。

用MASM代码来操作数组时的专用命令:TYPE命令返回变量所占据的字节数;LENGTHOF命令返回数组中的元素个数;SIZEOF命令则返回整个数组所占据的总字节数(相当于把TYPE命令与LENGTHOF命令所返回的结果乘起来)。

改变数据的大小及类型:MASM版本的代码需要使用一种新的命令即PTR命令,它会把早前定义的变量尺寸忽略掉,转而将该变量视为一个指向某份数据的指针,这份数据的大小由PTR前面的词决定。

我们在将数值复制到大寄存器的低半区时,应该使用MOVZ/MOVZX(ZX表示Zero eXtend,用0来扩展)与MOVS/MOVSX(SX表示Sign eXtend, 用符合位来扩展)两种指令,因为它们能够在复制的同时,用0位或符合位来填充高半区里的每一个二进制位。

5. 中级指令

5.2 按位执行的布尔运算:

NOT(非):它会分别反转操作数的每一个二进制位。这实际上就是在计算操作数的反码(或对操作数求反)。用来做NOT运算的那条指令也叫做NOT,它带有一个操作数。该指令将会对此数求反并把结果写入原位置。

AND(与):有一种常见的用途是通过AND来判断某值是偶数还是奇数。判断的原理是:检查受测数字的最低有效位(LSB)是0还是1。还有一个任务也可以通过AND操作迅速解决,即将ASCII字符从小写变成大写。大写与小写字母所对应的二进制值,大写与小写是由第5个二进制位(假设最右侧的叫做第0位)来控制的,除此之外,其它那些二进制位是完全相同的。此外,OR或XOR操作也可以用来转换大小写。前者用来将大写转成小写,后者可以实现双向切换:如果原字母是小写就将其改为大写,如果原字母是大写就讲其改写小写。AND操作所对应的指令也叫做AND。

OR(或):如果想实现跟AND运算相反的效果(也就是置1而不是清零),可以用OR指令,对两个操作数的每个二进制位分别执行OR运算。OR还有一个用法,是判断某数为正、为负,还是为0。只要把受测的数与它自身做OR运算,就可以根据结果判明这三种情况了。之所以能够如此,是因为OR与AND指令都会设置处理器中的许多标志位,例如CF、OF、PF、SF及ZF等。

XOR(异或):与OR类似,用来在两个操作数的每一对二进制位之间执行XOR运算。不过,它与OR有个关键的区别在于:只有当两个操作数一个是True一个是False时结果才是True,如果两个操作数均为True或均为False,那么结果是False。由于XOR运算是可逆的(reversible),因此成为很多对称加密(symmetric encryption)算法与数据存储算法中的重要环节。将原值与另一个值(此值称作键,key)连取两次XOR,就可以令运算结果回到原值

5.3 分支:branch,意思是说程序可以根据开发者所实现的逻辑进入不同的执行路径,甚至可以直接跳过某些指令。分支有两种形式,一种是无条件地进入某路径,另一种是根据条件来做测试,从而依照测试结果进入相应的路径。

无条件跳转:标签只是用来在代码中标明某个位置而已,它本身并不占据内存空间。在汇编代码中使用标签的其中一个原因是要给JMP指令提供跳转目标。这条指令能够直接令程序跳转到某个地方。

有条件跳转:在汇编语言中执行条件测试有多种办法,其中之一是使用TEST指令。该指令会对两个操作数执行AND运算,但并不修改二者的值,而且也不保存计算结果。不过,它会根据计算结果设置处理器的PF、SF及ZF等标志位。在结果中,如果值为1的二进制位是偶数个,PF标志就是1,否则为0,SF标志反映结果的最高有效位,ZF标志反映结果是否为0.CF与OF也会为TEST指令所修改,无论计算结果如何,这两个标志位总是会清零。

还有一种方法也可以做条件测试,就是用CMP指令来比较(compare)两个操作数。这能够实现出与高级语言类似的条件判断逻辑(例如等于、大于、小于等于)。汇编语言的条件跳转至少要用两条指令实现,首先,用一条指令比较两个操作数,然后,用一条或多条指令来处理比较结果。基本的条件测试逻辑可以由CMP指令起头。该指令会用目标操作数减去来源操作数,并根据计算结果修改CPU的相关标志位。与TEST指令类似,CMP指令不会修改这两个操作数,而且也不保存计算结果。比较了两个操作数之后可以用很多种办法来跳转,下表列出了常用的跳转指令以及每条指令所判断的CPU标志位:选择跳转指令的时候一定要注意操作数是无符号数还是带符号数。

5.4 重复执行:重复(repetition)也叫做循环(looping),意思是多次执行预先写好的某一组指令,具体的执行次数通常由某个计数器变量或条件来控制。

用CX/ECX/RCX计数器实现循环:由计数器所控制的循环很容易就能用汇编语言的LOOP指令实现出来。该指令会把某个”C系列的寄存器”(也就是cx/ecx/rcx)当作递减计数器(decrementing counter)来用,每循环一次就将该计数器的值减1.值降为0的时候,结束循环并继续执行LOOP下方的指令。

下面列出了各汇编器的规则

(1).MASM与NASM代码用$表示当前位置计数器(current location counter)。

(2).MASM及NASM代码要先写目标操作数,后写来源操作数。

(3).NASM的标识符区分大小写。

(4).MASM的标识符默认不区分大小写,但是可以添加”option casemap:none”命令来区分(这一般添加在.MODEL命令之后)。

(5).NASM代码用不加括号的ST0、ST1等写法来表示FPU栈寄存器。

(6).MASM通常用”%st(1)/ST(1)”、”%st(2)/ST(2)”这样带括号的写法来表示FPU栈寄存器。

(7).NASM用EQU命令将表达式的值设定给某个符号;MASM可以用=号,也可以用EQU命令。

(8).MASM和NASM都用单引号或双引号把字符串括起来。

(9).MASM的指令会自动根据某些因素(例如数据的大小)做出相应的处理,因此,有的时候很难看清楚这样一条指令究竟会如何执行。

(10).NASM通常不要求开发者用表示数据大小的命令来修饰源操作数,但如果用了也是可以的,而目标操作数的大小则必须明确,不然就要通过命令来指明。

GitHub:https://github.com/fengbingchun/CUDA_Test

相关文章:

IOS视频编辑功能详解上篇-添加水印

前言 用代码在简单视频编辑中,主要就是加美颜、水印(贴图)、视频截取、视频拼接、音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜、磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个…

《评人工智能如何走向新阶段》后记(再续7)

由AI科技大本营下载自视觉中国66. 谷歌近来研发用于基因科学的人工智能AlphaFold,根据基因序列预测生命基本分子一蛋白质的三维结构(AlphaFold与下国际围棋的AlphaGo似孪生兄弟),这是用来预测蛋白质折叠结构的能力或设计新的蛋白质…

Linux多线程实践(6) --Posix读写锁解决读者写者问题

Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthread_r…

iOS-直播开发(开发从底层做起)

代码链接: Github: https://github.com/jessonliu/JFLivePlaye 技术部分------ ⬇️ 脑涂: ![ 直播思维导图.png ] 视频直播的大概流程就上脑涂上所画的, 还有一些没列出来, 比如, 聊天, 送礼, 踢出, 禁言, 等等一系列功能, 但本文只是针对视频直播的简单实现! 下边来说一下以…

汇编程序设计与计算机体系结构软件工程师教程笔记:函数、字符串、浮点运算

《汇编程序设计与计算机体系结构: 软件工程师教程》这本书是由Brain R.Hall和Kevin J.Slonka著,由爱飞翔译。中文版是2019年出版的。个人感觉这本书真不错,书中介绍了三种汇编器GAS、NASM、MASM异同,全部示例代码都放在了GitHub上&#xff0c…

《庆余年》值得一看吗?Python告诉你谁在关注 | CSDN原力计划

扫码参与CSDN“原力计划”作者 | A字头来源 | 数据札记倌庆余年电视剧终于在前两天上了,这两天赶紧爬取数据看一下它的表现。庆余年《庆余年》是作家猫腻的小说。这部从2007年就开更的作品拥有固定的书迷群体,也在文学IP价值榜上有名。期待已久的影视版的…

《C语言及程序设计》实践项目——画分支结构流程图

返回&#xff1a;贺老师课程教学链接 【单分支结构流程图-大值】问题&#xff1a;画流程图&#xff0c;输入两个整数a和b&#xff0c;输出其中的大值。提示&#xff1a;当a<b时&#xff0c;交换a和b&#xff0c;最后输出的a一定是其中的大值。流程图中可以直接给出交换a和b…

汇编程序设计与计算机体系结构软件工程师教程笔记:内联汇编与宏

《汇编程序设计与计算机体系结构: 软件工程师教程》这本书是由Brain R.Hall和Kevin J.Slonka著&#xff0c;由爱飞翔译。中文版是2019年出版的。个人感觉这本书真不错&#xff0c;书中介绍了三种汇编器GAS、NASM、MASM异同&#xff0c;全部示例代码都放在了GitHub上&#xff0c…

无需标注数据,利用辅助性旋转损失的自监督GANs,效果堪比现有最好方法

作者 | Ting Chen译者 | 王红成出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;本文作者提出了一种自检督方式的生成对抗网络&#xff0c;通过辅助性的旋转损失来达到目的。因为通常主流方法来生成自然图像都是通过条件GAN来完成&#xff0c;但是这就需要很多的标签数…

iOS环信聊天界面中点击头像和消息的几种状态

/*环信自带头像点击事件*/ - (void)messageViewController:(EaseMessageViewController *)viewControllerdidSelectAvatarMessageModel:(id<IMessageModel>)messageModel {内容可以根据需要自己添加 }/*!methodbrief 点击了简历消息 (lyq添加)discussion 点击了简历消息,…

ASP.NET将Session保存到数据库中

因为ASP.NET中Session的存取机制与ASP相同&#xff0c;都是保存在进行中&#xff0c; 一旦进程崩溃&#xff0c;所有Session信息将会丢失&#xff0c;所以我采取了将Session信息保存到SQL Server中&#xff0c;尽管还有其它的几个方式&#xff08;本文不作介绍&#xff09;&…

iOS App上架流程

一、前言&#xff1a;作为一名iOSer&#xff0c;把开发出来的App上传到App Store是必要的。下面就来详细讲解一下具体流程步骤。 二、准备&#xff1a; 一个已付费的开发者账号&#xff08;账号类型分为个人&#xff08;Individual&#xff09;、公司&#xff08;Company&#…

不止Markov决策过程,全景式分析强化学习研究内容

作者 | 肖智清编辑 | 刘静来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;强化学习作为通用人工智能的希望&#xff0c;吸引了很多人工智能爱好者学习和研究。Markov决策过程是最知名的强化学习模型&#xff0c;强化学习教程也常以Markov决策过程作为起点。但是&am…

Windows下创建进程简介

正在执行的应用程序称为进程&#xff0c;进程不仅仅是指令和数据&#xff0c;它还有状态。状态是保存在处理器寄存器中的一组值&#xff0c;如当前执行指令的地址、保存在内存中的值&#xff0c;以及唯一定义进程在任一时刻任务的所有其他值。进程与应用程序的一个重要的区别在…

jQuery中鲜为人知的的几个方法

转来学习一下 jQuery中鲜为人知的的几个方法 jQuery近些年来仍旧是web开发中最受欢迎的类库&#xff0c;虽然大家褒贬不一&#xff0c;但是仍旧不失为一款最流行的Javascript&#xff0c;在今天这篇文章中&#xff0c;我们将介绍几个jQuery的相关方法&#xff0c;无论你是入门级…

Linux下创建进程简介

在博文https://blog.csdn.net/fengbingchun/article/details/108940548中简单介绍了Windows下通过函数CreateProcess创建进程的过程&#xff0c;这里简单介绍下Linux下通过fork函数创建进程的过程。很早之前在https://blog.csdn.net/fengbingchun/article/details/45690745中也…

热更新 FrameWork

工作中遇到想要绕过AppStore直接更新App的要求&#xff01;这里友情提示下&#xff0c;看了很多资料只是是实现了功能&#xff0c;但在项目中并没有真正用到&#xff01;资料大多都显示会被拒&#xff0c;这个说的是个人级的&#xff0c;好像企业级的不会这样,仅仅是项目需要做…

陆首群:评人工智能如何走向新阶段?

作者 | 陆首群&#xff0c;中国开源软件推进联盟名誉主席 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 编者按&#xff1a;近来&#xff0c;业内关于深度学习算法的潜力是否已达天花板的争论陆续发出。有人认为&#xff0c;基于深度学习算法的应用还有深度开拓空…

Mysql INSERT、REPLACE、UPDATE的区别

用于操作数据库的SQL一般分为两种&#xff0c;一种是查询语句&#xff0c;也就是我们所说的SELECT语句&#xff0c;另外一种就是更新语句&#xff0c;也叫做数据操作语句。言外之意&#xff0c;就是对数据进行修改。在标准的SQL中有3个语句&#xff0c;它们是INSERT、UPDATE以及…

软件调试的艺术笔记:GDB

很久之前&#xff0c;在https://blog.csdn.net/fengbingchun/article/details/41413381中简单整理过gdb中常用的一些命令&#xff0c;不齐全&#xff0c;这里按照《软件调试的艺术》一书中关于gdb的介绍再做次整理。《软件调试的艺术》于2009年由人民邮电出版社出版。 1. 预备…

App Store 审核被拒整理

整理以前和现在遇到的审核被拒第一&#xff1a;2.2 DetailsWe discovered one or more bugs in your app when reviewed on iPhone running iOS 8.1.3 on both Wi-Fi and cellular networks. Specifically, we were not able to complete the In App Purchase. When tapped on …

只服这篇“神文”:基于老子哲学、相对论的超级人工智能模型

作者 | Anonymous authors译者 | TroyChang出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;在此前我们为大家介绍 ICLR 2020 论文投稿情况时&#xff0c;提到了一篇“神作”在论文中作者们提出一个 ASI 概念&#xff08;Artificial Super Intelligence&am…

Navicat Premium使用教程【比较详细】

Navicat Premium使用教程简介&#xff1a;Navicat Premium是众所周知的数据库操作软件。本文比较详细。1、打开Navicat Premium&#xff0c;点击连接&#xff0c;选择MySQL&#xff0c;创建新连接。输入安装MySQL是的用户名和密码。点击确定。2、admin数据连接已经创建成功。下…

如何用Neo4j和Scikit-Learn做机器学习任务?| 附超详细分步教程

作者 | Mark Needham译者 | Tianyu、Shawnice编辑 | Jane出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;图算法不是一个新兴技术领域&#xff0c;在开源库中已经有很多功能强大的算法实现。近两年&#xff0c;业内的学者与科学家都在积极探索可以弥补深度…

Docker在Ubuntu16.04和Windows10家庭版上安装操作步骤

之前在 https://blog.csdn.net/fengbingchun/article/details/109559500 中对Docker作了简单的介绍&#xff0c;这里介绍下Docker在Ubuntu16.04 x86_64 64位上和Windows10 x86_64 64位家庭版上的安装过程。 在Ubuntu上安装Docker(或Docker引擎)&#xff0c;Ubuntu必须是64位的…

iOS 不同机型屏幕适配

// .pch 文件中写 // 判断是iPhone机型 /** 4s 960 * 640* 5/5s 1136 x 640* 6/6s/7/8 4.7英寸 1334 x 750* 6p/6sp/7p/8p 5.5英寸 1920 x 1080* X 5.8英寸 2436 x 1125}*/ #define IS_IPHONE_4s [UIScreen instancesRespondToSelector:selector(currentMode)] ? \ CGSizeEqua…

北京中天荣泰视觉检测 仿真

www.romtek.cnhttp://jobs.zhaopin.com/191485013250433.htm?ssidkeyy&ff01&ss101转载于:https://www.cnblogs.com/pengkunfan/p/4316018.html

Docker客户端常用命令整理

之前在 https://blog.csdn.net/fengbingchun/article/details/109584460 中介绍过在Windows10家庭版和Ubuntu16.04上安装Docker的操作步骤&#xff0c;这里整理下Docker客户端常用命令。 在Windows10家庭版上运行Docker后&#xff0c;通过VMware就不能打开Ubuntu16.04虚拟机了…

深度学习入门笔记,三流程序员如何凭借实力逆袭高薪?你不服不行!

最近经常有朋友提及&#xff0c;想要入门深度学习&#xff0c;该如何学习&#xff1f;关于深度学习&#xff0c;网上的资料很多&#xff0c;不过貌似大部分都不太适合初学者。 我曾经是一名三流程序员&#xff0c;每天的工作内容就是在前人留下的 bug 上写新的bug&#xff0c;我…

Swift编程语言

The Swift Programming Language中文手册1.【精校版】The Swift Programming Language--欢迎使用Swift--关于Swift2.【精校版】The Swift Programming Language-欢迎使用Swift-Swift 初见3.The Swift Programming Language--语言指南--基础部分4.The Swift Programming Languag…