如何计算指令之间的字节数



Valvano的书中有一段Keil汇编代码(3.3.3内存访问指令(:

; Keil Syntax
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
;outside of execution
PAaddr DCD 0x400043FC

第一行LDR R5, PAaddr由汇编程序翻译为

LDR R5, [PC, #16]

其中CCD_ 2表示CCD_ 3和CCD_。

我不明白#16是怎么来的。根据Keil的ARM和Thumb指令,MOV是一条16位指令(因此是2字节(。我找不到STRDCD的指令大小,但从ARM的指令集摘要来看,STR的周期是MOV的两倍,所以我直观地猜测STR的指令大小是MOV的两倍(或4字节(。DCD只是将值存储到ROM中,所以它不能比MOV大。如果我用字节来总结指令大小(MOV为2,STR为4,DCD可能为1或2(,那么从第二条到最后一条指令之间应该有7或8个字节,或者从PC跳转#7或#8。

我手头没有Kiel,但这并不重要,你没有提供足够的信息(你的目标体系结构/核心是什么(,arm并没有很好地记录所有这些。

所以通用拇指

.thumb
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
.align
PAaddr: .word 0x400043FC
Disassembly of section .text:
00000000 <PAaddr-0x8>:
0:   4d01        ldr r5, [pc, #4]    ; (8 <PAaddr>)
2:   2655        movs    r6, #85 ; 0x55
4:   602e        str r6, [r5, #0]
6:   46c0        nop         ; (mov r8, r8)
00000008 <PAaddr>:
8:   400043fc    .word   0x400043fc

立即偏移量添加到指令的Align(PC,4(值以形成地址。对于编码T1,允许的值是0-1020范围内的四的倍数。

因此ALIGN(0x00+2,4(=0x04。0x08-4=4=一个单词。所以1个字0x4D01,01就是立即数。

.thumb
nop
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
.align
PAaddr: .word 0x400043FC

00000000 <PAaddr-0x8>:
0:   46c0        nop         ; (mov r8, r8)
2:   4d01        ldr r5, [pc, #4]    ; (8 <PAaddr>)
4:   2655        movs    r6, #85 ; 0x55
6:   602e        str r6, [r5, #0]
00000008 <PAaddr>:
8:   400043fc    .word   0x400043fc

ALIGN(0x02+2,4(=0x4。0x08-0x04=0x04,一个字0x4D01编码。

.cpu cortex-m3
.thumb
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
.align
PAaddr: .word 0x400043FC
Disassembly of section .text:
00000000 <PAaddr-0x8>:
0:   4d01        ldr r5, [pc, #4]    ; (8 <PAaddr>)
2:   2655        movs    r6, #85 ; 0x55
4:   602e        str r6, [r5, #0]
6:   bf00        nop
00000008 <PAaddr>:
8:   400043fc    .word   0x400043fc

没有变化,但

.cpu cortex-m3
.syntax unified
.thumb
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
.align
PAaddr: .word 0x400043FC
Disassembly of section .text:
00000000 <PAaddr-0x8>:
0:   4d01        ldr r5, [pc, #4]    ; (8 <PAaddr>)
2:   f04f 0655   mov.w   r6, #85 ; 0x55
6:   602e        str r6, [r5, #0]
00000008 <PAaddr>:
8:   400043fc    .word   0x400043fc

.cpu cortex-m3
.syntax unified
.thumb
nop
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
.align
PAaddr: .word 0x400043FC
Disassembly of section .text:
00000000 <PAaddr-0xc>:
0:   bf00        nop
2:   4d02        ldr r5, [pc, #8]    ; (c <PAaddr>)
4:   f04f 0655   mov.w   r6, #85 ; 0x55
8:   602e        str r6, [r5, #0]
a:   bf00        nop
0000000c <PAaddr>:
c:   400043fc    .word   0x400043fc

ALIGN(0x02+2,4(=0x04。0x0C-0x04=0x08,2个字,0x4D02编码。

您可以使用Kiel的汇编语言与上面显示的gnu做同样的事情。

除非你正在编写自己的汇编程序(或者出于其他原因试图创建自己的机器代码(,否则你的工作不是计数。

在任何情况下,只需阅读有关体系结构的ARM体系结构文档。将其与经过调试的汇编程序的输出进行比较,以便根据需要进行进一步的说明。

编辑

来自早期/原始ARM ARM

address = (PC[31:2] << 2) + (immed_8 * 4)
Rd = Memory[address, 4]

这个更有意义IMO.

当有疑问时,请返回旧的/原始的ish ARM ARM。

最新的ARM ARM

if ConditionPassed() then
EncodingSpecificOperations(); NullCheckIfThumbEE(15);
base = Align(PC,4);
address = if add then (base + imm32) else (base - imm32);
data = MemU[address,4];
if t == 15 then
if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
elsif UnalignedSupport() || address<1:0> == ‘00’ then
R[t] = data;
else // Can only apply before ARMv7
if CurrentInstrSet() == InstrSet_ARM then
R[t] = ROR(data, 8*UInt(address<1:0>));
else
R[t] = bits(32) UNKNOWN;

但这涵盖了T1、T2和A1在一个镜头中的编码,使其最令人困惑。

在任何情况下,它们都描述了编码的情况以及每个指令的总体大小。

最新更新