x86汇编基础-Move指令和基本寻址

本文的立意仅仅是讨论基本的x86汇编语法,。所以我要重申这里的汇编教程并不是深入研究汇编,本人也没有那么大的能耐。学习基础的汇编主要达到以下的程度即可。

  • 读懂常用的运算符指令
  • 读懂存储和加载指令
  • 了解x86和x86_64常用的寄存器的用途。
  • 了解基本的寻址模型。

了解基本的汇编以后,有什么用?

  • 加深你对C/C++的编译器行为和大部分内部操作大有益处
  • 让你了解到用C/C++实现的高层算法在汇编层面实现细节。
  • 让你更深入地了解函数栈调用的细节,能够写出高效的代码。

其实我这里可以提一个问题?你知道 以下简单的语句它们在计算机底层做了写什么操作吗?
int *a=123; 或
double b=456;
double *pp=b;

如果你心中没有明确的答案,请不要蛮目自信地欺骗自己C/C++的功底是如何如何地扎实.....,我自己都没自信心敢这么说?如果你打算专职用C/C++写算法实现的,那么基本的汇编功底是必须的。

之前我也写过一篇关于x64的汇编教程提交到寄存器和系统调用的基本关系《汇编语言基础:寄存器和系统调用》


上面的图例是一个比较完整的示意图,通常在IA32或x86_64中主要集中讨论CPU中的寄存器与主内存的数据交换,而其他的外部寄存器不在本文的讨论范围之内。

加载与存储

在汇编中mov指令主要用于在主内存(RAM)和寄存器之间传输数据,按照传递的方向可以分为两类

  • 加载(Load)指令:从主内存(RAM)寄存器传输数据,以一个给定的内存地址作为参数,他从内存中获取该地址位置存储的数据,并将该数据放入寄存器
  • 存储(Store)指令:即从寄存器中缓存的内存地址中所指向的目标位置,并将另外一个寄存器中缓存的数据保存到该目标位置,我们可以把内存看作已经编了号的数组,而通过索引就是内存地址,通过指定的内存地址可以在特定位置中的修改内存中的数据。

IA32中的寄存器

在IA32架构中有八个寄存器,其中有6个是通用的寄存器,另外两个是esp和ebp有特殊的用途,如你对栈有所了解的话,就知道esp是始终指向栈顶的,ebp始终指向栈底。对于EAX,EBX,ECX和EDX寄存器,也会通常使用小字节的数据类型。 例如,EAX的最低有效2字节可被视为称为AX的16位寄存器。 AX的最低有效字节可以用作单个8位寄存器,称为AL,而AX的最高有效字节可以用作单个8位寄存器,称为AH。 这些名称指的是相同的物理寄存器。 当将两个字节的数量放入DX中时,更新将影响DH,DL和EDX的值。 这些子寄存器主要是较旧的16位版本指令集的保留。 但是,在处理小于32位(例如1字节ASCII字符)的数据时,它们有时很方便。


图片来源于网络

mov指令的长度分类

根据操作数的字长可以分为三个版本的mov指令

  • movl Source Dest : L表示可以移动4个字节
  • movw Source Dest: W表示可以移动2个字节
  • movb Source Dest: B表示可以移动1个字节

mov指令的操作数

并且在移动指令中会用到两个操作数,Source表示移动的数据源,Dest表示移动的数据最后到达的位置。
通常在x86用的比较频繁的mov指令版本是32位的movl,这里就以 movl Source Dest为例子

mov指令的操作数通常分为三类

  • 立即数(Immediate) 可以将其视为常数,和C语言的常量类似,但是以“$”为前缀,例如0x400,-500
  • 寄存器(Register)可以是以上8个整数寄存器中的其中一个,例如:“%eax”,“%edx”,当我们执行类似“movl %eax %edx”这种情况下,eax寄存器就成为源参数,而edx寄存器就成为目标参数,其含义是获取eax中的内容并存储在edx中。
  • 内存(Memory):而内存作为操作数通常是由寄存器缓存给定的内存地址来间接去操作的,该地址占用4个字节,例如(%eax),当寄存器在一个括号中,我们就说eax持有一个指向RAM中的某个位置的地址,你可以类比为类似C/C++中的指针变量,的那么 movl (%eax) %ebx 表示的是什么意思呢?你可以考虑一下表示什么意思?

mov的操作数组合

movl指令通过不同类型的操作数组合,能够表达出不同类型的指令类型的。


mov的参数组合
  • 例如源参数是立即数,而目标参数是的寄存器,即“movl $123,%eax ”表示将常量保存在寄存器eax中,等价于C/C++声明并初始化一个变量例如
     int a=123;
    
    其实在C编译器对每个声明的基本数据类型的变量会映射到一个寄存器中,例如一个int类型4字节,会选择一个32位的寄存器类装载int整数等待CPU中的运算单元(AU)处理。
  • 源参数是立即数,而目标参数是一个主内存中的地址,即“movl $123,%(eax) ”表示将常量保存到eax寄存器中的存储的内存位置所指向的内存位置,同理等价的C/C++语句如下:
    int *a=123;
    
  • 源参数是寄存器,而目标参数也是寄存器,例如“movl %edx,%eax”其实就是在寄存器之间拷贝数据。
  • 源参数是寄存器,而目标参数是内存。其实就是一种存储类型,例如“movl %eax,(%edx)”,表示当前寄存器eax中的数据写回主内存中的某个位置,而这个位置是由寄存器edx保存的地址所指向的。
  • 源参数是内存,而目标参数是寄存器,例如“movl (%edx),%eax”这是从内存中加载数据到eax寄存器当中。因此表示加载指令的其中一种。

可能你会想到最后一种,有从“内存”到“内存”传递的指令类型吗?单一的一条指令是不可能的。只能通过两步实现

  • 首先“内存”到“寄存器”例如:“movl (%edx),%eax
  • 然后“寄存器”到“内存” 例如:“movl %eax,(%ecx)

基本的内存寻址模型

间接访问
就是“(R)”这种格式,R表示一个寄存器名称。寄存器中保存着一个内存地址,我们用mov指令操作主内存时,只能通过使用该寄存器中的内容去实现对该地址指向的RAM中位置进行读/写操作。对于操作系统来说,内存其实就是一个连续的字节数组,每个字节都有对应的编号,而这个编号就是内存地址,也可以理解为该字节数组的索引。

我们用“RAM”表示主内存,那么 (R) 其实等价于 RAM[Reg[R]],

那么“movl (%edx),%eax”类似这样的指令的含义到这里应该不用多说了吧!

移位寻址
英文名称叫“Displacement”,这个其实就是在间接寻址表达式的基础是加上一个有符号的整数N。在汇编中抽象的移位寻址表达式“N(R)

我们用“RAM”表示主内存,那么 N(R) 其实等价于 RAM[Reg[R]+N],

那么具体的例子就是

  • 例如 “-4(%ebp)”:表示ebp寄存器中缓存的内存地址向低地址方向移动了4个字节
  • 例如“8(%ebp)”:表示ebp寄存器中缓存的内存地址向高地址方向移动8个字节。
  • 那么像这种“movl 4(%esp),%ecx”其实就是寄存器esp的指针向高地址方向偏移4个字节后的个新的地址,从该新地址指向的内存位置获取数据并保存到寄存器ecx。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容

  • 1.地址总线,数据总线,控制总线在哪里,它们有什么作用?答:它们都是cpu连接外部组件的线路。地址总线:地址总线A...
    MagicalGuy阅读 1,346评论 0 1
  • Return-Oriented-Programming(ROP FTW) Author: Saif El-Sher...
    RealSys阅读 3,229评论 0 2
  • Java原子类中CAS的底层实现 - GoldArowana - 博客园 Java原子类中CAS的底层实现 从Ja...
    听一首老歌阅读 639评论 0 1
  • 寄存器 用于解决处理器与内存之前的数据存储效率问题存在的。IA-32平台寄存器核心组有下面几种. 通用寄存器 8个...
    dodomix阅读 1,600评论 0 0
  • 《中国式众筹》中第四章“众筹十一个常见问题”:先找人,还是先找场地? 对于这个问题,我认为应该先选人,后选地...
    朝夕得闲大王阅读 304评论 0 2