我对ARM汇编代码完全不熟悉。
我刚检查了指令集,发现有一条指令LDR,可以用作“LDR {} {} Rd,”。
我对此说明有两个问题: 1)这里的地址是物理地址还是虚拟地址? 2)我怎么知道加载哪个地址“合法”或“可读”?我不知道我可以访问哪个地址。
我只是想测试这条指令,所以任何有效的地址对我都有帮助。
非常感谢。
答案 0 :(得分:2)
这取决于程序运行的ARM架构究竟是什么。如果它是像Cortex-M0这样的小型微控制器(ARMv6-M),则使用物理地址。在特定处理器的参考手册中,您可以检查哪些地址有效(例如,RAM的地址范围是什么)。您还需要记住,通常地址必须与字大小对齐(同样,它取决于架构的特定版本)。
如果您使用“大”ARM处理器,如Cortex-A(ARMv7-A)或64位ARM(ARMv8-A)之一,您还可以使用(最可能)某种高级操作系统(例如) Linux)和处理器本身都有一个MMU。在这种情况下,您传递虚拟地址。如果您使用标准3:1 split的32位Linux,则所有低于0xC0000000的地址(已对齐)都可供用户空间程序访问。顺便说一句,您可以使用其他指令(如LDRB,LDRH)访问未对齐的地址。
如果您正在使用Linux,my article可能会有所帮助。这篇文章目前非常混乱,但至少在内部有一组非常好的外部链接到其他文章。
答案 1 :(得分:1)
ARMv7-A -R Architecture Reference Manual
明确指出
指令中使用的地址,作为数据或指令地址,是虚拟地址(VA)。
PC,LR或SP中保存的地址是VA。
VA地图从零到VA空间的大小。对于ARMv7,最大VA空间为4GB,最大VA范围为0x00000000 - 0xFFFFFFFF。
同样很清楚,该VA被转换为物理地址,而物理地址又用于利用物理存储器执行所需的操作。 进一步说明了禁用内存管理单元(实际内存映射)的影响,但这并没有否定地址是虚拟地址这一事实。
使用最新的ARM体系结构,除非您正在编写内核(必须处理设置分页和地址转换),否则您将使用虚拟地址进行操作。如果您在某些操作系统下运行代码,那么您将非常安全。
这导致您回答第二个问题。当您通过操作系统保护时,您可以自由尝试访问您希望的任何地址,但在最坏情况下访问随机地址将导致操作系统终止您的特定应用程序。要确定您可以访问哪些地址,可以尝试在gdb
下运行您的程序,并使用info proc mappings
gdb
命令列出所有映射的内存。
答案 2 :(得分:0)
除非您正在编写内核/引导加载程序代码,否则所有地址始终虚拟。即使您愿意,也无法使用物理地址。 (假设您正在编写将在Linux等全面操作系统下运行的用户空间代码。更一般地说,要么总是拥有虚拟地址,要么总是拥有物理地址。您无法编写使用的代码一些物理和一些虚拟内存访问。如果你想对某个物理地址做某事,你必须将它映射到你的虚拟地址空间。)
当操作系统启动进程时,堆栈指针通常指向有效内存。您放入数据或bss段的任何内容也应该是可读的。
除此之外的任何内容超出了单一答案的范围。谷歌上了一个介绍教程。
但是,由于您具体提到{{1}},并且它不仅仅是一个简单的指令(将编译时常量放入寄存器的加载或伪指令):请参阅{ {3}}
我不太了解ARM asm,我没有意识到答案是针对特定于拱形的。 1.和2.适用于所有CPU上的用户空间代码(在具有受保护内存的普通操作系统上)。