An example: GCC generated ARM assembly

align:机器码opcode缩进(align)你会了吗?

  • align:带有一个数字,规定了没条指令或数据的对应的opcode(机器码)的长度
    对于数据: 多余的部分补充为NULLs
    对于指令: 用NULL指令或者(等效如 MOV EAX,EAX )
    数据段
.DATA
var2 BYTE  02; 变量长度为1
ALIGN 4
var2 BYTE  02; 变量长度为1
;对应的的编译器生成代码如下:
.DATA
;------------分割线------------------------------
.data:00402000 var1            db 1
.data:00402001                 db    0; 这个NULL是用来强制下一条指令的机器代码长度为4的倍数
.data:00402002                 db    0; 这个NULL是用来强制下一条指令的机器代码长度为4的倍数
.data:00402003                 db    0; 这个NULL是用来强制下一条指令的机器代码长度为4的倍数
.data:00402004 var2            db 2 

代码段

.CODE
;强制第一条指令的机器码长度为4的倍数
ALIGN 4
;入口点
EntryPoint:
MOVZX EAX, var1 
MOVZX EAX, var2 
MOVZX EAX, var3 
;对应的的编译器生成代码如下:
.CODE
;------------分割线------------------------------
.text:00401000 start:
;不能强制缩进入口点的代码对应的机器码长度
.text:00401000                 movzx   eax, var1
.text:00401007                 movzx   eax, var2
.text:0040100E                 movzx   eax, var3
;下面的指令是七字节指令,强制第三条指令的机器码长度为4的倍数
MOVZX EAX, var1 
MOVZX EAX, var2 
ALIGN 4 
MOVZX EAX, var3 
;这个指令的是1字节长度--opcode(cc)
;强制将其机器码缩进成2字节的倍数
ALIGN 2
INT 3
;------------分割线------------------------------
.text:00401015                 movzx   eax, var1
.text:0040101C                 movzx   eax, var2
.text:00401023                 nop; 这个NOP的填充用来强制第三条指令的机器码为4的倍数
.text:00401024                 movzx   eax, var3
.text:00401043                 nop; 这个NOP的填充用来强制第三条指令的机器码为2的倍数
.text:00401044                 int     3              ; Trap to Debugger
.text:00401044; --------------------------------------------------------------------------
  • 以句号(period)开头的是汇编程序的提示符(directives)

表示一个循环LOOP : .L4:
下面这两条指令声明下面的函数使用16位的thumb指令集
.code 16
.thumb_func

  • 函数指令

函数调用:bl
从函数中返回:bx
函数调用使用的参数存放在r0-r3中,如果超过三个参数,使用堆栈存放参数,并且返回值存放在r0
函数调用完后,r0-r3(r12)被清除,所以想要使用函数调用完得到的值,是需要手动将其保存下来的
r4-r15:在函数调用时被push到栈中

https://stackoverflow.com/questions/11277652/what-is-the-meaning-of-align-an-the-start-of-a-section

one example:使用GCC来生成汇编程序

使用参数-S或者-save-temps来捕获

指令(instruction) 解释说明
ldr 字数据加载指令 ldr 目的寄存器,源,将源(内存中的数据)存进目的寄存器中
str 字数据存储指令 str {条件} 源寄存器,<存储器地址>,将源寄存器中的数据存入内存地址
小知识
r0 arm的寄存器,寄存器中可以存储数据,并且r0就可以看成存储的数据
r11(FP) 可看做intel架构的EBP,指向栈帧的底部,是一个固定值
r13(SP) 栈指针,可看做ESP,动态的,随着栈的pop,push而改变
[r0] r0存储的数据作为内存地址,[r0]表示这个内存地址
LDR例子
ldr r2,[r0] 将[r0]这个数据存进r2这个寄存器内
LDR R1,=0xE0000000 R1=0xE0000000,立即数赋值,将立即数存进R1寄存器中
LDR R1,0xE0000000 将内存地址为0xE0000000所指向的数据存入寄存器R1
STR例子
STR R1,[R2] 将寄存器R1中存储的数据存入,内存地址为R2(寄存器R2存储的值为内存地址)的区域

小结:mov指令是寄存器之间的数据操作,STR和LDR是寄存器和内存地址之间的操作

非常简单的一个小函数
func1.cpp(C++)+ARM gcc 5.4(linux)

//从参数num2中得到数据,然后乘以240赋值给参数num1,然后返回参数num1
//实际上参数num1的内容并没有使用,但是就这样分析吧,懒得更改了
int main(int num1, int num2) {
    num1 = num2 * 240;
    return num1;
}
;------------分割线------------------------------
main:
        @@ int main(int num1, int num2) {
        str     fp, [sp, #-4]!   //push {fp},sp-4=fp,保存fp的值(感叹号:先修改寄存器的值再使用)
        add     fp, sp, #0       //fp=sp,将fp指向sp位置
        sub     sp, sp, #12      //sp=sp-12,栈指针下移,存储变量
        str     r0, [fp, #-8]    //引入参数数据(r0),将数据赋值给变量num1(栈地址:fp-8)
        str     r1, [fp, #-12]   //变量num2,栈地址:fp-12

        @@ num1 = num2 * 240;
        @@ 基数左移4位即乘以16,减一个基数即乘以15,在左移4(乘以16),总计乘以15*16=240
        ldr     r2, [fp, #-12]   //r2 = num2
        mov     r3, r2           //r3=r2=num2
        mov     r3, r3, asl #4   //r3左移4位,赋值给r3(r3 = r3*16 = num2*16)
        rsb     r3, r2, r3       //r3 = r3-r2,反向减法(r3=r3*16-r3=num2*15)
        mov     r3, r3, asl #4   //r3 =num2 *15 *16
        str     r3, [fp, #-8]    //num1 = r3=num2*240

        @@ return num1;
        ldr     r3, [fp, #-8]    

        @@ }
        mov     r0, r3           //r0中也存有返回值
        sub     sp, fp, #0
        ldr     fp, [sp], #4     //pop {fp}, post-indexed后变,将内存地址的数据赋给fp后,再sp=sp+4
        bx      lr               //返回到下一条指令,LinkPointer存有下一条指令的内存地址

基础功能 Basic Features

  • 寄存器

ARM有1632位的寄存器r0-r15

std gcc arm 描述
r0-r3 r0-r3 a1-a3 函数参数的存放,暂存寄存器scratch registers
r12 ip IP 和r0-r4同类
r4-r8 r4-r8 v1-v5 variable函数调用过程中,存储变量的寄存器
r9 r9 v6/SB 特殊平台/variable
r10 sl v7 variable
r11 fp v8 varible/帧指针,用于存储栈底地址(EBP)
r13 sp SP 栈指针,指向栈顶
r14 lr LR 链接寄存器,存储下一条指令的内存地址
r15 pc PC 程序计数器,随着指令的执行而增加;当执行到子函数时,用来存储当前指令的地址
  • 指令分类
    1、数据操作,算术和位操作
    2、内存操作,load或者store
    3、分支操作,条件跳转

每个ARM的指令都可以有条件的执行

  • 不带条件的指令,不管是否执行都必须内存中读取
@@ r2 = r0>=r1 ? r0:r1;
@@ 如果r0 >= r1,就将r0赋值给r2

    @@ 传统汇编
    cmp     r0, r1      //比较r0,r1
    blt .Lbmax          //r0<r1 brance less than小于就跳转到.Lbmax
    mov     r2, r0      //r2 = r0
    b       .Lrest
.Lbmax:
    mov     r2, r1
.Lrest

带有条件的汇编,指令简便、就会快捷

cmp     r0, r1
movge   r2, r1    //大于等于则执行
movlt   r2, r0    //less than小于就执行
指令 解释
sub 不设置状态寄存器
subs 设置状态寄存器
  • 桶型位移器(Barrel Shifter)
    内嵌的ARM核心组成之一,所以比任何算数运算都快
    任何指令都可以再没有消耗的情况使用桶型位移器移动到其中一个操作数
桶型位移操作 注释
lsl logic left shift逻辑左移(同asl算数左移)
lsr logic right shift逻辑右移
asr arithmetic right shift算数右移
ror rotate right循环右移

逻辑右移和算数右移的区别在于signed/unsigned有符号/无符号详情查看bit ops section

移位寄存器可以用来操作Op2这个操作数

@@r0= r1+(r1<<3) = r1 + r1*8
add    r0, r1, r1, lsl #3   

受到限制的立即数

op{cond}{s} Rd, Rn, Op2

  • ARM每条指令32位长度,4位条件代码、4位目的操作数、4位的第一操作寄存器,最后只剩下12位留给了立即数
  • 12位立即数:8位数字(n),4位循环移位字段(r)
立即数 = n ror 2*r

数据指令

  • 只能再寄存器中,不能直接在内存变量中
  • 大多数据指令是有一个目的寄存器Rd,两个操作数Rn,Op2,Rn经常是寄存器,Op2可以是四类(立即数#n、寄存器Rm、带有立即数的移位寄存器Rm ,lsl #n,带有寄存器的移位寄存器Rm ,lsl Rs
数据操作
  • Arithmetic算数表,只有加减法。rsbreverse subtract是特殊的减法,Op2是被减数,并且Op2只允许是立即数和移位寄存器
    结尾带有c(carry)的指令表示条件指令,带有进位的指令,允许算数值超过寄存器的大小,例如计算0x00FF+0x0104,因为第二个数超过了8位,需要分步计算,从最低有效位开始,最低字节位给出,0xFF + 0x04这个加法再c的条件下,允许进位,设置进位标志,计0x03加一个进位标志。然后是第二部分,高位加法0x00+0x01+1最后一个1是进位,计0x02,合计0x203。

QUESTION

  • 当程序从子方法返回到父方法时,PC是接着进入子方法之前,还是接着子方法结果来继续?

ARM在线汇编网站
ARM Instruction Set

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

推荐阅读更多精彩内容