汇编语言入门汇编指令及寄存器详解教程

目录
  • 前言
  • 什么是汇编语言
    • 汇编语言产生的原因
    • 汇编与二进制的关系
  • 寄存器
    • 寄存器作用
    • 存取速度比较
    • 寄存器分类
    • 常用寄存器用途
    • 寄存器EAX、AX、AH、AL的关系
  • 汇编语言指令
    • 数据传送指令
    • 算术运算指令
    • 逻辑运算指令
    • 循环控制指令
    • 转移指令
  • linux 和 windows 下汇编的区别
  • 总结

前言

我们大都是被高级语言惯坏了的一代,源源不断的新特性正在逐步添加到各类高级语言之中,汇编作为最接近机器指令的低级语言,已经很少被直接拿来写程序了,不过我还真的遇到了一个,那是之前的一个同事,因为在写代码时遇到了成员函数权限及可见性的问题,导致他无法正确调用想执行的函数,结果他就开始在 C++ 代码里嵌入汇编了,绕过了种种限制终于如愿以偿,但是读代码的我们傻眼了…

因为项目是跨平台的,代码推送的 Linux 上编译的时候他才发现,汇编代码的语法在 Linux 和 Windows 上居然是不一样的,结果他又用一个判断平台的宏定义“完美”的解决了,最终这些代码肯定是重写了啊,因为可读性太差了,最近在学习左值、右值、左引用和右引用的时候,总是有人用程序编译生成的中间汇编代码来解释问题,看得我迷迷糊糊,所以决定熟悉一下简单的汇编指令,边学习边记录,方便今后忘记了可以直接拿来复习。

什么是汇编语言

汇编语言是最接近机器语言的编程语言,引用百科中的一段话解释为:

汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。汇编语言又被称为第二代计算机语言。

汇编语言产生的原因

对于绝大多数人来说,二进制程序是不可读的,当然有能人可以读,比如第一代程序员,但这类人快灭绝了,直接看二进制不容易看出来究竟做了什么事情,比如最简单的加法指令二进制表示为 00000011,如果它混在一大串01字符串中就很难把它找出来,所以汇编语言主要就是为了解决二进制编码的可读性问题。

汇编与二进制的关系

换句话来说,汇编语言就是把给机器看的二进制编码翻译成人话,汇编指令是机器指令的助记符,与机器指令是一一对应的关系,是一种便于阅读和记忆的书写格式。有效地解决了机器指令编写程序难度大的问题,并且使用编译器,可以很方便的把汇编程序转译成机器指令程序,比如之前提到的 00000011 加法指令,对应的汇编指令是 ADD,在调用汇编器时就会把 ADD 翻译成 00000011

寄存器

说到汇编指令不得不提到寄存器,寄存器本身是用来存数据的,因为 CPU 本身只负责逻辑运算,数据需要单独储存在其他的地方,但是对于不熟悉寄存器的人来说会有疑惑,数据不是存在硬盘上吗?或者说数据不是存在内存中吗?这些想法都没错,那么寄存器是用来做什么的呢?

寄存器作用

其实硬盘、内存都是用来存储数据的,但是 CPU 的运算速度远高于内存的读写速度,更不用说从硬盘上取数据了,所以为了避免被拖慢速度影响效率,CPU 都自带一级缓存和二级缓存,一些 CPU 甚至增加了三级缓存,从这些缓存中读写数据要比内存快很多,但是还是无法使用飞速运转的 CPU,所以才会有寄存器的存在。

寄存器不是后来增加的,在最初的计算中就已经设计出来,相比而言,多级缓存出现的更晚一些,通常那些最频繁读写的数据都会被放在寄存器里面,CPU 优先读写寄存器,再通过寄存器、缓存跟内存来交换数据,达到缓冲的目的,因为可以通过名称访问寄存器,这样访问速度是最快的,因此也被称为零级缓存。

存取速度比较

通过上面的叙述我们可以知道存取速度从高到低分别是: 寄存器 > 1级缓存 > 2级缓存 > 3级缓存 > 内存 > 硬盘,关于它们的存取速度,举个例子很容易就能明白了,比如我们做菜(CPU工作)时,取手中(寄存器)正拿着的肉和蔬菜肯定是最快的,如果没有就需要把案板上(1级缓存)处理好的菜拿过来,如果案板上没有就在更远一点的洗菜池(2级缓存)中找一找,还没找到的话就要到冰箱(3级缓存)中看一看了,这时发现家里真没有,那去楼下的菜店(内存)去买点吧,转了一圈发现没有想要的,最后还是开车去农贸市场(硬盘)买吧。

通过上面这个例子应该能明白它们的速度关系了,既然缓存这么快,为什么不用缓存代替内存,或者将2、3级缓存都换成1级缓存呢?这里边有一个成本问题,速度越快对应着价格越高,如果你买过机械硬盘和固态硬盘应该很容易就理解了。

寄存器分类

常用的 x86 CPU 寄存器有8个:EAXEBXECXEDXEDIESIEBPESP,据说现在寄存器总数已经超过100个了,等我找到相关资料再来补充,上面这几个寄存器是最常用的,这些名字也常常出现在汇编的代码中。

我们常说的32位、64位 CPU 是指数据总线的宽度或根数,而寄存器是暂存数据和中间结果的单元,因此寄存器的位数也就是处理数据的长度与数据总线的根数是相同的,所以32位 CPU 对应的寄存器也应该是32位的。

常用寄存器用途

上面提到大8个寄存器都有其特定的用途,我们以32位 CPU 为例简单说明下这些寄存器的作用,整理如下表:

寄存器 含义 用途 包含寄存器
EAX 累加(Accumulator)寄存器 常用于乘、除法和函数返回值 AX(AH、AL)
EBX 基址(Base)寄存器 常做内存数据的指针, 或者说常以它为基址来访问内存. BX(BH、BL)
ECX 计数器(Counter)寄存器 常做字符串和循环操作中的计数器 CX(CH、CL)
EDX 数据(Data)寄存器 常用于乘、除法和 I/O 指针 DX(DH、DL)
ESI 来源索引(Source Index)寄存器 常做内存数据指针和源字符串指针 SI
EDI 目的索引(Destination Index)寄存器 常做内存数据指针和目的字符串指针 DI
ESP 堆栈指针(Stack Point)寄存器 只做堆栈的栈顶指针; 不能用于算术运算与数据传送 SP
EBP 基址指针(Base Point)寄存器 只做堆栈指针, 可以访问堆栈内任意地址, 经常用于中转 ESP 中的数据, 也常以它为基址来访问堆栈; 不能用于算术运算与数据传送 BP

寄存器EAX、AX、AH、AL的关系

在上面的图标中每个常用寄存器后面还有其他的名字,它们是同一个寄存器不同用法下的不同名字,比如在32位 CPU 上,EAX是32位的寄存器,而AX是EAX的低16位,AH是AX的高8位,而AL是AX的低8位,它们的对照关系如下:

00000000 00000000 00000000 00000000
|===============EAX===============|---4个字节
                  |======AX=======|---2个字节
                  |==AH===|-----------1个字节
                          |===AL==|---1个字节

汇编语言指令

终于说到汇编常用指令了,因为 linuxwindows 下的汇编语法是有些不同的,所以下面我们先通过 windows 下的汇编指令来简单学习一下,后续再来比较两者的不同。

数据传送指令

指令 名称 示例 备注
MOV 传送指令 MOV dest, src 将数据从src移动到dest
PUSH 进栈指令 PUSH src 把源操作数src压入堆栈
POP 出栈指令 POP desc 从栈顶弹出字数据到dest

算术运算指令

指令 名称 示例 备注
ADD 加法指令 ADD dest, src 在dest基础上加src
SUB 减法指令 SUB dest, src 在dest基础上减src
INC 加1指令 INC dest 在dest基础上加1
DEC 减1指令 DEC dest 在dest基础上减1

逻辑运算指令

指令 名称 示例 备注
NOT 取反运算指令 NOT dest 把操作数dest按位取反
AND 与运算指令 AND dest, src 把dest和src进行与运算之后送回dest
OR 或运算指令 OR dest, src 把dest和src进行或运算之后送回dest
XOR 异或运算 XOR dest, src 把dest和src进行异或运算之后送回dest

循环控制指令

指令 名称 示例 备注
LOOP 计数循环指令 LOOP label 使ECX的值减1,当ECX的值不为0的时候跳转至label,否则执行LOOP之后的语句

转移指令

指令 名称 示例 备注
JMP 无条件转移指令 JMP lable 无条件地转移到标号为label的位置
CALL 过程调用指令 CALL labal 直接调用label
JE 条件转移指令 JE lable zf =1 时跳转到标号为label的位置
JNE 条件转移指令 JNE lable zf=0 时跳转到标号为label的位置

linux 和 windows 下汇编的区别

前面说到 linuxwindows 下的汇编语法是不同的,其实两种语法的不同和系统不同没有绝对的关系,一般在 linux 上会使用 gcc/g++ 编译器,而在 windows 上会使用微软的 cl 也就是 MSBUILD,所以产生不同的代码是因为编译器不同,gcc 下采用的是AT&T的汇编语法格式,MSBUILD 采用的是Intel汇编语法格式。

差异 Intel AT&T
引用寄存器名字 eax %eax
赋值操作数顺序 mov dest, src movl src, dest
寄存器、立即数指令前缀 mov ebx, 0xd00d movl $0xd00d, %ebx
寄存器间接寻址 [eax] (%eax)
数据类型大小 操作码后加后缀字母,“l” 32位,“w” 16位,“b” 8位(mov dx, word ptr [eax]) 操作数前面加dword ptr, word ptr,byte ptr的格式 (movb %bl %al)

总结

汇编指令是机器指令的助记符,与机器指令是一一对应的

AT&T的汇编语法格式和Intel汇编语法格式的是不同的

常用寄存器:EAXEBXECXEDXEDIESIEBPESP

存取速度从高到低分别是: 寄存器 > 1级缓存 > 2级缓存 > 3级缓存 > 内存 > 硬盘

的汇编指令:movjejmpcalladdsubincdecandor

如今的每分每秒都是人生,不要总想着将自然发生的事情拖到预定的时刻才进行~

以上就是汇编语言入门汇编指令及寄存器详解教程的详细内容,更多关于汇编语言指令及寄存器的资料请关注我们其它相关文章!

(0)

相关推荐

  • 汇编语言入门教程阮一峰版

    汇编语言是一种最低级.最古老.不具有移植性的编程语言,它能够直接访问计算机硬件,所以执行效率极高,占用资源极少,一般用于嵌入式设备.驱动程序.实时应用.核心算法等. 汇编语言的缺点是开发周期特别长,实现一个简单的功能都非常麻烦,已经很少用来编写应用程序了. 学习编程其实就是学高级语言,即那些为人类设计的计算机语言. 但是,计算机不理解高级语言,必须通过编译器转成二进制代码,才能运行.学会高级语言,并不等于理解计算机实际的运行步骤. 计算机真正能够理解的是低级语言,它专门用来控制硬件.汇编语言就是

  • 汇编语言中的各种寄存器介绍

    汇编语言(assembly language)是一种用于电子计算机.微处理器.微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址.在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令.特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植. 计算机寄存器分类简介: 32位CPU所含有的寄存器有: 4个数据寄存器(EAX.EBX.ECX和EDX) 2个变址和指针寄存器(

  • 常用的汇编指令与技巧(收藏)

    1.数据传送指令:mov move r1,r2 /*r1=r2*/ move r1,#4096 /*r1=4096*/ 2.大范围的地址读取指令:ldr ldr r1,=0x123456789 /*r1=0x123456789*/ ldr r1,=label /*获取绝对地址,即label的地址*/ label: -- 3.内存访问指令(当ldr后面没有=号时为内存读取指令) 读取指令:ldr ldr r1 ,[r2,#4] /*将内存地址为r2+4的数据读取到r1中,相当于C语言中的*操作*/

  • 汇编语言开发过程详解

    程序开发过程 一.逐步开发 (1)源程序的编辑 源程序文件是无格式文件.纯文本类型 以.ASM为扩展名,可使用任何文本编辑器 ►Windows的记事本Notepad ►其他程序开发工具中的编辑环境 ►专注于源程序编写的编辑软件,例如UltraEdit32 ; eg0000.asm in Windows Console include io32.inc .data msg byte 'Hello World' ; 数据定义 .code start: mov eax,offset msg call

  • 王爽 汇编语言学习笔记(详细)

    王爽汇编语言第三版是一款高清完整版的专业编程图书,该书结构设计合理,内容全面涵盖知识点丰富,适合自学者使用,有需要者快来 一.基础知识 1.指令 机器指令:CPU能直接识别并执行的二进制编码 汇编指令:汇编指令是机器指令的助记符,同机器指令一一对应. 指令:指令通常由操作码和地址码(操作数)两部分组成 指令集:每种CPU都有自己的汇编指令集. 汇编语言由3类指令组成. 汇编指令 伪指令:没有对应的机器码,由编译器执行,计算机并不执行 其他符号:如+.-.*./等,由编译器识别,没有对应的机器码.

  • 汇编语言入门汇编指令及寄存器详解教程

    目录 前言 什么是汇编语言 汇编语言产生的原因 汇编与二进制的关系 寄存器 寄存器作用 存取速度比较 寄存器分类 常用寄存器用途 寄存器EAX.AX.AH.AL的关系 汇编语言指令 数据传送指令 算术运算指令 逻辑运算指令 循环控制指令 转移指令 linux 和 windows 下汇编的区别 总结 前言 我们大都是被高级语言惯坏了的一代,源源不断的新特性正在逐步添加到各类高级语言之中,汇编作为最接近机器指令的低级语言,已经很少被直接拿来写程序了,不过我还真的遇到了一个,那是之前的一个同事,因为在

  • LyScript获取上一条与下一条汇编指令的方法详解

    LyScript 插件默认并没有提供上一条与下一条汇编指令的获取功能,当然你可以使用LyScriptTools工具包直接调用内置命令得到,不过这种方式显然在效率上并不理想,我们需要在LyScript插件API基础上自己封装实现这个功能. LyScript项目地址:https://github.com/lyshark/LyScript 获取下一条汇编指令 下一条汇编指令的获取需要注意如果是被命中的指令则此处应该是CC断点占用一个字节,如果不是则正常获取到当前指令即可. 1.我们需要检查当前内存断点

  • 汇编语言中mov和lea指令的区别详解

    指令(instruction)是一种语句,它在程序汇编编译时变得可执行.汇编器将指令翻译为机器语言字节,并且在运行时由 CPU 加载和执行. 一条指令有四个组成部分: 标号(可选) 指令助记符(必需) 操作数(通常是必需的) 注释(可选) 最近在学习汇编语言,过程中遇到很多问题,对此在以后的随笔会逐渐更新,这次谈谈mov,lea指令的区别   一,关于有没有加上[]的问题 1,对于mov指令来说: 有没有[]对于变量是无所谓的,其结果都是取值 如: num dw 2 mov bx,num mov

  • 汇编语言Debug命令详解教程

    目录 1. Debug-R命令 2. Debug-D命令 3. Debug-E命令 4. Debug-U命令 5. Debug-T命令 6. Debug-A命令 参考书籍<汇编语言>--王爽 Debug的命令比较多,这里我介绍常用的命令,其余的等需要的时候再进行查询. 命令 用途Debug-R查看.改变CPU寄存器的内容Debug-D查看内存中的内容Debug-E改写内存中的内容Debug-U将内存中的机器指令翻译成汇编指令Debug-T执行一条机器指令Debug-A以汇编指令的格式在内存中写

  • C语言ASM汇编内嵌语法详解

    3 GCC Inline ASM GCC 支持在C/C++代码中嵌入汇编代码,这些汇编代码被称作GCC Inline ASM--GCC内联汇编.这是一个非常有用的功能,有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中,另外也允许我们直接写 C/C++代码中使用汇编编写简洁高效的代码. 1.基本内联汇编 GCC中基本的内联汇编非常易懂,我们先来看两个简单的例子: __asm__("movl %esp,%eax"); // 看起来很熟悉吧! 或者是 __asm__(&q

  • Python入门之三角函数atan2()函数详解

    描述 atan2() 返回给定的 X 及 Y 坐标值的反正切值. 语法 以下是 atan2() 方法的语法: import math math.atan2(y, x) 注意:atan2()是不能直接访问的,需要导入 math 模块,然后通过 math 静态对象调用该方法. 参数 x -- 一个数值. y -- 一个数值. 返回值 返回给定的 X 及 Y 坐标值的反正切值. 实例 以下展示了使用 atan2() 方法的实例: #!/usr/bin/python import math print

  • vue自定义指令directive实例详解

    下面给大家介绍vue自定义指令directive,具体内容如下所示: 官网截图实例 vue除了一些核心的内部定义的指令(v-model,v-if,v-for,v-show)外,vue也允许用户注册自己的一些功能性的指令,有时候你实在是要对Dom操作,这个时候是自定义指令最合适的了. 来直接看例子:当页面加载时使得元素获得焦点(autofocus 在移动版 Safari 是不支持的),就是当页面加载好了,不做任何的操作使得表单自动获得焦点,光标自动在某个表单上代码如下: Vue.directive

  • vue2.0自定义指令示例代码详解

    1.什么是指令? 指令通常以"v-"作为前缀, 以方便Vue知道你在使用一种特殊的标记. 除了 Vue 核心携带着的一些默认指令(v-model 和 v-show)之外, Vue 还允许你注册自己的自定义指令.某些情况下,还是需要对普通元素进行一些底层 DOM 访问, 这也是自定义指令仍然有其使用场景之处. 2.全局指令: 当页面加载时,元素将获取焦点,事实上,在访问页面时,如果你还没有点击任何地方,上面的输入框现在应该处于获取焦点的状态.现在让我们构建指令以完成此效果: <te

  • Vue.js 中的 v-cloak 指令及使用详解

    先来看下vue.js 中的v-cloak 指令 可以使用 v-cloak 指令设置样式,这些样式会在 Vue 实例编译结束时,从绑定的 HTML 元素上被移除. 当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码.我们可以使用 v-cloak 指令来解决这一问题. html: <div id="app"> {{context}} </div> js: <script> var app = new

  • Vue.js 中的 v-show 指令及用法详解

    1 用法 v-show 指令通过改变元素的 css 属性(display)来决定元素是显示还是隐藏. html: <div id="app"> <p v-show="type==='科技'">大数据之下的锦鲤:为什么你的微博总抽不到奖</p> </div> js: <script> var app = new Vue({ el: '#app', data: { type:'技术' } }); </sc

随机推荐