如何计算指令之间的字节数
How to count number of bytes between instructions
Valvano的书(3.3.3 Memory Access Instruction)中有这段Keil汇编代码:
; Keil Syntax
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
;outside of execution
PAaddr DCD 0x400043FC
第一行 LDR R5, PAaddr
被汇编器翻译成
LDR R5, [PC, #16]
其中 #16
表示 MOV R6, #0x55
和 DCD
定义之间的字节数。
我不明白 #16
是怎么来的。根据 Keil's ARM and Thumb Instructions, MOV
is a 16-bit instruction (hence 2-bytes). I can't find the instruction size for STR
or DCD
, but from reading ARM's instruction set summary,STR
的周期是 MOV
的两倍,所以我直觉地猜测 STR
的指令大小是 MOV
的两倍(或 4 个字节)。 DCD
只是把值存入ROM,所以不能比MOV大。如果我以字节为单位总结指令大小(MOV 为 2,STR 为 4,DCD 可能为 1 或 2),我应该在第二条指令到最后一条指令之间得到 7 或 8 个字节,或者 #7 或 #8改为从 PC 跳转。
我手边没有 Kiel,但这并不重要,您没有提供足够的信息(您的目标是什么 architecture/core),而且 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
The immediate offset added to the Align(PC, 4) value of the instruction to form the address. Permitted values are multiples of four in the range 0-1020 for encoding T1.
所以对齐(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
对齐(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
对齐(0x02+2,4) = 0x04。 0x0C-0x04 = 0x08,2个字,0x4D02编码。
你可以用 Kiel 的汇编语言和上面显示的 gnu 做同样的事情。
除非您正在编写自己的汇编程序(或出于其他原因尝试创建自己的机器代码),否则计算不是您的工作。
无论如何,只需阅读相关体系结构的 ARM 体系结构文档即可。将其与调试汇编程序的输出进行比较,以便根据需要进一步说明。
编辑
来自early/originalARM ARM
address = (PC[31:2] << 2) + (immed_8 * 4)
Rd = Memory[address, 4]
这个在我看来更有意义。
如有疑问,请返回 old/original-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 编码,因此最令人困惑。
在任何情况下,它们都描述了编码的情况以及每条指令的总体大小。
Valvano的书(3.3.3 Memory Access Instruction)中有这段Keil汇编代码:
; Keil Syntax
LDR R5, PAaddr
MOV R6, #0x55
STR R6, [R5]
;outside of execution
PAaddr DCD 0x400043FC
第一行 LDR R5, PAaddr
被汇编器翻译成
LDR R5, [PC, #16]
其中 #16
表示 MOV R6, #0x55
和 DCD
定义之间的字节数。
我不明白 #16
是怎么来的。根据 Keil's ARM and Thumb Instructions, MOV
is a 16-bit instruction (hence 2-bytes). I can't find the instruction size for STR
or DCD
, but from reading ARM's instruction set summary,STR
的周期是 MOV
的两倍,所以我直觉地猜测 STR
的指令大小是 MOV
的两倍(或 4 个字节)。 DCD
只是把值存入ROM,所以不能比MOV大。如果我以字节为单位总结指令大小(MOV 为 2,STR 为 4,DCD 可能为 1 或 2),我应该在第二条指令到最后一条指令之间得到 7 或 8 个字节,或者 #7 或 #8改为从 PC 跳转。
我手边没有 Kiel,但这并不重要,您没有提供足够的信息(您的目标是什么 architecture/core),而且 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
The immediate offset added to the Align(PC, 4) value of the instruction to form the address. Permitted values are multiples of four in the range 0-1020 for encoding T1.
所以对齐(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
对齐(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
对齐(0x02+2,4) = 0x04。 0x0C-0x04 = 0x08,2个字,0x4D02编码。
你可以用 Kiel 的汇编语言和上面显示的 gnu 做同样的事情。
除非您正在编写自己的汇编程序(或出于其他原因尝试创建自己的机器代码),否则计算不是您的工作。
无论如何,只需阅读相关体系结构的 ARM 体系结构文档即可。将其与调试汇编程序的输出进行比较,以便根据需要进一步说明。
编辑
来自early/originalARM ARM
address = (PC[31:2] << 2) + (immed_8 * 4)
Rd = Memory[address, 4]
这个在我看来更有意义。
如有疑问,请返回 old/original-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 编码,因此最令人困惑。
在任何情况下,它们都描述了编码的情况以及每条指令的总体大小。