微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

组装THUMB指令以在Cortex-M3上执行

如何解决组装THUMB指令以在Cortex-M3上执行

作为练习,我想让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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。