LDR中源寄存器和目的寄存器相同时的含义是什么?

3
在ARM汇编中执行ldr r0,[r0]是否合法?

3
为什么你不想尝试一下并找出答案呢? - shift66
早期的 ARM 核心可能存在问题,但从 ARM7(ARMv4)开始,我在许多不同的核心上使用了该指令,并没有出现问题,无论是 ARM 模式还是 Thumb 模式...如何发现这些问题,可以查看特定核心的技术参考手册,它会指定这样的限制。此外,ARM ARM,ARM 架构参考手册,对于该系列(ARMv7、ARMv6 等)也可能会告诉你。 - old_timer
@Ademiban 我确实尝试过,它确实有效。但是我想要确定,因为并不是所有表面上有效的东西都是被定义的。例如,读写缓冲区末尾之后的内容可能有效,但这并不意味着它是被定义的。 - tangrs
3个回答

5

如果有疑问,始终参考ARM架构参考手册,可以在arm.com上找到。它说:

The destination register. The SP can be used. The PC can be used, provided the
instruction is either outside an IT block or the last instruction of an IT block.
If the PC is used, the instruction branches to the address (data) loaded to the PC.
In ARMv5T and above, this branch is an interworking branch, see Pseudocode details of
operations on ARM core registers on page A2-12.

它并没有说目标寄存器不能与基址寄存器相同。也就是说,答案是“是”,它们可以相同。


3
是的,而且它将获取r0指向的值,并将寄存器r0加载到该值上。 如果不确定,可以使用模拟器进行测试。我使用的是VBA GBA模拟器,尽管是特定于GBA的,但是它是一个很好的ARM模拟器。要了解GBA编程基础以便进行此类测试,请访问教程。

仿真器无法知道硬件的实际操作,因此不要完全信赖它们。VBA与硬件也不匹配,存在足够的差异。 - old_timer
指令集将允许您编码此指令,如果问题是这样的话,那么是的,它会... - old_timer
@dwelch 是的,但不足以阻止它们被用于尝试像问题中提到的小事情。我说的是ARM汇编测试,而不是GBA测试。我认为在VBA中没有指令实现不正确 :) - byrondrossos
1
明白,VBA不太与GBA兼容,我不知道这种不兼容是在ARM核心内部还是外部。所以可以说它可能不是核心的问题。另一个公正的陈述是,如果ARM声明某些东西是“不可预测的(unpredictable)”,你需要了解即使您的代码在实际硬件或模拟器上运行也可能出现问题。您不能询问硬件或模拟器是否工作,单个实验不能确定设计成功。 ARM的文档比其他任何人都更好,使用这些文档。 - old_timer
dwelch 是完全正确的。模拟器仅证明模拟器的行为。不可预测的指令可能大部分时间都能正常工作,但当它们失败时,很难找出或复现问题。 - Variable Length Coder

1

这种编码对于从ARMv4开始的arm和thumb指令集都是有效的。

查看你感兴趣的系列的ARM ARM(ARM架构参考手册)(http://infocenter.arm.com)。在这种情况下,ARM7是ARMv4,与ARMv5 ARM一起被分为单独的ARM ARM(曾经是原始和唯一的ARM ARM)。

你正在寻找这样的东西:

if ConditionPassed(cond) then
Rd = (Rm * Rs)[31:0]
if S == 1 then
N Flag = Rd[31]
Z Flag = if Rd == 0 then 1 else 0
C Flag = unaffected in v5 and above, UNPREDICTABLE in v4 and earlier
V Flag = unaffected

对于乘法或这个

Specifying R15 for register <Rd>, <Rm>, or <Rs> has UNPREDICTABLE results.

或者这个

Operand restriction: Specifying the same register for <Rd> and <Rm> was previously described as producing UNPREDICTABLE results. There is no restriction in ARMv6, and it is believed all relevant ARMv4 and ARMv5 implementations do not require this restriction either, because high performance multipliers read all their operands prior to writing back any results.

在ARMv4/5手册中,LDR指令的操作数限制为:如果“写回基址寄存器”的选项被指定,并且相同的寄存器被用于“基址寄存器”和“目标寄存器”,则结果是不可预测的。我认为这个意思是这个指令:
ldr r0,[r0,#+/-offset_12]!

就像你告诉指令将加载值和计算后的地址保存到r0一样,它是不可预测的,只有一个可以获胜,听起来就像是个抛硬币的事情。如果末尾没有!,那么只有加载的值会被写入r0。而且关于限制没有任何注释(在原始ARM ARM的rev I中,回溯到rev B和C以及E的印刷版本,它们在这方面各不相同,这就是为什么我认为arm使用了“相关”这个术语)。对于上面剪切和粘贴的mul指令。

Thumb指令对限制或不可预测的行为没有任何注释。

现在,如果你在标签中加上ARM7是指ARMv7,请查看其中一个ARMv7手册

对于ARMv7来自ARMv7-AR手册的同样问题:

LDR<c> <Rt>, [<Rn>, #+/-<imm12>]!
if wback && n == t then UNPREDICTABLE;

除此之外,使用该指令的方式没有任何限制,也可以使用r15。


ldr r0,[r0],#4 也应该和 ldr r0,[r0,#offset]! 一样有问题,但是 ldr r0,[r0] 是可以的。 - old_timer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接