手臂拇指中 Table 分支字节 (TBB) 的简单示例
Simple example of Table Branch Byte (TBB) in arm thumb
我想弄清楚 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,但是无论我玩了多长时间,我都会遇到无限循环 and/or 编译错误。
so.s
.globl _start
_start:
bl example_TBB
b .
tbb.s
.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
你去吧,有一个大问题。 table 中的 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
哇那更糟(它是一个地址而不是加载地址)
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.
你的 table 是 3 个字节深,为了对齐目的把它变成四个字节
.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]
您可能希望您的 table 位于您指定的 .text 中。如果你把它放在 .data 中,那么假设这是一个微控制器,你必须将它从闪存中获取到 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。
请注意,如果您 link 使用已编译的代码将其加入其中,您的编译器可能符合 arm 调用约定,该约定规定您不能在函数中修改 r4,您必须保留它。这就是为什么我修改了你的代码(我想你是在我为你把它移植到 gas 上时从我这里得到的?)
唉,我忘记了 so.s 中的 .thumb。很好,不是感兴趣的代码,不会在上面进行修复,但在下面你可能想在代码中添加更多偏执狂,为什么不在代码中添加 .aligns...
so.s
.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 .
tbb.s
.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
link 内存在 0x20000000
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 对话...
我想弄清楚 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,但是无论我玩了多长时间,我都会遇到无限循环 and/or 编译错误。
so.s
.globl _start
_start:
bl example_TBB
b .
tbb.s
.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
你去吧,有一个大问题。 table 中的 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
哇那更糟(它是一个地址而不是加载地址)
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.
你的 table 是 3 个字节深,为了对齐目的把它变成四个字节
.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]
您可能希望您的 table 位于您指定的 .text 中。如果你把它放在 .data 中,那么假设这是一个微控制器,你必须将它从闪存中获取到 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。
请注意,如果您 link 使用已编译的代码将其加入其中,您的编译器可能符合 arm 调用约定,该约定规定您不能在函数中修改 r4,您必须保留它。这就是为什么我修改了你的代码(我想你是在我为你把它移植到 gas 上时从我这里得到的?)
唉,我忘记了 so.s 中的 .thumb。很好,不是感兴趣的代码,不会在上面进行修复,但在下面你可能想在代码中添加更多偏执狂,为什么不在代码中添加 .aligns...
so.s
.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 .
tbb.s
.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
link 内存在 0x20000000
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 对话...