苏州网站建设企业,跨专业的简历怎么制作,怎么在百度建立自己的网站,梓潼县住房和城乡建设局网站访存指令是ARM64汇编语言中的一部分#xff0c;涵盖了数据访问和内存操作的指令。这些指令使处理器能够与内存进行交互#xff0c;包括读取数据、写入数据以及执行其他内存相关的操作。理解这些指令对于理解处理器如何与内存交互以及如何管理数据至关重要。 访存指令介绍两个… 访存指令是ARM64汇编语言中的一部分涵盖了数据访问和内存操作的指令。这些指令使处理器能够与内存进行交互包括读取数据、写入数据以及执行其他内存相关的操作。理解这些指令对于理解处理器如何与内存交互以及如何管理数据至关重要。 访存指令介绍两个 ldr str
LDR
ldr 指令的意思是 Load Register将寄存器里面的值当成地址访问该内存地址储存的值将这个值拿出来放到另一个寄存器。比如
LDR X8, [X21][X21] 类似数组写法将内存看作数组就是将 Mem[X21] 的值给 X8。
查看手册LDR 有3种形式 LDR (immediate) LDR (literal) LDR (register)
其实差别不大在 IDA 中没啥区别只需要了解它是在读取内存即可。
拿 LDR (immediate) 的格式来说 imm9 是描述的偏移范围是 -256 到 255刚好占据9位有一位是符号位。
第 10 与 11 bit位是表示的是内偏移还是外偏移。
STR
STR 与 LDR 对应表示的意思是Store Register
STR X10, [SP]将X10的值存到 SP 指向的内存地址上。
STR 有2种形式 STR (immediate) STR (register)
后续行为
访存指令还会有一些后续行为就是类似于i 与i 。
内偏移写法比如
E1 17 40 F9 LDR X1, [SP,#0x28]这里计算地址要将 SP 的值加上 0x28当成内存地址然后获取地址上的值赋值给 X1。
还有一种带感叹号的形式
20 4C 40 F8 LDR X0, [X1,#4]!感叹号的作用就是说当指令执行完后X1 的值也需要加上 4。
还有一种外偏移的形式
20 44 40 F8 LDR X0, [X1],#4这种写法也是当指令执行完后X1 的值也需要加上 4。不过在访存的时候不会先加4注意与带感叹号写法的区别。
内偏移与外偏移不会同时存在就算想做也不行因为指令位不够。
其他访存指令
与 LDR 相似的还有 LDUR 等指令也是访问内存可以理解为 LDR 的特殊情况。
LDR指令将数据从内存中取出来存放到寄存器中。
LDUR指令将内存中负数的数据取出来并存放到寄存器中。
LDP指令表示出栈指令
STR指令将数据从寄存器中读出来存储到内存中。
STUR指令将寄存器中的负数数据读取出来存放到内存中。
STP指令表示入栈指令。
比如在 IDA 中 patch ldr 指令的时候就有可能会生成 ldur 指令。查看手册发现这两者的指令格式非常相似只有一个 bit 位的区别。
理解全局变量
看一个例子
#include stdio.h
#include stdlib.h
#include stdint.huint64_t x;int main()
{x 0x123456789a;getchar();return 0;
}查看汇编代码
.text:00000000000006F4 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00000000000006F4 EXPORT main
.text:00000000000006F4 main ; DATA XREF: LOAD:0000000000000438↑o
.text:00000000000006F4 ; .got:main_ptr↓o
.text:00000000000006F4
.text:00000000000006F4 var_s0 0
.text:00000000000006F4
.text:00000000000006F4 ; __unwind {
.text:00000000000006F4 FD 7B BF A9 STP X29, X30, [SP,#-0x10var_s0]!
.text:00000000000006F8 FD 03 00 91 MOV X29, SP
.text:00000000000006FC 08 00 00 B0 ADRP X8, #x_ptrPAGE
.text:0000000000000700 08 F1 47 F9 LDR X8, [X8,#x_ptrPAGEOFF]
.text:0000000000000704 49 13 8F D2 C9 8A A6 F2 49 02 C0 F2 MOV X9, #0x123456789A
.text:0000000000000710 09 01 00 F9 STR X9, [X8]
.text:0000000000000714 C7 FF FF 97 BL .getchar
.text:0000000000000714
.text:0000000000000718 E0 03 1F 2A MOV W0, WZR
.text:000000000000071C FD 7B C1 A8 LDP X29, X30, [SPvar_s0],#0x10
.text:0000000000000720 C0 03 5F D6 RET
.text:0000000000000720 ; } // starts at 6F4
.text:0000000000000720
.text:0000000000000720 ; End of function main
.text:0000000000000720
.text:0000000000000720 ; .text ends
.text:0000000000000720从 00000000000006FC 地址开始分析ADRP X8, #x_ptrPAGE
就是先将 PC 的地址做个页对齐再加上某个偏移量。但是这里 IDA 已经帮我们计算好了最终的值就是 #x_ptrPAGE所以该指令的意思就是将这个值赋值给 X8 寄存器。
x_ptr 是一个地址从名字也可以看出它是 x 变量的一个指针指向的地址储存了 x 的值。
下一条指令LDR X8, [X8,#x_ptrPAGEOFF]
将X8 x_ptrPAGEOFF 的值处的地址储存的值赋值给 X8从上一条指令我们知道X8 的值是 x_ptrPAGE所以最终X8的值是 x_ptrPAGE x_ptrPAGEOFF 处储存的值。
那么x_ptrPAGE 与 x_ptrPAGEOFF 这两个玩意到底是啥呢
我们在这个符号的位置按下 Q 快捷键就能知道它真实的数字了
.text:00000000000006FC 08 00 00 B0 ADRP X8, #0x1000
.text:0000000000000700 08 F1 47 F9 LDR X8, [X8,#0xFE0]所以最后的结果是将 0x1FE0 处储存的值放到了 X8 寄存器中。
我们去看 0x1FE0 处的内容
.got:0000000000001FE0 08 20 00 00 00 00 00 00 x_ptr DCQ x所以就是将 0x0000000000002008 放入 X8 寄存器中。
看下一个指令MOV X9, #0x123456789A
将0x123456789A的值放入 X9 寄存器。
看下一个指令STR X9, [X8]
将 X9 寄存器的值放入内存中就是将 0x123456789A 的值放入 0x0000000000002008 这个地址。
但是需要注意最终的地址肯定是需要 rebase 的因为 adrp 指令计算了 pc 的值静态分析时我们的 pc 值相当于 0动态调试的时程序的一些地方需要重定位肯定会改变一些值。
现在可以考虑一下
.got:0000000000001FE0 08 20 00 00 00 00 00 00 x_ptr DCQ x当程序运行时这里储存的地址会不会变化
我们调试看一下 当这两条指令执行完之后X8 寄存器的值为 0x00000056CBF43008。
与静态分析时的地址相比较 0x0000000000002008 是页对齐的。
此时0x00000056CBF43008 储存的内容为 赋值完成后查看 后面看到类似这种指令
globalvar:00000056CBF41750 ADRP X8, #off_56CBF42FE0PAGE
globalvar:00000056CBF41754 LDR X8, [X8,#off_56CBF42FE0PAGEOFF]要能想到这是访问全局变量。
got 储存了全局变量的地址程序加载时对这个地址进行重定位运行时给这个地址填入全局变量的值。 二手的程序员
红日初升其道大光。河出伏流一泻汪洋。潜龙腾渊鳞爪飞扬。乳虎啸谷百兽震惶。鹰隼试翼风尘翕张。奇花初胎矞矞皇皇。干将发硎有作其芒。天戴其苍地履其黄。纵有千古横有八荒。前途似海来日方长。
公众号