我可以使用ARM的LDR指令访问什么地址
What address I could access with LDR instruction of ARM
我对 ARM 汇编代码完全陌生。
我刚刚查看了指令集,发现有一条指令LDR可以用作"LDR{}{} Rd, "。
关于这条指令我有两个问题:
1)这里的地址是物理地址还是虚拟地址?
2) 我怎么知道哪个地址是 "legal" 或 "readable" 供我加载?我不知道我可以访问哪个地址。
我只是想测试这条指令,所以任何有效的地址都会对我有所帮助。
非常感谢。
除非您正在编写内核/引导加载程序代码,否则所有地址都是始终虚拟的。即使您愿意,也不能使用物理地址。 (假设您正在编写用户 space 代码,它将 运行 在像 Linux 这样的全面 OS 下。更一般地说,您要么总是有虚拟地址,要么总是有物理地址。你不能编写使用一些物理和一些虚拟内存访问的代码。如果你想对某个物理地址做一些事情,你必须将它映射到你的虚拟地址space。)
当 OS 启动您的进程时,堆栈指针通常指向有效内存。您放入 data 或 bss 段的任何内容也应该是可读的。
除此之外的任何内容都超出了单个答案的范围。 Google 上传介绍教程。
但是,由于您具体提到了 ldr
,而且它不仅仅是一条简单的指令(将编译时间常量放入寄存器的加载指令或伪指令):参见 Why use LDR over MOV (or vice versa) in ARM assembly?
我不太了解 ARM asm,我没有意识到答案将是特定于架构的。 1. 和 2. 适用于所有 CPU 上的用户 space 代码(在具有受保护内存的正常 OSes 上)。
这取决于您的程序运行在何种 ARM 架构上。如果它是像 Cortex-M0(它是 ARMv6-M)这样的小型微控制器,您可以使用物理地址。在特定处理器的参考手册中,您可以检查哪些地址有效(例如,RAM 的地址范围是什么)。您还需要记住,通常地址必须与字长对齐(同样,这取决于特定版本的体系结构)。
如果您使用 "big" ARM 处理器,例如 Cortex-A (ARMv7-A) 或 64 位 ARM (ARMv8-A),您也(很可能)使用某种高级操作系统系统(例如Linux)和处理器本身都有一个MMU。在那种情况下,您传递虚拟地址。如果您将 32 位 Linux 与标准 3:1 split 一起使用,则用户空间程序可以访问 0xC0000000 以下(已对齐)的所有地址。顺便说一句,您可以使用其他指令(如 LDRB、LDRH)访问未对齐的地址。
如果您正在研究 Linux,my article 可能会对您有所帮助。这篇文章目前比较乱,但至少里面有一组很好的外部链接到其他文章。
ARMv7-A -R Architecture Reference Manual
明确表示
An address used in an instruction, as a data or instruction address, is a Virtual Address (VA).
An address held in the PC, LR, or SP, is a VA.
The VA map runs from zero to the size of the VA space. For ARMv7, the maximum VA space is 4GB, giving a maximum VA range of 0x00000000 - 0xFFFFFFFF.
另外很明显,这个 VA 被转换为物理地址,而物理地址又用于对物理内存执行所需的操作。
进一步描述了禁用内存管理单元(进行实际内存映射)的影响,但这并不能否定地址是虚拟地址的事实。
总而言之,在最近的 ARM 架构中,您确实使用虚拟地址进行操作,除非您正在编写内核,内核必须处理设置分页和地址转换。如果您 运行 在某些操作系统下运行您的代码,那么您就完全安全了。
这就引出了你第二个问题的答案。由于受到 OS 的保护,您可以自由尝试访问任何您想要的地址,但访问随机地址在最坏的情况下会导致 OS 终止您的特定应用程序。要确定您可以访问哪些地址,您可以尝试 运行 您的程序在 gdb
下,并使用 info proc mappings
gdb
命令列出所有映射的内存。
我对 ARM 汇编代码完全陌生。
我刚刚查看了指令集,发现有一条指令LDR可以用作"LDR{}{} Rd, "。
关于这条指令我有两个问题: 1)这里的地址是物理地址还是虚拟地址? 2) 我怎么知道哪个地址是 "legal" 或 "readable" 供我加载?我不知道我可以访问哪个地址。
我只是想测试这条指令,所以任何有效的地址都会对我有所帮助。
非常感谢。
除非您正在编写内核/引导加载程序代码,否则所有地址都是始终虚拟的。即使您愿意,也不能使用物理地址。 (假设您正在编写用户 space 代码,它将 运行 在像 Linux 这样的全面 OS 下。更一般地说,您要么总是有虚拟地址,要么总是有物理地址。你不能编写使用一些物理和一些虚拟内存访问的代码。如果你想对某个物理地址做一些事情,你必须将它映射到你的虚拟地址space。)
当 OS 启动您的进程时,堆栈指针通常指向有效内存。您放入 data 或 bss 段的任何内容也应该是可读的。
除此之外的任何内容都超出了单个答案的范围。 Google 上传介绍教程。
但是,由于您具体提到了 ldr
,而且它不仅仅是一条简单的指令(将编译时间常量放入寄存器的加载指令或伪指令):参见 Why use LDR over MOV (or vice versa) in ARM assembly?
我不太了解 ARM asm,我没有意识到答案将是特定于架构的。 1. 和 2. 适用于所有 CPU 上的用户 space 代码(在具有受保护内存的正常 OSes 上)。
这取决于您的程序运行在何种 ARM 架构上。如果它是像 Cortex-M0(它是 ARMv6-M)这样的小型微控制器,您可以使用物理地址。在特定处理器的参考手册中,您可以检查哪些地址有效(例如,RAM 的地址范围是什么)。您还需要记住,通常地址必须与字长对齐(同样,这取决于特定版本的体系结构)。
如果您使用 "big" ARM 处理器,例如 Cortex-A (ARMv7-A) 或 64 位 ARM (ARMv8-A),您也(很可能)使用某种高级操作系统系统(例如Linux)和处理器本身都有一个MMU。在那种情况下,您传递虚拟地址。如果您将 32 位 Linux 与标准 3:1 split 一起使用,则用户空间程序可以访问 0xC0000000 以下(已对齐)的所有地址。顺便说一句,您可以使用其他指令(如 LDRB、LDRH)访问未对齐的地址。
如果您正在研究 Linux,my article 可能会对您有所帮助。这篇文章目前比较乱,但至少里面有一组很好的外部链接到其他文章。
ARMv7-A -R Architecture Reference Manual
明确表示
An address used in an instruction, as a data or instruction address, is a Virtual Address (VA).
An address held in the PC, LR, or SP, is a VA.
The VA map runs from zero to the size of the VA space. For ARMv7, the maximum VA space is 4GB, giving a maximum VA range of 0x00000000 - 0xFFFFFFFF.
另外很明显,这个 VA 被转换为物理地址,而物理地址又用于对物理内存执行所需的操作。 进一步描述了禁用内存管理单元(进行实际内存映射)的影响,但这并不能否定地址是虚拟地址的事实。
总而言之,在最近的 ARM 架构中,您确实使用虚拟地址进行操作,除非您正在编写内核,内核必须处理设置分页和地址转换。如果您 运行 在某些操作系统下运行您的代码,那么您就完全安全了。
这就引出了你第二个问题的答案。由于受到 OS 的保护,您可以自由尝试访问任何您想要的地址,但访问随机地址在最坏的情况下会导致 OS 终止您的特定应用程序。要确定您可以访问哪些地址,您可以尝试 运行 您的程序在 gdb
下,并使用 info proc mappings
gdb
命令列出所有映射的内存。