ARM64汇编07 - 访存指令

2024-03-21 15:12
文章标签 指令 汇编 07 arm64 访存

本文主要是介绍ARM64汇编07 - 访存指令,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

访存指令是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.h>uint64_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,#-0x10+var_s0]!
.text:00000000000006F8 FD 03 00 91                         MOV             X29, SP
.text:00000000000006FC 08 00 00 B0                         ADRP            X8, #x_ptr@PAGE
.text:0000000000000700 08 F1 47 F9                         LDR             X8, [X8,#x_ptr@PAGEOFF]
.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, [SP+var_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_ptr@PAGE

就是先将 PC 的地址做个页对齐,再加上某个偏移量。但是这里 IDA 已经帮我们计算好了,最终的值就是 #x_ptr@PAGE,所以该指令的意思就是将这个值赋值给 X8 寄存器。

x_ptr 是一个地址,从名字也可以看出,它是 x 变量的一个指针,指向的地址储存了 x 的值。

下一条指令LDR X8, [X8,#x_ptr@PAGEOFF]

X8 + x_ptr@PAGEOFF 的值处的地址储存的值赋值给 X8,从上一条指令我们知道,X8 的值是 x_ptr@PAGE,所以最终X8的值是 x_ptr@PAGE + x_ptr@PAGEOFF 处储存的值。

那么x_ptr@PAGE 与 x_ptr@PAGEOFF 这两个玩意到底是啥呢?

我们在这个符号的位置,按下 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_56CBF42FE0@PAGE
globalvar:00000056CBF41754 LDR             X8, [X8,#off_56CBF42FE0@PAGEOFF]

要能想到这是访问全局变量。

got 储存了全局变量的地址,程序加载时对这个地址进行重定位,运行时给这个地址填入全局变量的值。

二手的程序员

红日初升,其道大光。河出伏流,一泻汪洋。潜龙腾渊,鳞爪飞扬。乳虎啸谷,百兽震惶。鹰隼试翼,风尘翕张。奇花初胎,矞矞皇皇。干将发硎,有作其芒。天戴其苍,地履其黄。纵有千古,横有八荒。前途似海,来日方长。

公众号

这篇关于ARM64汇编07 - 访存指令的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/833002

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

工作常用指令与快捷键

Git提交代码 git fetch  git add .  git commit -m “desc”  git pull  git push Git查看当前分支 git symbolic-ref --short -q HEAD Git创建新的分支并切换 git checkout -b XXXXXXXXXXXXXX git push origin XXXXXXXXXXXXXX

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

Android中如何实现adb向应用发送特定指令并接收返回

1 ADB发送命令给应用 1.1 发送自定义广播给系统或应用 adb shell am broadcast 是 Android Debug Bridge (ADB) 中用于向 Android 系统发送广播的命令。通过这个命令,开发者可以发送自定义广播给系统或应用,触发应用中的广播接收器(BroadcastReceiver)。广播机制是 Android 的一种组件通信方式,应用可以监听广播来执行

mysql中导入txt文件数据的操作指令

1 表tt的格式:    CREATE TABLE `tt` (   `ind` int NOT NULL auto_increment,   `name` char(100) default NULL,   PRIMARY KEY  (`ind`)  )   2 文件d.txt的内容示例:  1,a  2,b  3,c

07 v-if和v-show使用和区别

划重点: v-ifv-show 小葱拌豆腐 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="

可选择的反思指令微调

论文:https://arxiv.org/pdf/2402.10110代码:GitHub - tianyi-lab/Reflection_Tuning: [ACL'24] Selective Reflection-Tuning: Student-Selected Data Recycling for LLM Instruction-Tuning机构:马里兰大学, Adobe Research领

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

汇编:嵌入式软件架构学习资源

成为嵌入式软件架构设计师需要掌握多方面的知识,包括嵌入式系统、实时操作系统、硬件接口、软件设计模式等。 以下是一些推荐的博客和网站,可以帮助你深入学习嵌入式软件架构设计: ### 1. **Embedded.com**    - **网址**: [Embedded.com](https://www.embedded.com/)    - **简介**: 这是一个专注于嵌入式系统设计的专业网

4G模块、WIFI模块、NBIOT模块通过AT指令连接华为云物联网服务器(MQTT协议)

MQTT协议概述 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,它被设计用来提供一对多的消息分发和应用之间的通讯,尤其适用于远程位置的设备和高延迟或低带宽的网络。MQTT协议基于客户端-服务器架构,客户端可以订阅任意数量的主题,并可以发布消息到这些主题。服务器(通常称为MQTT Broker)则负责接受来自客户端的连接请求,并转发消