汇编入门

CPU在运行的时候实际上是读取指令并一条一条的执行,而这些指令是二进制的,也就是机器码,但是由于二进制的语言对人类的可读性不好,因此便出现了汇编语言,一般而言,汇编语言可以看作是机器码的文本格式,它们间可以相互转换,还原成机器码后便可以被CPU执行。其特点有:

  • 可直接访问、控制各种硬件设备。比如存储器、CPU等,能最大限度地发挥硬件的功能
  • 能够不受编译器的限制,对生成的二进制代码进行完全的控制
  • 目标代码简短,占用内存少,执行速度快
  • 汇编指令是机器指令的助记符,同机器指令一一对应。每种CPU都有自己的机器指令集/汇编指令集,所以* 汇编语言不具备可移植性
  • 汇编语言知识点过多,开发者需要对CPU等硬件结构有所了解,不宜于编写、调试、维护
  • 不区分大小写,比如mov和MOV是一样的

对于一个使用高级语言的程序员来说,汇编语言不需要自己编写,但是至少需要看得懂,知道其中的原理,才能更好的排查问题。

总的来说,汇编代码是被CPU一条一条地取出执行的,CPU会通过这些指令来对寄存器和内存等进行操作。因此学好汇编,需要对寄存器和内存有一定的了解

寄存器

由于CPU的运算速度通常都比内存读写速度要快,而CPU要运算的时候都要从内存中读取数据。为了节省时间,一般CPU都自带缓存,除此之外,还自带了寄存器,用来存储频繁使用的数据,此外CPU还会使用寄存器与内存交换数据。

不同CPU里面的寄存器名字和数量都不一致,寄存器的用法基本都是想通的,但是大致上可以分成以下种:

通用寄存器

主要是AX,BX,CX,DX等等

指令寄存器

也就是IP,用于记录现在程序执行到哪

指针寄存器

主要是栈指针寄存器SP和栈基指针寄存器BP,每当有数据入栈/出栈的时候,都会导致SP改变

段寄存器

标志段的开始,主要有CS,DS,SS,ES等等

当然还有许多别的种类的寄存器没有提及,比如索引寄存器(SI,DI),而且,上述的通用寄存器部分又有各自的用途,比如AX用于累加和中断,CX用于计数、循环等等。实际上,如果仅是看代码的话,大部分寄存器在通常情况下都可以看作通用寄存器。因为它们存放的数值被汇编代码的指令控制的。我们只需要知道的特殊的寄存器(比如IP,SP)即可。

内存分段

在程序运行的时候,系统会给程序分配一定的内存空间,这些内存空间会分成好几段:

代码段

存放汇编指令,其段寄存器为CS,此外还有指令寄存器IP,CPU就是从这个段读取指令

数据段

存放全局变量,可以根据这些变量有没有被初始化进一步划分,其段寄存器为DS

堆栈段

用来存放程序运行期间产生的变量,又分成堆和栈,其中栈用于存放函数中的局部变量,而堆用来存放动态分配的变量,堆栈段的寄存器为SS,另外有个SP的寄存器永远指向栈顶。堆和栈的具体区别如下图。


image
扩展段

保存程序其它相关的信息,其段寄存器为ES

常用汇编指令

每一个处理器汇编指令都不太一样,但是其基本功能都是相通的,这里仅以8086处理器的指令集为例:

mov

传送指令,其用法为mov a,b,指的是将b的值赋值给a

add

加法,其用法为add a,b,将b的值加上a的值赋值给a,即a = a + b

sub

减法,其用法为sub a, b,与上面类似,相当于a = a - b

cmp

比较,其用法为cmp a, b,比较a和b的大小,其比较的结果存储在标志寄存器中。

jmp

无条件转移指令,通过修改IP和CS寄存器,使程序跳到目标地址运行

jcc

条件转移指令,jcc包含一系列的指令,通过判断标志寄存器的状态决定是否跳转

call

调用函数,程序会调到函数入口执行

ret

函数返回

高级语言程序结构对应的汇编语言

下面看一下程序的顺序结构、选择结构、循环结构下的汇编语言是怎么样的,本文所使用的语言为C++,处理器为x86_64,其指令集跟上面的不太一样,而且,其用法跟8086是相反的。

顺序结构

在main函数里面写上如下代码:

int a = 5;
int b = 1;
a++;
b += a;

其对应的汇编语言是这样的

;a = 5
0x100000f94 <+20>: movl   $0x5, -0x14(%rbp) ;将5赋值给偏移量为-0x14的内存区域,也就是说-0x14代表a
;b = 1
0x100000f9b <+27>: movl   $0x1, -0x18(%rbp) ;将1赋值给偏移量为-0x18的内存区域,也就是说-0x18代表b
;a++
0x100000fa2 <+34>: movl   -0x14(%rbp), %edi ;将a赋值给edi寄存器
0x100000fa5 <+37>: addl   $0x1, %edi ; edi寄存器加1
0x100000fa8 <+40>: movl   %edi, -0x14(%rbp) ;将edi寄存器赋值给a,这个时候完成了a++的操作
;b += a
0x100000fab <+43>: movl   -0x14(%rbp), %edi ;将a赋值给edi寄存器
0x100000fae <+46>: addl   -0x18(%rbp), %edi ;edi加上b的值
0x100000fb1 <+49>: movl   %edi, -0x18(%rbp) ;将edi寄存器赋值给a,这个时候完成了b += a的操作

选择结构

同样,在main函数中写一个简单的选择结构

int a = 5;
if (a>3) {
    a++;
}else {
    a--;
}

对应的汇编代码如下:

0x100000f82 <+18>: movl   $0x5, -0x14(%rbp)  ;a = 5
0x100000f89 <+25>: cmpl   $0x3, -0x14(%rbp)  ;a 和 3比较
0x100000f8d <+29>: jle    0x100000fa1        ;如果小于等于,就跳到0x100000fa1执行
;下面是a++的实现
0x100000f93 <+35>: movl   -0x14(%rbp), %eax
0x100000f96 <+38>: addl   $0x1, %eax
0x100000f99 <+41>: movl   %eax, -0x14(%rbp)
0x100000f9c <+44>: jmp    0x100000faa        ; 实现后程序跳转到0x100000faa执行
;下面是a--
0x100000fa1 <+49>: movl   -0x14(%rbp), %eax  
0x100000fa4 <+52>: addl   $-0x1, %eax
0x100000fa7 <+55>: movl   %eax, -0x14(%rbp)
0x100000faa .....

显然,汇编语言是使用cmp、jmp和jcc指令实现选择结构的。

循环机构

在main函数中写一个简单的循环:

int i = 0;
while(1){
    i++;
    if(i>5){
        break;
    }
}

这里使用了while做循环,实际上跟使用for循环的汇编代码是差不多的。

0x100000f82 <+18>: movl   $0x0, -0x14(%rbp) ;i = 0
0x100000f89 <+25>: movl   -0x14(%rbp), %eax ;这里开始循环
0x100000f8c <+28>: addl   $0x1, %eax  
0x100000f8f <+31>: movl   %eax, -0x14(%rbp)
0x100000f92 <+34>: cmpl   $0x5, -0x14(%rbp)
0x100000f96 <+38>: jle    0x100000fa1               
0x100000f9c <+44>: jmp    0x100000fa6  ;如果i>5,则跳出循环              
0x100000fa1 <+49>: jmp    0x100000f89  ;跳回0x100000f89,继续循环
0x100000fa6 ....

可以看出,循环结构也是通过cmp、jmp和jcc指令实现的。

参考文献

iOS之底层汇编(一)

程序内存空间(代码段、数据段、堆栈段)

8086汇编指令全集

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容