ARM汇编之内存处理一网打尽

RISC架构可以认为是加载/存储的架构,因为所有存储在外部数据都需要通过指令加载到处理器进行处理。

加载/存储的指令很多,常用的如下:

加载 存储 长度和类型
LDR STR 32位的字(默认)
LDRB STRB 8位的无符号字节
LDRH STRH 16位无符号的半字
LDRSB 8位的有符号字节
LDRSH 16位的有符号半字
LDM STM 多个字的处理

  • 加载/存储的单指令处理的格式如下:
    LDR|STR{<size>}{<cond>} <Rd>, <addressing_mode>
    LDR表示从内存中加载数据并写到通用寄存器,STR表示从通用寄存器读取数据并把它存储到内存中。其中size是可选的如上表中的B/SB/H/SH等,addressing_mode表示寻址模式就是前面的文章《ARM汇编之内存寻址模式》介绍的,总共3种。
    下面这种格式不加!是偏移寻址模式,加!是前变址寻址模式
    LDR|STR{<size>}{<cond>} <Rd>, [<Rn>, <offset>]{!}
    下面这种格式是后变址寻址模式
    LDR|STR{<size>}{<cond>} <Rd>, [<Rn>], <offset>
    例子:
AREA load_store, CODE, READONLY

ARM

ENTRY

start

MOV R1,#0x40000000
MOV R2,#2

LDR R3,[R1,R2,LSL #2];偏移寻址模式
;LDR R3,[R1,R2,LSL#2]!;前变址寻址模式
;LDR R3,[R1],R2,LSL#2;后变址寻址模式

STR R2,[R1]
STR R2,[R1,#4]!
MOV R2,#0XFF
STR R2,[R1],#8

stop

MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)

END
  • 加载/存储多个寄存器的指令

LDM的语法格式如下:
LDM{addr_mode}{cond} Rn{!}, reglist{^}
其中<addr_mode>告诉汇编指令寻址的模式有下面四种:
IA,在每次传输完之后递增地址(默认模式,可省略) 。
IB,在每次传输完之前递增地址 (仅A32支持)。
DA,在每次传输完之后递减地址 (仅A32支持)。
DB,在每次传输完之前递减地址。

cond是可选的,表示条件码。
Rn是基址寄存器。
感叹号!是可选的,如果有表示最后的地址要写回Rn寄存器。
reglist是用来加载数据的寄存器列表(包含一个或多个寄存器,多个的话可用逗号进行分隔,如果是多个连续的寄存器也可用一个范围表示,比如R0-R4),reglist需要用花括号括起来,对A32来说寄存器从R0到R15都可用,但T32只有部分寄存器可用。
reglist之后的^是可选的,仅A32支持,他不能用在用户模式或者系统模式( User mode/System mode),他是为如下场景设计的:

  • 当reglist中包含PC寄存器时,不仅将数据加载到寄存器列表中指定的寄存器,同时也顺便把SPSR复制到CPSR,这发生在异常模式下中断处理程序还回时。
  • 否则数据将被传输进/出用户模式的寄存器,而不是当前模式的寄存器

备注:因为有多个寄存器,那么怎么考虑寄存器列表里面的寄存器和内存之间的映射,拿存储来说,是最低序号的寄存器存储到最低内存地址中,最高序号的寄存器存储到最高的内存地址中,加载也是按这种方式进行映射的,这个是跟寄存器列表中寄存器的存放顺序没有关系的。

STM的语法格式如下:
STM{addr_mode}{cond} Rn{!}, reglist{^}

STM和LDM所带选项基本一样,释义也基本一样,对LDM来说Rn存储的是内存中的基地址,只是STM要从该地址往内存中写数据,而LDM是从该地址从内存中读数据。reglist之后的^对STM来说,同样也不能在用户模式或者系统模式,只是出现该符号时数据将被传输进/出用户模式的寄存器,而不是当前模式的寄存器。

例子1:

AREA load_store, CODE, READONLY
ARM

ENTRY

start

MOV R9,#0x40000000
ADD R10,R9,#32
LDMIA R9, {R5, R0, R3};低地址的数据先加载到r0,在加载到r3,最后加载到r5,
                      ;加载顺序跟放置在列表中的位置无关,只跟寄存器的编号有关
LDMDB R10!,{R0-R1};最终地址会被写回R10

stop

MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)

END

例子2:

AREA load_store, CODE, READONLY

ARM

ENTRY

start

MOV R9,#0x40000000
ADD R10,R9,#32
MOV R2,#2
MOV R1,#1
STMIA R9,{R2,R1};注意最低地址存储R1,在接着存储R2,存储顺序跟放置在列表中的位置无关

STMIB R9,{R1,R2}
STMDA R10,{R2,R1}
STMDB R10!,{R1,R2}

stop

MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)

END
  • PUSH和POP

主要是针对栈的操作,PUSH其实就是 STMDB sp!,POP其实就是 LDMIA sp!
语法格式如下:
PUSH{<cond>} <reglist>
POP{<cond>} <reglist>
其中reglist可以参照前面的LDM/STMD的说明

例子:

AREA push_pop, CODE, READONLY

ARM

ENTRY

start

mov sp,#0x40000010
push {r1,r0}
pop {r3,r4}

stop

MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)

END
  • 使用 LDM和STM来实现栈

使用栈时需要注意两点:

  • 栈的增长方向,向上增长(ascending)或者向下增长(Descending)
  • 栈指针的位置,指向空的位置(empty,栈中下一个空的位置),或者满的位置(Full,最后一个栈成员的位置)

因此就可以组合出四种栈:
FD(Full Descending stack)
FA(Full Ascending stack)
ED(Empty Descending stack)
EA(Empty Ascending stack)
当然这四种操作和LDM/STM中的addr_mode是等价的可以互相替换的,编程时如果你觉得基于这种栈方式的操作更容易理解,可以用这种助记符来进行编写程序,汇编器会自动帮你把这些转换为基于addr_mode的合适指令。
下面是一张等价图

image.png

如果你是基于FD的栈来进行开发,如果没用FD助记符,那么入栈是你需要使用STMDB,而出栈是需要使用LDMIA,如果使用FD的话入栈STMFD,出栈LDMFD就行了剩下的交个汇编器去解释,这种就很容易记忆了。下面是四种栈入栈/出栈的指令及等效的addr_mode模式下的原始指令


image.png

例子:

AREA push_pop, CODE, READONLY

ARM

ENTRY

start

mov sp,#0x40000010
stmfd sp!,{r0,r1};入栈
ldmfd sp!,{r2,r3};出栈

stop

MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)

END

参考文献

【1】DUI0801I_armasm_user_guide

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

推荐阅读更多精彩内容