学习笔记之ARM汇编



1 内存访问指令

1.1 LDR:字数据读取指令

指令语法格式: LDR Rd, <地址>
LDR指令用于从地址中将一个32位的字读取到指令中的目标寄存器(Rd)中

    LDR R0,[R1,#4]         ; 将内存单元R1+4中的字读取到R0寄存器中
    LDR R0,[R1,#-4]        ; 将内存单元R1-4中的字读取到R0寄存器中
    LDR R0,[R1,R2]         ; 将内存单元R1+R2中的字读取到R0寄存器中
    LDR R0,[R1,-R2]        ; 将内存单元R1-R2中的字读取到R0寄存器中
    LDR R0,[R1,R2,LSL #2]  ; 将内存单元(R1+R2*4)中的数据读取到R0中
    LDR R0,[R1,#4]!        ; 将内存单元R1+4中的数据读取到R0中,同时R1=R1+4
    LDR R0,[R1,R2]!        ; 将内存单元R1+R2中的数据读取到R0中,同时R1=R1+R2
    LDR R0,[R1,R2,LSL #2]! ; 将内存单元(R1+R2*4)中的数据读取到R0中,同时R1=R1+R2*4
    
    LDR R0,[R1],#4         ; 将内存单元R1中的数据读取到R0中,然后R1=R1+4
    LDR R0,[R1],R2         ; /将内存单元R1中的数据读取到R0中,然后R1=R1+R2
    LDR R0,[R1],R2,LSL #2  ; 将内存单元R1中的数据读取到R0中,然后R1=R1+R2*4

伪指令形式: LDR Rd, =expr
装载一个32bit常数或一个地址到寄存器Rd中,当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或者MVN指令代替该LDR伪指令。

LDR R0,=0x12345678     ;  R0=0x12345678伪指令,它会被拆分为几条真正的RAM指令,因为ARM指令是
                       ;32bit,有几个bit表示指令本身,剩下的位数不足以保存任意数,只能表示简单值(被
                       ;称为立即数)

1.2 STR:字数据写入指令

指令语法格式: STR Rd, <地址>
STR指令用于将一个32位的字数据写入到指令中指定的内存单元.

    STR R0,[R1,#0x100]     ; 将R0中的字数据保存到内存单元(R1+0x100)中
    STR R0,[R1],#8         ; 将R0中的字数据保存到内存单元R1中,然后R1=R1+8

1.3 LDM/STM:批量内存字数据读取/写入指令

指令语法格式: LDM/STM{类型} Rn{!} , {寄存器列表}
主要包含四种类型的指令:

其他 说明
LDMED LDMIB 预先增加装载
LDMFD LDMIA 过后增加装载
LDMEA LDMDB 预先减少装载
LDMFA LDMDA 过后减少装载
STMFA STMIB 预先增加存储
STMEA STMIA 过后增加存储
STMFD STMDB 预先减少存储
STMED STMDA 过后减少存储
  • FD、ED、FA、和 EA 指定是满栈还是空栈,是升序栈还是降序栈。一个满栈的栈指针指向上次写的最后一个数据单元,而空栈的栈指针指向第一个空闲单元。一个降序栈是在内存中反向增长(就是说,从应用程序空间结束处开始反向增长)而升序栈在内存中正向增长。
  • 其他形式简单的描述指令的行为,意思分别是过后增加(Increment After)、预先增加(Increment Before)、过后减少(Decrement After)、预先减少(Decrement Before)。
  • 寄存器按从最低到最高的编号次序与从低端到高端的内存之间传送数据。
    LDR R0,=0x8000     ;R0=0x8000
    MOV R1,#0x12       ;R1=0x12
    MOV R2,#0x34       ;R2=0x34
    MOV R3,#0x56       ;R3=0x56
 (1)STMIA R0!,{R1-R3}  ;[8000]=0x12,[8004]=0x34,[8008]=0x56,R0=0x8008
    LDMDA R0!,{R4-R6}  ;R4=0x12,R5=0x34,R6=0x56,R0=0x8000
 (2)STMIB R0!,{R1-R3}  ;[8004]=0x12,[8008]=0x34,[800c]=0x56,R0=0x800c
    LDMDB R0!,{R4-R6}  ;R4=[8000]内的数值,R5=0x12,R6=0x34,R0=0x8000
 (3)STMDA R0!,{R1-R3}  ;[7ff8]=0x12,[7ffc]=0x34,[8000]=0x56,R0=0x7ff8
    LDMIA R0!,{R4-R6}  ;R4=0x12,R5=0x34,R6=0x56,R0=0x8000   
 (4)STMDB R0!,{R1-R3}  ;[7ff4]=0x12,[7ff8]=0x34,[7ffc]=0x56,R0=0x7ff4
    LDMIB R0!,{R4-R6}  ;R4=0x34,R5=0x56,R6=[8000]内的数值,R0=0x8000
    
    LDR SP,=0x8000     ;SP=0x8000
    MOV R1,#0x12       ;R1=0x12
    MOV R2,#0x34       ;R2=0x34
    MOV R3,#0x56       ;R3=0x56
 (1)LDMEA SP!,{R1-R3}  ;[7ff4]=0x12,[7ff8]=0x34,[7ffc]=0x56,SP=0x7ff4,对于向下生长栈,第一个有效栈地址为0x8000(栈顶)-4=0x7ffc
    STMEA SP!,{R4-R6}  ;R4=0x12,R5=0x34,R6=0x56,R0=0x7ffc 
 (2)LDMFD SP!,{R1-R3}  ;[8000]=0x12,[8004]=0x34,[8008]=0x56,SP=0x8008,对于向上生长栈,第一个有效栈地址为0x8000
    STMED SP!,{R4-R6}  ;R4=0x12,R5=0x34,R6=0x56,R0=0x8000  

2 跳转指令

2.1 B:跳转指令及BL(带返回的跳转指令)

B指令和BL指令均可以跳转到指令中的目标地址,这两个指令和目标出的指令独属于ARM指令集。不同之处在于B指令仅仅执行跳转操作;BL指令同时还将PC寄存器的值减4保存到LR寄存器中.
ARM汇编器通过以下步骤完成跳转:

  1. 将PC寄存器的值作为本跳转指令的基地址值
  2. 从跳转的目标地址中减去上面所说的跳转的基地址值,生成字节偏移值。由于ARM指令是字节对齐的,该
    字节偏移量为4的倍数
  3. 当上面生成的字节偏移量超过范围33554432~33554430,程序需要作相应的处理
  4. 否则,设置偏移量为上述字节偏移量的bits[25:2]
    B Lable               ; 程序跳转到标号Lable处执行
    BL func               ; 程序跳转到子程序func处执行,同时将当前PC值减4保存到LR中(即下一条指令的地址)

3 数据处理指令

3.1 MOV:传送指令

指令语法格式: MOV Rd, <op>
MOV从另一个寄存器、或被移位的寄存器、或一个立即数装载到目的寄存器。可以指定相同的寄存器来实现NOP指令的效果.

    MOV R0,R0            ; R0=R0...NOP指令效果
    MOV R0,R0,LSL#3      ; R0=R0*8
    MOV R0,#0x100        ; R0=0x100

3.2 MVN:传送指令

指令语法格式: MOV Rd, <op>
MVN 从另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器。不同之处是在传送之前位被反转了,所以把一被取反的值传送到一个寄存器中。这是逻辑非操作而不是算术操作,这个取反的值加 1 才是它的取负的值

    MVN R0,#4            ; R0=-5  0x04取反为0xfb.该0xfb以补码形式存放,原码为:0xfb除符号位全部取反,然后加1,即为0x85,最高位为符号位即-5.
    MVN R0,#0            ; R0=-1  0x00取反为0xff.该0xff以补码形式存放,原码为:0xff除符号位全部取反,然后加1,即为0x81,最高位为符号位即-1.
  • 正数的反码和补码都与原码相同。
  • 负数的反码为对该数的原码除符号位外各位取反。
  • 负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1。

3.3 ADD:加法指令

指令语法格式: ADD Rd, <op1>, <op2>
ADD 将把两个操作数加起来,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值.

    ADD R0,R1,R2         ; R0 = R1 + R2
    ADD R0,R1,#256       ; R0 = R1 + 256
    ADD R0,R2,R3,LSL#1   ; R0 = R2 + (R3 << 1)

3.4 SUB:减法指令

指令语法格式: SUB Rd, <op1>, <op2>
SUB 用操作数 one 减去操作数 two,把结果放置到目的寄存器中。操作数 1 是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即值

    SUB R0,R1,R2         ; R0 = R1 - R2
    SUB R0,R1,#256       ; R0 = R1 - 256
    SUB R0,R2,R3,LSL#1   ; R0 = R2 - (R3 << 1)

3.5 CMP:比较指令

指令语法格式:CMP <Rn> , <Yn>
CMP指令表示寄存器<Rn>中值减去<Yn>寄存器中的值(或一个立即数),根据操作的结果更新CPSR(当前程序状态寄存器)中响应的条件标志位N,Z,C,V标志),后面的指令就可以根据CPSR中相应的条件标志位来判断是否执行。
CMP指令和SUBS指令的区别在于CMP指令不保存操作结果。

标志 说明
N 标 志 本位设置成当前指令运算结果的bit[31]的值,当两个补码表示的有符号整数运算时,N=1表示运算的结果为负数;N=0表示结果为正数。
Z表示 Z=1表示运算的结果为0;Z=0表示运算的结果不为0.对于CMP指令,Z=1表示进行比较的两个数大小相等.
C标志 1. 在加法指令中(包括比较指令CMN),当结果产生了进位,则C=1,表示无符号数运算发生上溢出;其它情况下C=0 ,
2. 在减法指令中(包括比较指令CMP),当运算中发生了借位,则C=0,表示无符号数运算发生下溢出;其它情况下C=1.
3.对于包含移位操作的非加/减法运算指令,C中包含最后一次被溢出的位的数值.
4对于其它非加/减法运算指令,C位的值通常不受影响
V标志 对于加/减法运算指令,当操作数和运算结果为二进制的补码表示的带符号数时,V=1表示符号位溢出.通常其它的指令不影响V位,具体可参考各指令的说明

4 实际反汇编分析

4.1 示例1-纯汇编代码的反汇编分析

/*********************start.S文件汇编代码***********************/

.text
.global _start

_start:

/* 配置GPF4为输出引脚
 * 把0x100写到地址0x56000050
 */
    ldr r1, =0x56000050
    ldr r0, =0x100  /* mov r0, #0x100 */
    str r0, [r1]

/* 设置GPF4输出高电平 
 * 把0写到地址0x56000054
 */
    ldr r1, =0x56000054
    ldr r0, =0  
    str r0, [r1]

    /* 死循环 */
halt:
    b halt

/********************反汇编代码**********************/

    led_on.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:   e59f1014    ldr r1, [pc, #20]    ;     R1=[PC+20]=[8+20]=[0x1c] 读取地址0x1c里面的值然后赋值给R1,即R1=0x56000050.PC值为当前指令地址加8
   4:   e3a00c01    mov r0, #256         ;     R0=0x100
   8:   e5810000    str r0, [r1]         ;     R0的值(0x100)存入R1寄存器中的地址内(0x56000050) 
   c:   e59f100c    ldr r1, [pc, #12]    ;     R1=[PC+12]=[0x0c+8+12]=[0x20] 读取0x20地址里面的值然后赋值给R1,即R1=0x56000054
  10:   e3a00000    mov r0, #0           ;     R0=0x00
  14:   e5810000    str r0, [r1]         ;     R0的值(0x00)存入R1寄存器中的地址内(0x56000054) 

00000018 <halt>:
  18:   eafffffe    b   18 <halt>
  1c:   56000050    undefined
  20:   56000054    undefined

4.1 示例2-包含C程序的反汇编分析

/*******************start.S文件汇编代码*******************/

.text
.global _start

_start:

    /* 设置内存: sp 栈 */
    ldr sp, =4096  /* nand启动 */

    /* 调用main */
    bl main

halt:
    b halt

/*********************led.c文件代码***********************/

int main()
{
    unsigned int *pGPFCON = (unsigned int *)0x56000050;
    unsigned int *pGPFDAT = (unsigned int *)0x56000054;

    /* 配置GPF4为输出引脚 */
    *pGPFCON = 0x100;
    
    /* 设置GPF4输出0 */
    *pGPFDAT = 0;

    return 0;
}

/********************C语言程序反汇编代码******************/

00000000 <_start>:
   0:   e3a0da01    mov sp, #4096   ; 0x1000
   4:   eb000000    bl  c <main>

00000008 <halt>:
   8:   eafffffe    b   8 <halt>

0000000c <main>:
   c:   e1a0c00d    mov ip, sp                       ; ip(R12)=sp=4096
  10:   e92dd800    stmdb   sp!, {fp, ip, lr, pc}    ; 感叹号表示 sp=最终的,被修改的sp值,如果不加感叹号,sp=4096,加了感叹号sp=4096-16=4080,高编号寄存器存放高地址.[4092]=PC的内容,[4088]=lr的内容,[4084]=ip的内容,[4080]=fp的内容
  14:   e24cb004    sub fp, ip, #4                   ; fp(R11)=4096-4=4092
  18:   e24dd008    sub sp, sp, #8                   ; sp=4080-8=4072   
  1c:   e3a03456    mov r3, #1442840576              ; r3=0x56000000
  20:   e2833050    add r3, r3, #80                  ; r3=0x56000000+0x50=0x56000050
  24:   e50b3010    str r3, [fp, #-16]               ; r3(0x56000050)存入[fp-16]的地方即4092-16=4076 即局部变量存放在栈中
  28:   e3a03456    mov r3, #1442840576              ; r3=0x56000000
  2c:   e2833054    add r3, r3, #84                  ; r3=0x56000000+0x54=0x56000054
  30:   e50b3014    str r3, [fp, #-20]               ; r3(0x56000054)存入[fp-20]的地方即4092-20=4072 即局部变量存放在栈中
  34:   e51b2010    ldr r2, [fp, #-16]               ; 读取[fp-16]=[4076]地址上的内容(0x56000050)存入R2中,
  38:   e3a03c01    mov r3, #256                     ; r3=0x100
  3c:   e5823000    str r3, [r2]                     ; 把R3里面的内容(0x100)存入r2中的地址内(0x56000050)
  40:   e51b2014    ldr r2, [fp, #-20]               ; 读取[fp-20]=[4072]地址上的内容(0x56000054)存入R2中,
  44:   e3a03000    mov r3, #0                       ; r3=0x00
  48:   e5823000    str r3, [r2]                     ; 把R3里面的内容(0x00)存入r2中的地址内(0x56000054)
  4c:   e3a03000    mov r3, #0                       ; r3=0x00   
  50:   e1a00003    mov r0, r3                       ; r0=0x00,main函数返回值赋值给r0
  54:   e24bd00c    sub sp, fp, #12                  ; sp=fp-12=4092-12=4080 恢复栈
  58:   e89da800    ldmia   sp, {fp, sp, pc}         ; [4080]内容赋值给fp,[4084]内容赋值给sp,[4088]内容赋值给pc
Disassembly of section .comment:

00000000 <.comment>:
   0:   43434700    cmpmi   r3, #0  ; 0x0
   4:   4728203a    undefined
   8:   2029554e    eorcs   r5, r9, lr, asr #10
   c:   2e342e33    mrccs   14, 1, r2, cr4, cr3, {1}
  10:   Address 0x10 is out of bounds.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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