我正在浏览这个教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html
第一条装配线是:
ldr r0,=0x20200000
字符串
第二个是:
mov r1,#1
型
我以为ldr
是从内存中加载值到寄存器中。但似乎=
意味着0x20200000是一个值而不是内存地址。两行似乎都在加载绝对值。
我正在浏览这个教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html
第一条装配线是:
ldr r0,=0x20200000
字符串
第二个是:
mov r1,#1
型
我以为ldr
是从内存中加载值到寄存器中。但似乎=
意味着0x20200000是一个值而不是内存地址。两行似乎都在加载绝对值。
4条答案
按热度按时间wf82jlnq1#
这是一个窍门/捷径。比如说
字符串
会发生的是汇编程序会分配一个数据字,在指令附近,但在指令路径之外
型
现在将这个技巧扩展到常量/立即数,特别是那些不能放入移动立即数指令的常量/立即数:
型
组装然后拆卸
型
你会看到汇编程序已经为你添加了数据字,并为你将ldr改为pc相对值。
现在如果你使用一个适合mov指令的立即数,那么可能取决于汇编程序,当然是我使用的gnu,它把它变成了mov
型
所以它基本上是一个输入的快捷方式,要知道你是在给汇编程序一个权力,让它找到一个地方来粘贴常量,它通常做得很好,有时会抱怨,不确定我是否见过它不能安全地做到这一点。有时你需要在代码中使用.ltorg或.pool来鼓励汇编程序找到一个地方。
ntjbwcob2#
一个简短的回应,来自一个更接近你水平的人,希望它能有所帮助:在ARM中,指令有32位。一些位用于识别操作,一些用于操作数,在MOV指令的情况下,一些可用于立即值(例如#1)。
正如你所看到的here(第33页),只有12位可用于立即数。不是使用每个位作为数字(范围从0到2^12-1~4095),而是通过右旋转(ROR)前8位,最后4位指定的量的两倍来计算立即数。即
immediate = first 8 bits ROR 2*(last four bits)
。通过这种方式,我们可以获得比0到4095更广泛的数字范围(参见第34页可能的立即数的简要总结)。但是请记住,对于12位,仍然只有4096个可能的值可以指定。
如果我们的数字不能转换成像前一个那样的指令(257不能表示为8位旋转2次任何4位),那么,我们必须使用LDR r 0,=257
在这种情况下,编译器将数字257保存在内存中,靠近程序代码,因此它可以相对于PC进行寻址,并从内存中加载它,就像dwell详细解释的那样。
注意:如果你按照那个教程,那么当你尝试用mov r 0,#257 'make'时,你会得到一个错误,你必须手动尝试ldr r 0,=257。
qhhrdooz3#
虽然其他答案都很好,但我想我可以简化答案。
ldr= LoaD寄存器
mov= MOVE
两者都有效地做同样的事情,但以不同的方式。
这种区别就像
字符串
和
型
用C语言编写。
mov确实很快,因为它将伴随的值直接存储为指令的一部分(以上面答案中描述的12位格式)。由于它存储值的方式,它有一些限制。为什么?因为
另一方面,ldr是通用的(主要是由于编译器优化)。它是这样工作的(如反汇编例程所示)
希望能帮上忙。
ufj5ltwl4#
这是这个问题唯一的答案,所有其他的答案都令人困惑。
MOV:* 要放入的立即值,编码T1时允许的值范围为0-255 *
LDR:* 对于编码T1,偏移的允许值是0-1020范围内的4的倍数。*
ARMv 6-M说明书:https://developer.arm.com/documentation/ddi0419/latest/