按原样处理您的代码。
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -d so.o
so.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
0: b480 push {r7}
2: b083 sub sp, #12
4: af00 add r7, sp, #0
6: 2302 movs r3, #2
8: 607b str r3, [r7, #4]
a: 687b ldr r3, [r7, #4]
c: 330d adds r3, #13
e: 603b str r3, [r7, #0]
10: 2300 movs r3, #0
12: 4618 mov r0, r3
14: 370c adds r7, #12
16: 46bd mov sp, r7
18: bc80 pop {r7}
1a: 4770 bx lr
对于 armv8-m,您的 hex 文件有点腥味。 0x8000 的低地址?同样,这是对象还是完整的二进制文件?十六进制文件仅作为一个完整的二进制文件才有意义,其中反汇编对象不是 100% 熟,而是比汇编语言本身更熟。
:0C800000F8B500BFF8BC08BC9E467047F5
:10800C0008B50021044600F0F5F8044B1868C36B62
:10801C0003B19847204600F0C7F900BFC4830000A5
注意:
$(ARMGNU)-objcopy --srec-forceS3 so.elf -O srec so.srec
虽然您可能对英特尔与摩托罗拉有强烈的宗教立场。使用 S3 行,您可以获得完整的地址。底线是二进制文件的消费者,您必须匹配消费者使用的格式(MCU 编程工具等)。当我在启用 S3 的情况下制作自己的工具时,srec 是可行的方法。许多工具直接支持 elf 文件,因此通常不需要这些文件。其他支持原始二进制图像(-O 二进制),因此不需要十六进制格式。 YMMV
嗯,push {r7} 很清楚,你的 hex 文件中只有一个 b4,它是一个校验和。
这一行有一个bx lr
:10802C00024B13B1024800F047B9 7047 0000000042
所以第一次尝试是
.thumb
.inst.n 0x4B02
.inst.n 0xB113
.inst.n 0x4802
.inst.n 0xF000
.inst.n 0xB947
.inst.n 0x4770
.inst.n 0x0000
.inst.n 0x0000
给了
00000000 <.text>:
0: 4b02 ldr r3, [pc, #8] ; (c <.text+0xc>)
2: b113 cbz r3, a <.text+0xa>
4: 4802 ldr r0, [pc, #8] ; (10 <.text+0x10>)
6: f000 b947 b.w 298 <.text+0x298>
a: 4770 bx lr
c: 0000 movs r0, r0
因为有一个 b.w 被拆卸,所以没有必要更进一步。你只有一个 bx lr,所以
哦,等一下,第一行也有一个
0: b5f8 push {r3, r4, r5, r6, r7, lr}
2: bf00 nop
4: bcf8 pop {r3, r4, r5, r6, r7}
6: bc08 pop {r3}
8: 469e mov lr, r3
a: 4770 bx lr
所以我在 ihex 文件中看不到您的(机器)代码。
我们也没有看到每四个字节有很多 0xEx 字节,所以它可能不是全尺寸的 arm 指令,即使 0x8000 有点暗示这是作为全尺寸 arm 的 linux 二进制文件构建的。
objcopy 从对象(elf,不是链接的elf)制作十六进制类型文件
S00A00006F75742E7478740F
S3150000000080B483B000AF02237B607B680D333B6016
S31100000010002318460C37BD4680BC704724
S70500000000FA
:1000000080B483B000AF02237B607B680D333B601C
:0C001000002318460C37BD4680BC70472A
:00000001FF
我们可以看到前面的 0xb480 和末尾的 0x4770。请注意,某些工具不会对十六进制文件进行字节交换,您可能会看到 4770 而不是 7047,这并没有错,只是世界有时是这样的……十六进制文件的创建者和使用者都需要同步这个。
编辑
极少,但这是您想要做的事情
flash.s(向量表和引导程序)
.thumb
.word 0x20001000
.word reset
.thumb_func
reset:
bl main
b .
flash.ld(链接器脚本)
MEMORY
{
bob : ORIGIN = 0x08000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.hello : { *(.text*) } > bob
.world : { *(.data*) } > ted
}
构建
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m23 flash.s -o flash.o
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m23 -mthumb -c so.s -o so.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o so.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy --srec-forceS3 so.elf -O srec so.srec
arm-none-eabi-objcopy -O binary so.elf so.bin
检查
08000000 <reset-0x8>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset>:
8000008: f000 f801 bl 800000e <main>
800000c: e7fe b.n 800000c <reset+0x4>
0800000e <main>:
800000e: b480 push {r7}
8000010: b083 sub sp, #12
8000012: af00 add r7, sp, #0
8000014: 2302 movs r3, #2
8000016: 607b str r3, [r7, #4]
8000018: 687b ldr r3, [r7, #4]
800001a: 330d adds r3, #13
800001c: 603b str r3, [r7, #0]
800001e: 2300 movs r3, #0
8000020: 4618 mov r0, r3
8000022: 370c adds r7, #12
8000024: 46bd mov sp, r7
8000026: bc80 pop {r7}
8000028: 4770 bx lr
(naturally you can make an ihex or whatever other format you want)
S00A0000736F2E7372656338
S31508000000001000200900000800F001F8FEE780B49F
S3150800001083B000AF02237B607B680D333B6000230F
S30F0800002018460C37BD4680BC704731
S70500000000FA
hexdump -C so.bin
00000000 00 10 00 20 09 00 00 08 00 f0 01 f8 fe e7 80 b4 |... ............|
00000010 83 b0 00 af 02 23 7b 60 7b 68 0d 33 3b 60 00 23 |.....#{`{h.3;`.#|
00000020 18 46 0c 37 bd 46 80 bc 70 47 |.F.7.F..pG|
0000002a
向量表在正确的位置并且看起来不错(处理程序地址 ORRed 为 1),因此它不会在启动时挂起。不知道你有哪个特定的核心,我只拿了一个,所以我可以使用 -mcpu ...如果你选择 cortex-m0,它到目前为止可以在所有的 cortex-ms 上工作,有时可能会更慢,但会起作用。更大的错误是将 armv7-m 的东西剪切并粘贴到 armv6-m 或一些 armv8-ms 上,这将不起作用,因此还要检查反汇编以查看其中是否有任何 armv7-m 指令,这会很好地让你进入处理程序以及(因为向量表是错误的)
大多数人都希望支持 .data 和 .bss 并对其进行初始化,这使得链接器脚本和引导程序更加复杂。
EDIT2
如果你想半直接使用C(gcc为你调用汇编器)
so.c
int main ( void )
{
return(5);
}
几乎一样,这里也改成-m33。
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m33 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m33 -mthumb -c so.c -o so.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o so.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy -O binary so.elf so.bin
给予
08000000 <reset-0x8>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset>:
8000008: f000 f802 bl 8000010 <main>
800000c: e7fe b.n 800000c <reset+0x4>
...
08000010 <main>:
8000010: 2005 movs r0, #5
8000012: 4770 bx lr
0x08000000 是 stm32 的大部分(如果不是全部的话)(一些 0x00200000),0x01000000 是我所知道的 ti(msp432 和以前的 luminary micros)。如果我没记错的话,nxp 可能是 0x00000000。我不记得北欧或其他人。只需阅读文档。从技术上讲,所有这些都应该适用于使用 0x00000000 的小型二进制文件,但例如核板(stm32)不允许您将 .bin 文件复制到它上面,如果地址错误,则会出错。飞思卡尔或某人对复制bin文件的事情有更多的规定。
您确实需要自己控制引导程序和链接器脚本,即使您是从别人那里借来的。 C 库或 hal 库也将发挥作用,也许这就是您实际构建东西的方式,因为那里的 makefile 使用 hal/cmsis/other 库中的引导程序和链接器脚本。出于某种原因,许多人会制作繁重的链接器脚本,试图解决所有问题,引导程序、C 库(如果有的话)、芯片库、编译器库等。而不是精益求精,让事情自然而然地工作。我建议从最小化开始,然后变得更复杂,但是你会牺牲一个 C 库和供应商提供的 hal/任何库。
当您使用裸机时,清单中的一件事就是使用别人的沙箱或掌握工具。看起来你想掌握工具,那很好,上面的东西看起来很容易......如果你不把它复杂化,那么它仍然很容易。