Assembly 正确比较Arm机器代码和部件
我已经习惯于查看Arm上的汇编输出,并且认为浏览机器代码会很有趣,因为我有参考资料,可以很容易地看到我面前的所有内容。然而,我发现它与我期望看到的不符。这告诉我,我在某个地方犯了一点错误。也许有人能帮我。这是我的asm:Assembly 正确比较Arm机器代码和部件,assembly,arm,machine-code,Assembly,Arm,Machine Code,我已经习惯于查看Arm上的汇编输出,并且认为浏览机器代码会很有趣,因为我有参考资料,可以很容易地看到我面前的所有内容。然而,我发现它与我期望看到的不符。这告诉我,我在某个地方犯了一点错误。也许有人能帮我。这是我的asm: .arch armv8-m.main .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_at
.arch armv8-m.main
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "arm_test.c"
.text
.align 1
.global main
.syntax unified
.thumb
.thumb_func
.fpu softvfp
.type main, %function
main:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
push {r7}
sub sp, sp, #12
add r7, sp, #0
movs r3, #2
str r3, [r7, #4]
ldr r3, [r7, #4]
adds r3, r3, #13
str r3, [r7]
movs r3, #0
mov r0, r3
adds r7, r7, #12
mov sp, r7
@ sp needed
pop {r7}
bx lr
.size main, .-main
.ident "GCC: (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)"
下面是我的十六进制输出的开始(来自objcopy):
现在,由于arm默认为little endian,我希望第一个字节(0x47)是一个PUSH命令。但是0x47=0B010000111,这在我看来像是一条BLX指令。好吧,也许是从树枝开始的?如果这是真的,那么由于它是一条16位指令,下一条指令以0x46开始(我想是吧?)。现在0x46=0B010000110看起来像一条MOV(另一条16位指令)。。。但现在已经开始觉得这和ASM不符了。。。因此,由于我显然没有正确地看待这一点,有人能告诉我正确的开始位置吗?按照原样编写代码
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
注:
虽然你可能对英特尔和摩托罗拉有强烈的宗教立场。通过S3行,您可以获得完整的地址。底线是二进制的使用者,您必须匹配使用者使用的格式(mcu编程工具等)。当我制作自己的工具时,启用S3的srec是一个不错的选择。许多工具直接支持elf文件,因此通常不需要这些文件。其他支持原始二进制图像(-O二进制),因此同样不需要十六进制格式。YMMV
嗯,push{r7}很明显,在十六进制文件中只有一个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
所以我在ihex文件中没有看到您的(机器)代码
我们也没有看到每四个字节有很多0xEx字节,因此它可能不是全尺寸arm指令,尽管0x8000有点暗示这是作为全尺寸arm的linux二进制文件构建的
objcopy从对象生成十六进制类型文件(elf,不是链接的elf)
我们可以看到前面的0xb480和后面的0x4770。请注意,有些工具不会对十六进制文件进行字节交换,您可能会看到4770而不是7047,这没什么错,只是世界有时是这样的……十六进制文件的创建者和使用者都需要在这方面保持同步
编辑
非常小,但这是你想要做的事情
flash.s(向量表和引导)
flash.ld(链接器脚本)
建造
检查
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
几乎相同,这里也将其更改为-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:
8000000:20001000和CS r1、r0、r0
8000004:08000009 stmdaeq r0,{r0,r3}
08000008 :
8000008:f000 f802 bl 8000010
800000c:e7fe b.n 800000c
...
08000010 :
8000010:2005年电影r0,#5
8000012:4770 bx lr
0x08000000即使不是所有STM32(大约0x00200000),也是最多的,0x01000000是我所知道的ti(msp432s,可能是以前的发光显微镜)。如果我没记错的话,nxp可能是0x00000000。我不记得北欧或其他国家的情况。只需阅读文档即可。从技术上讲,所有这些都适用于使用0x00000000的小型二进制文件,但例如,NucleoBoards(stm32)不允许您在上面复制.bin文件,如果地址错误,则会出错。飞思卡尔或其他人对复制bin文件有更多的规定
你真的需要自己控制引导程序和链接器脚本,即使你从别人那里借用它。C库或hal库也将扮演一个角色,也许这就是您实际构建东西的方式,因为那里的makefiles正在使用hal/cmsis/other库中的引导和链接器脚本。出于某种原因,许多人会制作大量的链接器脚本,试图解决所有问题,如引导、C库(如果有的话)、芯片库、编译器库等,而不是精简和简单,让事情自然地工作。我建议从minimal开始,然后再变得更复杂,但这样就牺牲了供应商提供的C库和hal/随便什么库
当你进入纯金属时,清单上的一件事就是要么使用其他人的沙箱,要么掌握工具。看起来您希望掌握这些工具,这很好,上面的内容使它看起来很简单……如果您不使其复杂化,那么它仍然可以保持简单。按原样编写代码
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
注:
虽然你可能对英特尔和摩托罗拉有强烈的宗教立场。通过S3行,您可以获得完整的地址。底线是二进制的使用者,您必须匹配使用者使用的格式(mcu编程工具等)。当我制作自己的工具时,启用S3的srec是一个不错的选择。许多工具直接支持elf文件,因此通常不需要这些文件。其他支持原始二进制图像(-O二进制),因此同样不需要十六进制格式。YMMV
嗯,push{r7}很明显,在十六进制文件中只有一个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
所以我在ihex文件中没有看到您的(机器)代码
我们也没有看到每四个字节有很多0xEx字节,因此它可能不是全尺寸arm指令,尽管0x8000有点暗示这是作为全尺寸arm的linux二进制文件构建的
objcopy从对象生成十六进制类型文件(elf,不是链接的elf)
我们可以看到前面的0xb480和后面的0x4770。请注意,有些工具不会对十六进制文件进行字节交换,您可能会看到4770而不是7047,这没什么错,只是世界有时是这样的……十六进制文件的创建者和使用者都需要在这方面保持同步
编辑
非常小,但这是你想要做的事情
flash.s(向量表和引导)
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
int main ( void )
{
return(5);
}
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