assembly 手臂拇指中的表分支字节(TBB)的简单示例

x9ybnkn6  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(90)

我试图弄清楚TBB在手臂装配中如何工作的细节。我只是想找出一个简单的例子,但无论我的代码去无限循环或不编译。

.syntax unified             
.thumb      

BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.global example_TBB
.thumb_func
 example_TBB:
 mov r1, #1

 ADR.W r0, BranchTable_Byte
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r2, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r3, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r4, #3
    b endTBB

 endTBB:

 bx lr

字符串
我相信应该发生的是,由于r1=1,tbb操作代码应该分支到情况2,但我得到无限循环和/或编译错误,无论我玩了多久。

5n0oy7gb

5n0oy7gb1#

所以

.globl _start
_start:
    bl example_TBB
    b .

字符串
待定

.syntax unified
.thumb

BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.global example_TBB
.thumb_func
 example_TBB:
 mov r1, #1

 ADR.W r0, BranchTable_Byte
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r0, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r0, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r0, #3
    b endTBB

 endTBB:

 bx lr


为文本和数据地址创建一个位置并不重要,这是为了看看工具在做什么:

arm-none-eabi-ld -Ttext=0x1000 -Tdata=0x2000 so.o tbb.o -o so.elf

00001000 <_start>:
    1000:   fb000000    blx 100a <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <BranchTable_Byte>:
    1008:       svcmi   0x00060300

0000100a <example_TBB>:
    100a:   01f04f06    mvnseq  r4, r6, lsl #30
    100e:   af01        add r7, sp, #4
    1010:   08f2        lsrs    r2, r6, #3


你看,这是个大问题如何将表中的3个字节的数据放入两个字节中?
你的代码暗示你可能想这样做:

.syntax unified
.thumb
.data
BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.global example_TBB
.thumb_func
 example_TBB:
 mov r1, #1

 ADR.W r0, BranchTable_Byte
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r0, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r0, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r0, #3
    b endTBB

 endTBB:

 bx lr


哇,这更糟糕(好吧,这是一个ADR,而不是加载地址):

00001000 <_start>:
    1000:   fa000000    blx 1008 <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <example_TBB>:
    1008:   f04f 0101   mov.w   r1, #1
    100c:   f2af 0004   subw    r0, pc, #4
    1010:   e8d0 f001   tbb [r0, r1]

00001014 <Case1>:
    1014:   f04f 0001   mov.w   r0, #1
    1018:   e005        b.n 1026 <endTBB>

0000101a <Case2>:
    101a:   f04f 0002   mov.w   r0, #2
    101e:   e002        b.n 1026 <endTBB>

00001020 <Case3>:
    1020:   f04f 0003   mov.w   r0, #3
    1024:   e7ff        b.n 1026 <endTBB>

00001026 <endTBB>:
    1026:   4770        bx  lr

Disassembly of section .data:

00002000 <__data_start>:
    2000:   Address 0x0000000000002000 is out of bounds.


表的深度为3个字节,为了对齐,可以使用4个字节

.syntax unified
.thumb
BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation
 .byte 0
 
.text
.global example_TBB
.thumb_func
 example_TBB:
 mov r1, #1

 ADR.W r0, BranchTable_Byte
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r0, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r0, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r0, #3
    b endTBB

 endTBB:

 bx lr


给予

00001000 <_start>:
    1000:   fa000001    blx 100c <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <BranchTable_Byte>:
    1008:   00060300    andeq   r0, r6, r0, lsl #6

0000100c <example_TBB>:
    100c:   f04f 0101   mov.w   r1, #1
    1010:   f2af 000c   subw    r0, pc, #12
    1014:   e8d0 f001   tbb [r0, r1]


好多了:现在4个字节能装下4个字节。那很好。但更好的是,如果你把数据与代码内联,你应该对齐,或者把数据放在后面:

.syntax unified
.thumb
BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.align
.global example_TBB
.thumb_func

 example_TBB:
 mov r1, #1
...


这也解决了问题

00001000 <_start>:
    1000:   fa000001    blx 100c <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <BranchTable_Byte>:
    1008:   00060300    andeq   r0, r6, r0, lsl #6

0000100c <example_TBB>:
    100c:   f04f 0101   mov.w   r1, #1
    1010:   f2af 000c   subw    r0, pc, #12
    1014:   e8d0 f001   tbb [r0, r1]


你可能希望你的表在.text中,这是你指定的地方。如果你把它放进.data,那么你必须把它从flash到ram假设这是一个微控制器。但你需要做的事情略有不同。

.syntax unified
.thumb

.data
BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.global example_TBB
.thumb_func

 example_TBB:
 mov r1, #1

 ldr r0,=BranchTable_Byte
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r0, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r0, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r0, #3
    b endTBB

 endTBB:

 bx lr

Disassembly of section .text:

00001000 <_start>:
    1000:   fa000000    blx 1008 <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <example_TBB>:
    1008:   f04f 0101   mov.w   r1, #1
    100c:   4806        ldr r0, [pc, #24]   ; (1028 <endTBB+0x4>)
    100e:   e8d0 f001   tbb [r0, r1]

00001012 <Case1>:
    1012:   f04f 0001   mov.w   r0, #1
    1016:   e005        b.n 1024 <endTBB>

00001018 <Case2>:
    1018:   f04f 0002   mov.w   r0, #2
    101c:   e002        b.n 1024 <endTBB>

0000101e <Case3>:
    101e:   f04f 0003   mov.w   r0, #3
    1022:   e7ff        b.n 1024 <endTBB>

00001024 <endTBB>:
    1024:   4770        bx  lr
    1026:   20000000    andcs   r0, r0, r0
    ...

Disassembly of section .data:

00002000 <__data_start>:
    2000:   Address 0x0000000000002000 is out of bounds.


你不讨厌他们这样做吗?

.syntax unified
.thumb

.data
BranchTable_Byte:
 .byte 0 @; Case1 offset calculation
 .byte ((Case2-Case1)/2) @; Case2 offset calculation
 .byte ((Case3-Case1)/2) @; Case3 offset calculation

.text
.global example_TBB
.thumb_func

 example_TBB:
 mov r1, #1

 ldr r0,btbadd
 TBB [r0, r1] @; R1 is the index, R0 is the base address of the branch table

 Case1:
    @; an instruction sequence follows
    mov r0, #1
    b endTBB
 Case2:
    @; an instruction sequence follows
    mov r0, #2
    b endTBB
 Case3:
    @; an instruction sequence follows
    mov r0, #3
    b endTBB

.align
btbadd: .word BranchTable_Byte

 endTBB:

 bx lr


这是一种更好的方法:

Disassembly of section .text:

00001000 <_start>:
    1000:   fa000000    blx 1008 <example_TBB>
    1004:   eafffffe    b   1004 <_start+0x4>

00001008 <example_TBB>:
    1008:   f04f 0101   mov.w   r1, #1
    100c:   4805        ldr r0, [pc, #20]   ; (1024 <btbadd>)
    100e:   e8d0 f001   tbb [r0, r1]

00001012 <Case1>:
    1012:   f04f 0001   mov.w   r0, #1
    1016:   e007        b.n 1028 <endTBB>

00001018 <Case2>:
    1018:   f04f 0002   mov.w   r0, #2
    101c:   e004        b.n 1028 <endTBB>

0000101e <Case3>:
    101e:   f04f 0003   mov.w   r0, #3
    1022:   e001        b.n 1028 <endTBB>

00001024 <btbadd>:
    1024:   00002000    andeq   r2, r0, r0

00001028 <endTBB>:
    1028:   4770        bx  lr
    102a:   46c0        nop         ; (mov r8, r8)

Disassembly of section .data:

00002000 <__data_start>:
    2000:   Address 0x0000000000002000 is out of bounds.


但是现在你有了.data,你不需要它是. data。
请注意,如果你将其与编译后的代码链接,你的编译器可能符合arm调用约定,即你不能在函数中修改r4,你必须保留它。这就是为什么我修改了您的代码(我想您是从我那里得到的,当我为您将它移植到gas时?))
我忘了,拇指在so. s。这很好,不是感兴趣的代码,不打算修复上面,但将在下面你可能想添加一些更多的偏执狂的代码,为什么不洒它与. aligns...
所以

.thumb
.globl _start
_start:
    .word 0x20001000
    .word reset
    .word loop
    .word loop

.thumb_func
loop: b loop
.thumb_func
reset:
    mov r0,#1
    bl example_TBB
    b .


待定

.syntax unified
.thumb

.align
BranchTable_Byte:
    .byte ((Case0-Case0)/2)
    .byte ((Case1-Case0)/2)
    .byte ((Case2-Case0)/2)
    .byte ((Case3-Case0)/2)

.align
.global example_TBB
.thumb_func
example_TBB:
    and r0,#3
    adr.w r1, BranchTable_Byte
    tbb [r1, r0]

.align
Case0:
    mov r0, #1
    b endTBB
Case1:
    mov r0, #2
    b endTBB
Case2:
    mov r0, #3
    b endTBB
Case3:
    mov r0, #4
    b endTBB

.align
endTBB:
    bx lr


给予

Disassembly of section .text:

08000000 <_start>:
 8000000:   20001000    andcs   r1, r0, r0
 8000004:   08000013    stmdaeq r0, {r0, r1, r4}
 8000008:   08000011    stmdaeq r0, {r0, r4}
 800000c:   08000011    stmdaeq r0, {r0, r4}

08000010 <loop>:
 8000010:   e7fe        b.n 8000010 <loop>

08000012 <reset>:
 8000012:   2001        movs    r0, #1
 8000014:   f000 f804   bl  8000020 <example_TBB>
 8000018:   e7fe        b.n 8000018 <reset+0x6>
    ...

0800001c <BranchTable_Byte>:
 800001c:   09060300    stmdbeq r6, {r8, r9}

08000020 <example_TBB>:
 8000020:   f000 0003   and.w   r0, r0, #3
 8000024:   f2af 010c   subw    r1, pc, #12
 8000028:   e8d1 f000   tbb [r1, r0]

0800002c <Case0>:
 800002c:   f04f 0001   mov.w   r0, #1
 8000030:   e008        b.n 8000044 <endTBB>

08000032 <Case1>:
 8000032:   f04f 0002   mov.w   r0, #2
 8000036:   e005        b.n 8000044 <endTBB>

08000038 <Case2>:
 8000038:   f04f 0003   mov.w   r0, #3
 800003c:   e002        b.n 8000044 <endTBB>

0800003e <Case3>:
 800003e:   f04f 0004   mov.w   r0, #4
 8000042:   e7ff        b.n 8000044 <endTBB>

08000044 <endTBB>:
 8000044:   4770        bx  lr
 8000046:   46c0        nop         ; (mov r8, r8)


这是一个完整的程序,你可以在你的stm32上运行,并使用openocd停止并检查寄存器,当完成时,看看r0被设置为什么。你也可以这样做

.syntax unified
.thumb
.globl _start
_start:
    mov r0,#1
    bl example_TBB
    b .

.align
BranchTable_Byte:
    .byte ((Case0-Case0)/2)
    .byte ((Case1-Case0)/2)
    .byte ((Case2-Case0)/2)
    .byte ((Case3-Case0)/2)

.align
.global example_TBB
.thumb_func
example_TBB:
    and r0,#3
    adr.w r1, BranchTable_Byte
    tbb [r1, r0]

.align
Case0:
    mov r0, #1
    b endTBB
Case1:
    mov r0, #2
    b endTBB
Case2:
    mov r0, #3
    b endTBB
Case3:
    mov r0, #4
    b endTBB

.align
endTBB:
    bx lr


0x20000000处的ram链接

Disassembly of section .text:

20000000 <_start>:
20000000:   f04f 0001   mov.w   r0, #1
20000004:   f000 f804   bl  20000010 <example_TBB>
20000008:   e7fe        b.n 20000008 <_start+0x8>
2000000a:   46c0        nop         ; (mov r8, r8)

2000000c <BranchTable_Byte>:
2000000c:   09060300    stmdbeq r6, {r8, r9}

20000010 <example_TBB>:
20000010:   f000 0003   and.w   r0, r0, #3
20000014:   f2af 010c   subw    r1, pc, #12
20000018:   e8d1 f000   tbb [r1, r0]

2000001c <Case0>:
2000001c:   f04f 0001   mov.w   r0, #1
20000020:   e008        b.n 20000034 <endTBB>

20000022 <Case1>:
20000022:   f04f 0002   mov.w   r0, #2
20000026:   e005        b.n 20000034 <endTBB>

20000028 <Case2>:
20000028:   f04f 0003   mov.w   r0, #3
2000002c:   e002        b.n 20000034 <endTBB>

2000002e <Case3>:
2000002e:   f04f 0004   mov.w   r0, #4
20000032:   e7ff        b.n 20000034 <endTBB>

20000034 <endTBB>:
20000034:   4770        bx  lr
20000036:   46c0        nop


然后您可以加载它,运行它,停止并检查来自openocd的r0与您的STM32对话。

相关问题