这是我的组装代码。
a EQU 0x20000000
b EQU 0x20000004
c EQU 0x20000008
LDR R4, =a
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c 我有两个问题。在LDR R0, [R4]之后,R[4]里面是什么?0x20000000还是0x20000000的内存内容?
第二,在最后一行之后,R4?c或0x20000008中的内存内容是什么?
我在网上搜索过EQU和LDR,我自己的猜测是,对于所有的问题,它都是记忆的内容,但我很困惑,因为我的朋友说不行,我上面提到的十六进制数字存储在R[4]中。
更新:对不起,我想说的是:在LDR R0, [R4]之后,R0内部发生了什么?0x20000000或0x20000000的内存内容
R4?0x20000008还是0x20000008中的内存内容?
发布于 2020-06-24 21:55:14
首先,没有必要搜索整个互联网,直接到源代码,arm文档涵盖指令集。根据说明,这是手臂或拇指代码,但不是aarch64,所以假设手臂.
下一步是EQU是一个指令,而不是一个应该相当明显的指令,处理器将如何在汇编语言中使用变量和这样的指令?他们不会。
下一件事是汇编语言是由汇编程序定义的,你使用的工具不是目标(指令集)。这看起来可能是ARM的汇编器之一。许多人使用gnus工具,两者都能工作。我有gnu,所以汇编语言更改为:
.EQU a, 0x20000000
.EQU b, 0x20000004
.EQU c, 0x20000008
LDR R4, =a
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c对于gnu汇编程序,我先组装,然后反汇编,然后得到以下内容:
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <.text>:
0: e3a04202 mov r4, #536870912 ; 0x20000000
4: e5940000 ldr r0, [r4]
8: e3a04242 mov r4, #536870916 ; 0x20000004
c: e5941000 ldr r1, [r4]
10: e3a04282 mov r4, #536870920 ; 0x20000008类型语法是伪代码,因此不是真正的指令内容,因此汇编程序会有所不同。正如本页面其他部分所指出的,对该特性的支持是依赖于工具的,一些工具处理它的方式与其他工具不同。Gnu汇编程序,似乎最具特色的rich....let me digress...The寄存器是32位,指令是32位,不可能用32位立即加载指令和32位(固定长度)指令--没有其他位了。不同的(固定长度)指令集解决这种不同的方式,arm有它的解决方案是有趣的,并且在arm,拇指和thumb2扩展之间变化,对于arm,您可以有多达8个非零位,可以旋转一个偶数位,使immediate....gnu汇编程序将尽最大努力选择mov或mvn,如果它可以,否则它会创建一个pc相对负载,并将该值放置在附近的池。
在您的例子中,这些常量都工作得很好,因此mov被替换为ldr =伪指令。
0: e3a04202 mov r4, #536870912 ; 0x20000000
4: e5940000 ldr r0, [r4]
8: e3a04242 mov r4, #536870916 ; 0x20000004
c: e5941000 ldr r1, [r4]
10: e3a04282 mov r4, #536870920 ; 0x20000008因为您应该已经在arm文档中阅读过了(如果没有方便的处理器供应商提供的文档,您就无法开始学习/阅读程序集)。ldr r0,r4的意思是将r4中的位作为地址使用(在r4中放置了0x20000000的先前指令,因此对于这个指令0x20000000成为一个地址),从该地址读取(加载)并将结果(返回的位)放在r0中。
作示范用途
.EQU a, 0x20000004
.EQU b, 0x20000200
.EQU c, 0x20000008
LDR R4, =a
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c给出
00000000 <.text>:
0: e3a04242 mov r4, #536870916 ; 0x20000004
4: e5940000 ldr r0, [r4]
8: e59f4004 ldr r4, [pc, #4] ; 14 <a-0x1ffffff0>
c: e5941000 ldr r1, [r4]
10: e3a04282 mov r4, #536870920 ; 0x20000008
14: 200002000x20000004可以旋转,你可以旋转0x00000042,例如,围绕偶数位旋转,这看起来像他们所做的。但是,不能根据mov或mvn指令的规则创建0x20000200,因此在附近使用了值0x20000200的pc相对负载。由于这不是完整的代码,处理器会像指令一样大量地输入数据,直到最终崩溃或幸运地陷入循环。对于真正的代码,该池将放置在某种类型的无条件分支之后和/或您告诉它的地方,该池基于汇编程序特定的汇编语言指令。
从技术上讲,arm汇编程序的汇编语言不必支持ldr r0,r4语法汇编程序作者可以自由地做他们想做的任何事情-- ldr r0,(r4),ldr r4,r0 loadw r0,0(r4),bob泡菜,洋葱,只要它生成正确的机器代码,它就是生成arm指令的汇编语言,因此也是arm汇编语言。到目前为止,我使用的所有汇编程序都按照这个顺序支持ldr r0,r4语法,但我认为并不是所有的人都支持=address,而且根据这里的经验,并不是所有的人都支持它。
您可以自己加载,但也可以使用汇编语言特定的差异:
.EQU a, 0x20000000
.EQU b, 0x20000000
.EQU c, 0xFFFFFF20
LDR R4, avalue
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c
avalue: .word a
Disassembly of section .text:
00000000 <avalue-0x14>:
0: e59f400c ldr r4, [pc, #12] ; 14 <avalue>
4: e5940000 ldr r0, [r4]
8: e3a04202 mov r4, #536870912 ; 0x20000000
c: e5941000 ldr r1, [r4]
10: e3e040df mvn r4, #223 ; 0xdf
00000014 <avalue>:
14: 20000000这迫使pc的相对负载,因为这是我所要求的。在arm目标中,一些汇编语言希望冒号标记标签,其他语言则看不到EQU差异(EQU类似于C#中简单的#define,在C中定义了0x2000000,但与C不同,您不使用它来处理更复杂的宏,可能会有特定于汇编程序的宏语言部分)。大多数正常的汇编程序使用冒号来标记注释,对于arm的gnu则不这样做(请注意,gnu汇编语言并不都必须在不同的目标上都有共同的规则/特性,假设每个目标都是由不同的人编写和维护的,因此每种语言对于评论和其他非指令性的东西都是不同的。如果它们是重叠的,那就这样吧。
这是不链接的,所以这个工具的反汇编从0开始,一旦链接,这个反汇编输出就会有不同的地址,但是位置无关( pc相对负载是……计算机代码将保持原样(对于这些示例)。
EQU是一个类似于C中定义的指令,它允许您使用0x20000000的值,而不是键入变量或名称或字符串a,而预处理程序将搜索并用0x20000000替换字母a的明显用法(当然,它不会替换a in add r0、r1、r2 )。
LDR是一个指令族LoaD寄存器。提供位于寄存器中的地址、可能的偏移量和目标寄存器。LDR R0,R4的意思是r4包含地址(在您的例子中是0x20000000),而r0是保存加载结果的目标寄存器。
ARM制造核心而不是芯片,没有理由假设0x20000000是“内存”--它可能是一个外围设备,处理器不关心,它只是一个它放在总线上的地址,芯片供应商知道这个地址意味着什么,并在总线上返回一个值。处理器不知道它是内存还是其他东西。
正如所写的,假设这不是某种破坏事物的奇怪的汇编程序,第一个ldr从地址0x20000000加载,并将结果放在r0中。
发布于 2020-06-24 20:54:30
前3行定义地址--这些地址可以存储在内存中的本地池中,但由于它们非常简单,汇编程序可能在第一次使用时使用几个MOV指令来组装它们。
第4行将R4设置为宏a -> 0x20000000的值(可能通过带有shift操作的MOV,但如果汇编程序出于某种原因希望从内存池加载)。
第5行从0x20000000的内存中读取,并将从内存中读取的值放入R0。
第6行用R4加载0x20000004 (可能成为MOV和ADD)
第7行从0x20000004的内存中读取值,并将值放入R1,最后一行用0x2000008加载R4 (可能成为MOV和ADD)。
简而言之,LDR R4, =指令只加载寄存器中存储在EQU语句中的地址。后面的R0/R1负载是它们所指向的地址中的负载。
现在,如果真正了解程序集的人正在编写这个程序集,那么它可能只会变成2个指令:一个MOV of 0x2,它将转换为R4,以及一个处理负载和增量的LDM指令。
https://stackoverflow.com/questions/62563750
复制相似问题