问题描述
作为练习,我想让STM32F103从内部SRAM执行。想法是手工编写一些THUMB程序集,将其与arm-none-eabi-as
进行汇编,使用OpenOCD的mwh
指令将机器代码加载到SRAM中,使用reg pc 0x20000000
将PC设置为SRAM的开头,然后最后step
几次。
# main.S
.thumb
.Syntax unified
mov r0,#40
mov r1,#2
add r2,r0,r1
mvn r0,#0x20000000
bx r0
我需要获取机器代码,以便可以将其加载到SRAM中,但是反汇编程序的输出似乎不正确。
$ arm-none-eabi-as -mthumb -mcpu=cortex-m3 -o main.o main.S
$ arm-none-eabi-objdump -d -m armv7 main.o
main.o: file format elf32-littlearm
disassembly of section .text:
00000000 <.text>:
0: f04f 0028 mov.w r0,#40 ; 0x28
4: f04f 0102 mov.w r1,#2
8: eb00 0201 add.w r2,r1
c: f06f 5000 mvn.w r0,#536870912 ; 0x20000000
10: 4700 bx r0
THUMB指令的长度不是16位吗?我得到的机器代码每条指令占用4个字节。
解决方法
STM32F103基于cortex-m3。您需要先从st文件开始说起,然后说到arms网站获取cortex-m3技术参考手册。它告诉您这是基于armv7-m架构的,因此您可以获取架构参考手册。然后,您可以开始编程。
从Flash运行通常的方法是使用向量表,从ram运行可能意味着取决于启动引脚,但是如果要使用调试器下载程序,则在正确的路径上就被卡住或停止了整理。
# main.S
.thumb
.syntax unified
mov r0,#40
mov r1,#2
add r2,r0,r1
mvn r0,#0x20000000
bx r0
您指定了统一语法,也许在命令行cortex-m3上指定了?还是armv7-m?因此,您最终得到了thumb2扩展,它们是ARM记录的两个16位半部分(armv7-m体系结构参考手册向您展示了所有指令)。它们是可变长度的,第一个是解码的,第二个只是操作数。 non-thumb2都是16位,bl / blx是/是两个单独的16位指令,但是cortex-ms希望它们是背靠背的,在先前的内核上,您实际上可以将它们分开,以证明它们确实是两个不同的说明。
例如
.cpu cortex-m3
.thumb
.syntax unified
add r2,r1
adds r2,r1
00000000 <.text>:
0: eb00 0201 add.w r2,r1
4: 1842 adds r2,r1
16位“全拇指变体”编码仅带有标志,因此您必须添加加号;如果gnu汇编程序和您指定了统一的语法(大多数人会告诉您这样做),我个人不会说。请注意:
.cpu cortex-m3
.thumb
add r2,r1
so.s: Assembler messages:
so.s:6: Error: instruction not supported in Thumb16 mode -- `adds r2,r1'
如此
.cpu cortex-m3
.thumb
add r2,r1
add r2,r1
00000000 <.text>:
0: 1842 adds r2,r1
2: 1842 adds r2,r1
只是警告您,以防您掉入该陷阱。而且,您不只是喜欢反汇编程序使用的添加。
无论如何。这些很好,这些都是
.cpu cortex-m3
.thumb
.syntax unified
mov r0,#0x20000000
bx r0
00000000 <.text>:
0: f04f 0028 mov.w r0,#40 ; 0x28
4: f04f 0102 mov.w r1,#2
8: eb00 0201 add.w r2,r1
c: f06f 5000 mvn.w r0,#536870912 ; 0x20000000
10: 4700 bx r0
就像添加mov的16位编码是带有标志一样
movs r0,#40
movs r1,#2
00000000 <.text>:
0: 2028 movs r0,#40 ; 0x28
2: 2102 movs r1,#2
4: eb00 0201 add.w r2,r1
8: f06f 5000 mvn.w r0,#536870912 ; 0x20000000
c: 4700 bx r0
我们知道现在添加
00000000 <.text>:
0: 2028 movs r0,#2
4: 1842 adds r2,r1
6: f06f 5000 mvn.w r0,#536870912 ; 0x20000000
a: 4700 bx r0
MVN毫无意义,您想分支到0x20000000的两件事,首先要0x20000000而不是0xDFFFFFFF,所以请尝试
0: 2028 movs r0,r1
6: f04f 5000 mov.w r0,#536870912 ; 0x20000000
a: 4700 bx r0
第二,这是一个cortex-m,因此您不能将bx设置为偶数地址,这是您切换到布防模式的方式,但是此处理器没有执行此操作,因此会出错。您需要lsbit集。所以试试这个
.cpu cortex-m3
.thumb
.syntax unified
movs r0,#2
adds r2,r1
ldr r0,=0x20000001
bx r0
00000000 <.text>:
0: 2028 movs r0,r1
6: 4801 ldr r0,[pc,#4] ; (c <.text+0xc>)
8: 4700 bx r0
a: 0000 .short 0x0000
c: 20000001 .word 0x20000001
如果使用gnu汇编程序,则ldr equals事物将选择最有效的(最小指令)解决方案,否则它将从池中拉出。
或者您可以执行此操作而不使用游泳池
.cpu cortex-m3
.thumb
.syntax unified
movs r0,r1
mov r0,#0x20000000
orr r0,#1
bx r0
这使我的皮肤爬行,因为您不希望添加,但这会使它缩短半个字:
.cpu cortex-m3
.thumb
.syntax unified
movs r0,#0x20000000
adds r0,#1
bx r0
00000000 <.text>:
0: 2028 movs r0,#536870912 ; 0x20000000
a: 3001 adds r0,#1
c: 4700 bx r0
然后您需要链接。但是...
.cpu cortex-m3
.thumb
.syntax unified
movs r0,#0
loop:
adds r0,#1
b loop
不使用链接描述文件进行链接即可快速
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x20000000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000020000000
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
20000000 <_stack+0x1ff80000>:
20000000: 2000 movs r0,#0
20000002 <loop>:
20000002: 3001 adds r0,#1
20000004: e7fd b.n 20000002 <loop>
打开两个窗口,一次启动openocd以连接到板/芯片
在另一个
telnet localhost 4444
当您假设所有设置都起作用时,您会收到openocd提示
halt
load_image so.elf
resume 0x20000000
或者您也可以恢复0x20000001,因为这样感觉更好,但是无论哪种方式该工具都很好。现在
halt
reg r0
resume
halt
reg r0
resume
作为一个stm32并成为所有Thumb变体指令,此示例将适用于到目前为止我听说过的任何stm32(我(使用过)很多)。
您将看到r0会增加,从恢复到再次暂停之间的人工时间将计数很多次,您可以看到数字变化看到程序正在运行。
telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> load_image so.elf
6 bytes written at address 0x20000000
downloaded 6 bytes in 0.001405s (4.170 KiB/s)
> resume 0x20000000
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x20000002 msp: 0x20001000
> reg r0
r0 (/32): 0x000ED40C
> resume
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x20000002 msp: 0x20001000
> reg r0
r0 (/32): 0x001C8777
>
如果您想将其放入闪存中,则假设蓝色药丸(这是蓝色药丸对吗?)没有像某些人那样的写保护闪存,但是您可以轻松地将其移除(这样您就可以知道了) ,并不一定很容易,建议在某个时候完成一个完整的电源循环)。
.cpu cortex-m3
.thumb
.syntax unified
.word 0x20001000
.word reset
.thumb_func
reset:
movs r0,#1
b loop
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x08000000 so.o -o so.elf
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 0000000008000000
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <_stack+0x7f80000>:
8000000: 20001000 .word 0x20001000
8000004: 08000009 .word 0x08000009
08000008 <reset>:
8000008: 2000 movs r0,#0
0800000a <loop>:
800000a: 3001 adds r0,#1
800000c: e7fd b.n 800000a <loop>
复位向量必须是处理程序ORRED的地址,且必须为1。并且向量表必须为0x08000000(或0x00000000,但对于某些非本项,您最终将需要0x08000000或0x02000000,对于本项,则最终需要0x08000000,请阅读文档)。
在telnet中进入openocd
flash write_image erase so.elf
reset
halt
reg r0
resume
halt
reg r0
resume
现在它是用闪存编程的,因此,如果您关闭电源,那么它将开始运行。
openocd将以类似这样的结尾
Info : stm32f1x.cpu: hardware has 6 breakpoints,4 watchpoints
然后进行telnet会话
telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0xa1000000 pc: 0x0800000a msp: 0x20001000
> flash write_image erase so.elf
auto erase enabled
device id = 0x20036410
flash size = 64kbytes
wrote 1024 bytes from file so.elf in 0.115819s (8.634 KiB/s)
> reset
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x0800000a msp: 0x20001000
> reg r0
r0 (/32): 0x002721D4
> resume
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x0800000a msp: 0x20001000
> reg r0
r0 (/32): 0x0041DF80
>
如果要将闪光灯重置为ram,则可以这样做
.cpu cortex-m3
.thumb
.syntax unified
.word 0x20001000
.word 0x20000001
重新启动电源后,理想情况下应该崩溃/故障,但是如果您像以前一样使用openocd在ram中放置某些东西
flash.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <_stack+0x7f80000>:
8000000: 20001000 .word 0x20001000
8000004: 20000001 .word 0x20000001
so.elf: file format elf32-littlearm
Disassembly of section .text:
20000000 <_stack+0x1ff80000>:
20000000: 2000 movs r0,#1
20000004: e7fd b.n 20000002 <loop>
telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x0800000a msp: 0x20001000
> flash write_image erase flash.elf
auto erase enabled
device id = 0x20036410
flash size = 64kbytes
wrote 1024 bytes from file flash.elf in 0.114950s (8.699 KiB/s)
> load_image so.elf
6 bytes written at address 0x20000000
downloaded 6 bytes in 0.001399s (4.188 KiB/s)
> reset
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x20000002 msp: 0x20001000
> reg r0
r0 (/32): 0x001700E0
> resume
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x20000004 msp: 0x20001000
> reg r0
r0 (/32): 0x00245FF1
> resume
> halt
target state: halted
target halted due to debug-request,current mode: Thread
xPSR: 0x01000000 pc: 0x20000002 msp: 0x20001000
> reg r0
r0 (/32): 0x00311776
>
但是重新开机
telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
> reset
stm32f1x.cpu -- clearing lockup after double fault
target state: halted
target halted due to debug-request,current mode: Handler HardFault
xPSR: 0x01000003 pc: 0xfffffffe msp: 0x20000fe0
Polling target stm32f1x.cpu failed,trying to reexamine
stm32f1x.cpu: hardware has 6 breakpoints,4 watchpoints
> halt
>
是的,不如预期/期望的那样开心。
请注意,_start来自默认链接器脚本中的ENTRY(_start),它既不特殊,也不是硬编码到工具中的(也不是gcc的主要功能,它来自默认的引导程序)。
所以你可以这样做
so.s
.cpu cortex-m3
.thumb
.syntax unified
movs r0,#1
b loop
so.ld
MEMORY
{
hello : ORIGIN = 0x20000000,LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > hello
}
arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -T so.ld so.o -o so.elf
arm-none-eabi-objdump -d so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
20000000 <loop-0x2>:
20000000: 2000 movs r0,#1
20000004: e7fd b.n 20000002 <loop>
,_ start警告消失。请注意,您在链接描述文件中创建的部分名称(在本例中为hello)不必是ram,rom,flash等,它们可以是您想要的名称,是的,您可以使用链接描述文件来执行此操作,但没有MEMORY部分在文件中,只有SECTION。
如果您选择
arm-none-eabi-objcopy -O binary so.elf so.bin
openocd可以读取elf文件和其他一些文件,但是像原始内存映像一样,您必须指定地址,否则可能会得到0x00000000或谁知道
load_image so.bin 0x20000000
如果/当您获得一些核子板时,只需将bin文件复制到虚拟拇指驱动器中,它将为您将其加载到目标MCU中,并且虚拟驱动器将重新加载或重新加载并显示失败.TXT(如果它不起作用)的一种发生方式是,您链接为0x00000000而不是0x08000000。但是,您无法以这种方式加载sram,只是快闪。但我认为您有蓝色药丸而不是核子板。
那是很长的答案。
简短回答
这些是thumb2扩展名,它们是两个半字。有关说明,请参见armv7-m体系结构参考手册。对于此芯片,它们非常合适。
您可能想在openocd上不使用load_image而不是mwh,但是如果以正确的顺序输入半字,则mwh将起作用。
理想情况下,您希望链接,尽管您编写的代码或我的代码与位置无关,因此可以说您可以提取指令并使用mwh。
该芯片具有从sram模式启动的引导,它将/应该使用向量表而不只是启动指令,您需要正确设置启动引脚,并使用openocd之类的东西将程序加载到ram中,然后重置(关机后再开机)。
在这里,MVN移负或取反不是正确的指令,在使用bx之前需要设置lsbit,因此您希望在寄存器中输入0x20000001,类似
ldr r0,=0x20000001
bx r0
用于gnu汇编程序,或
mov r0,#1
bx r0
但这是针对armv7-m的,对于cortex-m0,m0 +的某些-m8s,您不能使用这些指令,它们将不起作用。
.cpu cortex-m0
.thumb
.syntax unified
mov r0,#1
bx r0
arm-none-eabi-as so.s -o so.o
so.s: Assembler messages:
so.s:5: Error: cannot honor width suffix -- `mov r0,#0x20000000'
so.s:6: Error: cannot honor width suffix -- `orr r0,#1'
因此,使用ldr =伪指令或从池中手动加载,或加载0x2或0x20之类的东西,然后对其进行移位,并向另一个寄存器加载1并对其进行orr操作,或使用add(yuck)。
编辑
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,=0x12345678
b .
00000000 <_start>:
0: 4800 ldr r0,#0] ; (4 <_start+0x4>)
2: e7fe b.n 2 <_start+0x2>
4: 12345678 eorsne r5,r4,#120,12 ; 0x7800000
如果它不能生成一条指令,那么它将生成pc的相对负载,并将变量放入文字池中,如果可以找到,则放在分支后的某个位置。
但是你也可以自己做
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,myvalue
b .
.align
myvalue: .word 0x12345678
00000000 <_start>:
0: 4800 ldr r0,#0] ; (4 <myvalue>)
2: e7fe b.n 2 <_start+0x2>
00000004 <myvalue>:
4: 12345678 eorsne r5,12 ; 0x7800000
文字池是一个内存区域(在文本段中),用于存储常量。
unsigned int fun0 ( void )
{
return 0x12345678;
}
unsigned int fun1 ( void )
{
return 0x11223344;
}
00000000 <fun0>:
0: e59f0000 ldr r0,[pc] ; 8 <fun0+0x8>
4: e12fff1e bx lr
8: 12345678 .word 0x12345678
0000000c <fun1>:
c: e59f0000 ldr r0,[pc] ; 14 <fun1+0x8>
10: e12fff1e bx lr
14: 11223344 .word 0x11223344
让C编译器执行此操作并将其放在函数的末尾很常见。
.global fun1
.syntax unified
.arm
.fpu softvfp
.type fun1,%function
fun1:
@ Function supports interworking.
@ args = 0,pretend = 0,frame = 0
@ frame_needed = 0,uses_anonymous_args = 0
@ link register save eliminated.
ldr r0,.L6
bx lr
.L7:
.align 2
.L6:
.word 287454020
.size fun1,.-fun1
我没有为thumb / cortex-m构建它,但这很好,它会做同样的事情。但是,这样说:
unsigned int fun0 ( void )
{
return 0x12345678;
}
unsigned int fun1 ( void )
{
return 0x00110011;
}
00000000 <fun0>:
0: 4800 ldr r0,#0] ; (4 <fun0+0x4>)
2: 4770 bx lr
4: 12345678 .word 0x12345678
00000008 <fun1>:
8: f04f 1011 mov.w r0,#1114129 ; 0x110011
c: 4770 bx lr
由于我对可以用于各种Arm指令集的立即数有一个粗略的了解。同样
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,=0x12345678
ldr r1,=0x00110011
nop
nop
nop
b .
00000000 <_start>:
0: 4803 ldr r0,#12] ; (10 <_start+0x10>)
2: f04f 1111 mov.w r1,#1114129 ; 0x110011
6: bf00 nop
8: bf00 nop
a: bf00 nop
c: e7fe b.n c <_start+0xc>
e: 0000 .short 0x0000
10: 12345678 .word 0x12345678
通过使用ldr = something gnu汇编程序将选择最佳指令。并非所有的手臂汇编器都支持此功能(汇编语言是由工具而不是目标定义的),并且并非所有人都会选择最佳指令,如果某些指令可以识别出与pc相关的ldr,则它们总是会生成 语法。
它在某种意义上是用于获取标签的地址的
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,=mydataword
ldr r1,[r0]
add r1,#1
str r1,[r0]
bx lr
.data
mydataword: .word 0
在另一个段中,它无法在组装时解决此问题,因此为链接器留下了占位符
00000000 <_start>:
0: 4802 ldr r0,#8] ; (c <_start+0xc>)
2: 6801 ldr r1,[r0,#0]
4: f101 0101 add.w r1,r1,#1
8: 6001 str r1,#0]
a: 4770 bx lr
c: 00000000 .word 0x00000000
arm-none-eabi-ld -Ttext=0x1000 -Tdata=0x2000 so.o -o so.elf
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
00001000 <_start>:
1000: 4802 ldr r0,#8] ; (100c <_start+0xc>)
1002: 6801 ldr r1,#0]
1004: f101 0101 add.w r1,#1
1008: 6001 str r1,#0]
100a: 4770 bx lr
100c: 00002000 andeq r2,r0
Disassembly of section .data:
00002000 <__data_start>:
2000: 00000000
或
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,=somefun
ldr r1,[r0]
orr r1,#1
bx r1
.align
somefun:
nop
b .
即使在同一段中
00000000 <_start>:
0: 4803 ldr r0,#12] ; (10 <somefun+0x4>)
2: 6801 ldr r1,#0]
4: f041 0101 orr.w r1,#1
8: 4708 bx r1
a: bf00 nop
0000000c <somefun>:
c: bf00 nop
e: e7fe b.n e <somefun+0x2>
10: 0000000c .word 0x0000000c
00001000 <_start>:
1000: 4803 ldr r0,#12] ; (1010 <somefun+0x4>)
1002: 6801 ldr r1,#0]
1004: f041 0101 orr.w r1,#1
1008: 4708 bx r1
100a: bf00 nop
0000100c <somefun>:
100c: bf00 nop
100e: e7fe b.n 100e <somefun+0x2>
1010: 0000100c andeq r1,r12
如果让工具来完成工作
.cpu cortex-m3
.thumb
.syntax unified
.globl _start
_start:
ldr r0,[r0]
bx r1
.align
.thumb_func
somefun:
nop
b .
您不需要在lsbit中执行orr,该工具会为您完成
00001000 <_start>:
1000: 4802 ldr r0,#8] ; (100c <somefun+0x4>)
1002: 6801 ldr r1,#0]
1004: 4708 bx r1
1006: bf00 nop
00001008 <somefun>:
1008: bf00 nop
100a: e7fe b.n 100a <somefun+0x2>
100c: 00001009 andeq r1,r9
所有或大多数情况下,立即数池用于帮助这样的指令集,该指令集的长度有些固定,因此对立即值有所限制。
有时您可以帮助gnu汇编器将池数据放置在何处
.cpu cortex-m3
.thumb
.syntax unified
.globl fun0
.thumb_func
fun0:
ldr r0,=0x12345678
bx lr
.globl fun1
.thumb_func
fun1:
ldr r0,=0x11223344
bx lr
.align
.word 0x111111
00000000 <fun0>:
0: 4802 ldr r0,#8] ; (c <fun1+0x8>)
2: 4770 bx lr
00000004 <fun1>:
4: 4802 ldr r0,#8] ; (10 <fun1+0xc>)
6: 4770 bx lr
8: 00111111 .word 0x00111111
c: 12345678 .word 0x12345678
10: 11223344 .word 0x11223344
但如果我
.cpu cortex-m3
.thumb
.syntax unified
.globl fun0
.thumb_func
fun0:
ldr r0,=0x12345678
bx lr
.pool
.globl fun1
.thumb_func
fun1:
ldr r0,=0x11223344
bx lr
.align
.word 0x111111
00000000 <fun0>:
0: 4800 ldr r0,#0] ; (4 <fun0+0x4>)
2: 4770 bx lr
4: 12345678 .word 0x12345678
00000008 <fun1>:
8: 4801 ldr r0,#4] ; (10 <fun1+0x8>)
a: 4770 bx lr
c: 00111111 .word 0x00111111
10: 11223344 .word 0x11223344
所以
ldr r0,=something
表示在链接时或有时将某物的地址加载到r0中。 标签只是地址,只是值/数字
ldr r0,=0x12345678
表示标签本身就是值本身,因此给我标签的地址是0x12345678并将其放在r0中,因此这是气体或某人想到的可能是武器组装商这一概念的有趣扩展,我不记得当时其他人也采纳了它或对其进行了改进或其他改进。请注意,如果您想自己做,您可以这样做
ldr r0,something_address
b .
.align
something_address: .word something
因为某物是一个标签,而该标签是一个地址,并且您没有在其中放置等号,所以等号仅用于ldr指令。与向量表相同:
.word 0x20001000
.word reset
最后,您可以执行以下操作之一以获取正确的功能地址 所谓的拇指互动
.cpu cortex-m3
.thumb
.syntax unified
.word 0x20001000
.word reset
.word handler
.word broken
.thumb_func
reset:
b .
.type handler,%function
handler:
b .
broken:
b .
Disassembly of section .text:
08000000 <_stack+0x7f80000>:
8000000: 20001000 .word 0x20001000
8000004: 08000011 .word 0x08000011
8000008: 08000013 .word 0x08000013
800000c: 08000014 .word 0x08000014
08000010 <reset>:
8000010: e7fe b.n 8000010 <reset>
08000012 <handler>:
8000012: e7fe b.n 8000012 <handler>
08000014 <broken>:
8000014: e7fe b.n 8000014 <broken>
可以使用.thumb_func,如果在拇指模式下可以在手臂模式和拇指模式下都使用.type标签,%function,并且可以看到它生成了正确的 向量表中的拇指地址,但未使用任何拇指地址,因此无法正确生成损坏的标签,因此向量将在cortex-m上发生故障。
有些人可悲地这样做:
.word reset + 1
.word handler + 1
.word broken + 1
尝试修复该问题,而不是按预期使用该工具。用于arm / thumb的其他汇编语言表示其他工具(ARM,Kiel等)具有自己的语法和规则,仅限于gnu汇编器。
还要注意,这个答案中有多少只是命令行内容,我检查了该工具的输出并对其进行了操纵,直到获得所需的东西,而不必加载和运行代码来查看发生了什么。只需使用工具即可。
编辑2
在评论中阅读其余的问题
.cpu cortex-m3
.thumb
.syntax unified
ldr r0,=0x12345678
nop
b .
00000000 <.text>:
0: 4801 ldr r0,#4] ; (8 <.text+0x8>)
2: bf00 nop
4: e7fe b.n 4 <.text+0x4>
6: 0000 .short 0x0000
8: 12345678 .word 0x12345678
将.word放在偏移量6处将是ldr的对齐错误,因此他们需要填充它以将其放置在单词对齐的地址上。
现在,您应该已经从ARM网站或其他地方下载了armv7-m体系结构参考手册。而且您至少可以在我正在查看的文档(这些文档在不断发展)中看到T1编码
imm32 = ZeroExtend(imm8:'00',32); add = TRUE;
再往下
Encoding T1 multiples of four in the range 0 to 1020
和
address = if add then (base + imm32) else (base - imm32);
data = MemU[address,4];
R[t] = data;
指令中编码的偏移量(立即数)是相对于pc的字数。 pc是“ 2前面”或指令的地址加4,因此对于ldr r0指令
0: 4801 ldr r0,#4] ; (8 <.text+0x8>)
2: bf00 nop
4: e7fe b.n 4 <.text+0x4> <--- pc is here
6: 0000 .short 0x0000
8: 12345678 .word 0x12345678
8-4 = 4; 4 >> 2 = 1,因此距离PC 1个字,指令0x48xx xx为0x4801表示一个字。再次使用此指令对齐。
那如果我们
.cpu cortex-m3
.thumb
.syntax unified
nop
ldr r0,=0x12345678
b .
00000000 <.text>:
0: bf00 nop
2: 4801 ldr r0,#4] ; (8 <.text+0x8>)
4: e7fe b.n 4 <.text+0x4>
6: 0000 .short 0x0000
8: 12345678 .word 0x12345678
似乎坏了
Operation
if ConditionPassed() then
EncodingSpecificOperations();
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;
else
R[t] = data;
当您看到所有伪代码时,在这种情况下为6个pc
然后继续阅读文档以了解伪代码
计算指令的PC或Align(PC,4)值。指令的PC值是其地址加上Thumb指令的4。一条指令的Align(PC,4)值是其PC值,并与0xFFFFFFFC进行和,以使其强制为字对齐。
所以0x6&0xFFFFFFFC =4。8-4 = 4; 4 >> 2 = 1;所以是0x4801。
如果我们强制执行thumb2指令
.cpu cortex-m3
.thumb
.syntax unified
ldr.w r0,=0x12345678
b .
它仍然可以使我们免受故障的困扰,thumb2版本可以达到奇数
00000000 <.text>:
0: f8df 0004 ldr.w r0,#4] ; 8 <.text+0x8>
4: e7fe b.n 4 <.text+0x4>
6: 0000 .short 0x0000
8: 12345678 .word 0x12345678
请注意指令末尾的4是pc + 4,但是如果我们尝试这样做,该怎么办:
.cpu cortex-m3
.thumb
.syntax unified
ldr.w r0,something
b .
something: .word 0x12345678