最近在分析代码时,感觉对堆栈和多数据寻址有一些感悟,故总结一下,做个记录。
⊙一.什么是多寄存器寻址和堆栈寻址
⊙二.多寄存寻址和堆栈寻址各有几种形态
⊙三.多寄存寻址和堆栈寻址过程中发生了什么
⊙四.多寄存寻址和堆栈寻址的异同点
一.什么是多寄存器寻址和堆栈寻址
多寄存器寻址是指一条指令可以对对各寄存器值的传送,这种寻址方式中用一条指令最多可传送16个通用寄存器的值,连续的寄存器用"-"来连接,否则用","分隔离。
LDMIA RO! ,{R1 -R4}
堆栈是一种数据结构,堆栈寻址意味着进行出栈入栈的操作。
STMFD R13!,{R0-R4};
LDMFD R13!,{RO-R4};
二.多寄存寻址和堆栈寻址各有几种形态
1 .多寄存器寻址:
从存值和取值:
①从内存中取出数据对寄存器赋值(load much)
②把多寄存器的数据放入到内存中(store much)
从堆栈指针增加和减少:
①进行一个操作后可以增加堆栈指针的值(increase)
②进行一个操作后可以减少堆栈指针的值(decrease)
从先后顺序上:
①可以在操作(取值或存值)前(before)进行堆栈指针的(增加或减少)
②可以在操作(取值或存值)后(after)进行堆栈指针的(增加或减少)
多寄存器寻址的排列组合数为:2*2*2 = 8种
STMDA |
从寄存器取值到内存后目标指针再减 | LDMDA |
从内存取值到寄存器后目标指针减 |
STMIA |
从寄存器取值到内存后目标指针再增 | LDMIA |
从内存取值到寄存器后目标指针增 |
STMDB |
从寄存器取值到内存前目标指针减 | LDMDB |
从内存取值到寄存器前目标指针减 |
STMIB |
从寄存器取值到内存前目标指针增 | LDMIB |
从内存取值到寄存器前目标指针增 |
2.堆栈寻址:
从入栈和出栈:
①从寄存器中把数据放入堆栈为入栈(store much)
②把堆栈中的值放入到寄存器中为出栈(load much)
从堆栈的状态:
①满(full)堆栈:当前栈顶指针指向的堆栈内存是有值的。
②空(empty)堆栈:当前栈顶指针指向的堆栈内存是无值的。
从出栈或入栈方向上:
①(出栈或入栈)的栈顶指针向上增加
②(出栈或入栈)的栈顶指针向下减少
堆栈寻址的排列组合数为: 2*2*2 =8
STMED |
从寄存器取值到堆栈后目标指针减 | LDMFA |
从堆栈取值到寄存器后堆栈指针减 |
STMEA |
从寄存器取值到堆栈后堆栈指针增 | LDMFD |
从堆栈取值到寄存器后堆栈指针增 |
STMFD |
从寄存器取值到堆栈前堆栈指针减 | LDMEA |
从堆栈取值到寄存器前堆栈指针减 |
STMFA |
从寄存器取值到堆栈前堆栈指针增 | LDMED |
从堆栈取值到寄存器前堆栈指针增 |
三.多寄存寻址和堆栈寻址过程中发生了什么
多寄存器寻址:
STMDA R0!,{R1-R2};
[RO]=R2
R0=RO-4
[RO]=R1
R0=RO-4]
LDMIB RO!,{R1-R2};
RO=RO+4
R1 =[R0]
RO=RO+4
R2=[RO]
堆栈寻址:
STMED sp!,{R1-R2};
[SP] = R2
SP = SP-4
[SP] = R1
SP=SP-4
LDMED sp!,{R1-R2};
SP = SP+4
R1 = [SP]
SP=SP+4
R2 = [SP]
有没有发现多寄存寻址的STMDA和LDMIB 都是根据最后两个字母进行变换的,但是堆栈寻址的LDMED,最后两个字母明明是ED为什么是加呢?
这里回答下因为多寄存器寻址和堆栈寻址指令意义明显表示的不同,在出栈入栈中st代表的就是入栈了,而ld代表的是出栈了,在这个情况下,自然以入栈的最后两个字母为主,而加上ld后后面的字母就被反转回来,就很有意思。
可能看完这篇文章还有人问,你怎么知道上方的STMED sp!,{R1-R2}时从先把R2放到内存中,然后把R1放到内存中呢?为什么不是先把R1放到内存中,然后把R2放到内存中呢(堆栈寻址中同理)?
目前arm中是这样的如果在目标指针是减的情况下,就会从右到左进行处理,如果目标指针是增加的情况下,那么就是从左到右处理!
四.多寄存寻址和堆栈寻址的异同点
相同点:
①都是操作内存和寄存器之间进行读写.
②进行操作的时候都会进行目标指针的移动,只不过数据块传送为目标指针,而堆栈是堆栈指针。
不同点:
①表示的具体意义不同
那么有一个问题,多寄存器寻址能够替代堆栈寻址吗?
在 "三.多寄存寻址和堆栈寻址过程中发生了什么"中我们看到了这两组不同的寻址方式,但是你会发现他们对于数据的处理操作是相同的,于是我做了个实验,写了
STMDA R13!,{R1-R2};
并编译为二进制文件,然后用ida打开反编译下,你会发现ida竟然将其翻译为
STMED sp!,{R1-R2};
这也太神奇了!
于是我就试了其他的指令发现,堆栈寻址和多寄存寻址确实存在一一对应的关系,也就是说可以被转换替代,具体对应关系如下
STMDA | STMED |
STMIA | STMEA |
STMDB | STMFD |
STMIB | STMFA |
LDMDA | LDMFA |
LDMIA | LDMFD |
LDMDB | LDMEA |
LDMIB | LDMED |
我是BestToYou,分享工作或日常学习中关于二进制逆向和分析的一些思路和一些自己闲暇时刻调试的一些程序,文中若有错误的地方,恳请大家联系我批评指正。
原文始发于微信公众号(二进制科学):arm中的多寄存器寻址和与堆栈寻址
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论