在 Cortex-M4 上编译和 运行 ARM 汇编二进制文件(在 QEMU 中模拟)
Compiling and running ARM assembly binary on Cortex-M4 (simulated in QEMU)
我使用以下过程在虚拟 QEMU 嵌入式系统 connex
上成功编译并执行了 ARM 二进制文件:
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=program.bin of=flash.bin bs=4096 conv=notrunc
qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null
在第四行中,我创建了一个归零的空磁盘,它代表闪存,在第五行中,我将我的二进制文件复制到闪存中。
所以这很有用,但它模拟了整个嵌入式系统,而我只想模拟 ARM 内核,例如 Cortex-M4。这就是为什么我试图只使用 qemu-arm
而不是 qemu-system-arm
。
所以我第一次尝试编译 运行 我的程序是这样的(第 1-3 行与上面相同):
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
qemu-arm -cpu cortex-m4 program.bin
这不起作用 - 它说:
Error while loading program.bin: Exec format error
所以我尝试像以前一样创建 Flash 图像(因为它有效):
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=program.bin of=flash.bin bs=4096 conv=notrunc
qemu-arm -cpu cortex-m4 flash.bin
我明白了:
Error while loading flash.bin: Permission denied
谁能帮我一下?使用 sudo
没有帮助。
qemu-arm 的目的不是"simulate just an ARM core"。它是 "run a single Linux binary",它期望您提供的二进制文件是 Linux 格式的 ELF 可执行文件。尝试用其他东西喂它是行不通的。
由于 Linux 假定 A-profile 内核,而不是 M-profile 内核,所以您在 qemu-arm 上使用 -cpu cortex-m4 所做的任何事情都只能靠运气,而不是故意的。 (我们不禁用那些 CPU 类型,因为有一些 GCC 测试用例场景使用半主机,我们不想故意破坏这种工作。但这些工作与运气一样多其他任何东西。)
与微控制器构建相比,您需要一个入口点(并且它是 ram)。
start.s
.thumb
.thumb_func
.global _start
_start:
@mov r0,=0x10000
@mov sp,r0
bl notmain
mov r7,#0x1
mov r0,#0
swi #0
.word 0xFFFFFFFF
b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.thumb_func
.globl dummy
dummy:
bx lr
.thumb_func
.globl write
write:
push {r7,lr}
mov r7,#0x04
swi 0
pop {r7,pc}
b .
.end
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
void write ( unsigned int, char *, unsigned int );
int notmain ( void )
{
//unsigned int ra;
//for(ra=0;ra<1000;ra++) dummy(ra);
write(1,"Hello\n",6);
return(0);
}
hello.ld
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x00010000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
建设
arm-none-eabi-as --warn --fatal-warnings start.s -o start.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -o notmain.elf -T hello.ld start.o notmain.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
运行
qemu-arm -d in_asm,cpu,cpu_reset -D hello -cpu cortex-m4 notmain.elf
Hello
转储日志
cat hello
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000000 -Z-- A usr26
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000010 -Z-- A usr32
Reserved 0xf7000000 bytes of guest address space
host mmap_min_addr=0x10000
guest_base 0x7f4347fb4000
start end size prot
00010000-00011000 00001000 r-x
f67ff000-f6800000 00001000 ---
f6800000-f7000000 00800000 rw-
start_brk 0x00000000
end_code 0x00010044
start_code 0x00010000
start_data 0x00010044
end_data 0x00010044
start_stack 0xf6fff350
brk 0x00010044
entry 0x00010001
----------------
IN:
0x00010000: f000 f810 bl 0x10024
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010000
PSR=00000030 ---- T usr32
----------------
IN: notmain
0x00010024: b508 push {r3, lr}
0x00010026: 2001 movs r0, #1
0x00010028: 4903 ldr r1, [pc, #12] (0x10038)
0x0001002a: 2206 movs r2, #6
0x0001002c: f7ff fff5 bl 0x1001a
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00010005 R15=00010024
PSR=00000030 ---- T usr32
----------------
IN:
0x0001001a: b580 push {r7, lr}
0x0001001c: 2704 movs r7, #4
0x0001001e: df00 svc 0
R00=00000001 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff348 R14=00010031 R15=0001001a
PSR=00000030 ---- T usr32
----------------
IN:
0x00010020: bd80 pop {r7, pc}
R00=00000006 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000004
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff340 R14=00010031 R15=00010020
PSR=00000030 ---- T usr32
----------------
IN: notmain
0x00010030: 2000 movs r0, #0
0x00010032: bc08 pop {r3}
0x00010034: bc02 pop {r1}
0x00010036: 4708 bx r1
R00=00000006 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff348 R14=00010031 R15=00010030
PSR=00000030 ---- T usr32
----------------
IN:
0x00010004: 2701 movs r7, #1
0x00010006: 2000 movs r0, #0
0x00010008: df00 svc 0
R00=00000000 R01=00010005 R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00010031 R15=00010004
PSR=40000030 -Z-- T usr32
如果你触摸堆栈指针,它会变得不快乐,所以不要...
感谢您指出这个程序,当时并不知道它,会玩得开心...
编辑
抱歉,您只是想组装。
start.s
.thumb
.thumb_func
.global _start
_start:
mov r4,#10
top:
nop
sub r4,#1
bne top
mov r7,#0x1
mov r0,#0
swi #0
.word 0xFFFFFFFF
b .
.end
上面的链接描述文件
建设
arm-none-eabi-as --warn --fatal-warnings start.s -o start.o
arm-none-eabi-ld -o notmain.elf -T hello.ld start.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
运行
qemu-arm -d in_asm,cpu,cpu_reset -D hello -cpu cortex-m4 notmain.elf
转储日志
cat hello
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000000 -Z-- A usr26
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000010 -Z-- A usr32
Reserved 0xf7000000 bytes of guest address space
host mmap_min_addr=0x10000
guest_base 0x7f36110fc000
start end size prot
00010000-00011000 00001000 r-x
f67ff000-f6800000 00001000 ---
f6800000-f7000000 00800000 rw-
start_brk 0x00000000
end_code 0x00010014
start_code 0x00010000
start_data 0x00010014
end_data 0x00010014
start_stack 0xf6fff350
brk 0x00010014
entry 0x00010001
----------------
IN:
0x00010000: 240a movs r4, #10
0x00010002: 46c0 nop (mov r8, r8)
0x00010004: 3c01 subs r4, #1
0x00010006: d1fc bne.n 0x10002
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010000
PSR=00000030 ---- T usr32
----------------
IN:
0x00010002: 46c0 nop (mov r8, r8)
0x00010004: 3c01 subs r4, #1
0x00010006: d1fc bne.n 0x10002
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000009 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010002
PSR=20000030 --C- T usr32
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000008 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010002
PSR=20000030 --C- T usr32
----------------
IN:
0x00010008: 2701 movs r7, #1
0x0001000a: 2000 movs r0, #0
0x0001000c: df00 svc 0
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010008
PSR=60000030 -ZC- T usr32
我使用以下过程在虚拟 QEMU 嵌入式系统 connex
上成功编译并执行了 ARM 二进制文件:
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=program.bin of=flash.bin bs=4096 conv=notrunc
qemu-system-arm -M connex -pflash flash.bin -nographic -serial /dev/null
在第四行中,我创建了一个归零的空磁盘,它代表闪存,在第五行中,我将我的二进制文件复制到闪存中。
所以这很有用,但它模拟了整个嵌入式系统,而我只想模拟 ARM 内核,例如 Cortex-M4。这就是为什么我试图只使用 qemu-arm
而不是 qemu-system-arm
。
所以我第一次尝试编译 运行 我的程序是这样的(第 1-3 行与上面相同):
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
qemu-arm -cpu cortex-m4 program.bin
这不起作用 - 它说:
Error while loading program.bin: Exec format error
所以我尝试像以前一样创建 Flash 图像(因为它有效):
arm-none-eabi-as -o program.o program.s
arm-none-eabi-ld -Ttext=0x0 -o program.elf program.o
arm-none-eabi-objcopy -O binary program.elf program.bin
dd if=/dev/zero of=flash.bin bs=4096 count=4096
dd if=program.bin of=flash.bin bs=4096 conv=notrunc
qemu-arm -cpu cortex-m4 flash.bin
我明白了:
Error while loading flash.bin: Permission denied
谁能帮我一下?使用 sudo
没有帮助。
qemu-arm 的目的不是"simulate just an ARM core"。它是 "run a single Linux binary",它期望您提供的二进制文件是 Linux 格式的 ELF 可执行文件。尝试用其他东西喂它是行不通的。
由于 Linux 假定 A-profile 内核,而不是 M-profile 内核,所以您在 qemu-arm 上使用 -cpu cortex-m4 所做的任何事情都只能靠运气,而不是故意的。 (我们不禁用那些 CPU 类型,因为有一些 GCC 测试用例场景使用半主机,我们不想故意破坏这种工作。但这些工作与运气一样多其他任何东西。)
与微控制器构建相比,您需要一个入口点(并且它是 ram)。
start.s
.thumb
.thumb_func
.global _start
_start:
@mov r0,=0x10000
@mov sp,r0
bl notmain
mov r7,#0x1
mov r0,#0
swi #0
.word 0xFFFFFFFF
b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.thumb_func
.globl dummy
dummy:
bx lr
.thumb_func
.globl write
write:
push {r7,lr}
mov r7,#0x04
swi 0
pop {r7,pc}
b .
.end
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
void write ( unsigned int, char *, unsigned int );
int notmain ( void )
{
//unsigned int ra;
//for(ra=0;ra<1000;ra++) dummy(ra);
write(1,"Hello\n",6);
return(0);
}
hello.ld
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x00010000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
建设
arm-none-eabi-as --warn --fatal-warnings start.s -o start.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -o notmain.elf -T hello.ld start.o notmain.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
运行
qemu-arm -d in_asm,cpu,cpu_reset -D hello -cpu cortex-m4 notmain.elf
Hello
转储日志
cat hello
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000000 -Z-- A usr26
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000010 -Z-- A usr32
Reserved 0xf7000000 bytes of guest address space
host mmap_min_addr=0x10000
guest_base 0x7f4347fb4000
start end size prot
00010000-00011000 00001000 r-x
f67ff000-f6800000 00001000 ---
f6800000-f7000000 00800000 rw-
start_brk 0x00000000
end_code 0x00010044
start_code 0x00010000
start_data 0x00010044
end_data 0x00010044
start_stack 0xf6fff350
brk 0x00010044
entry 0x00010001
----------------
IN:
0x00010000: f000 f810 bl 0x10024
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010000
PSR=00000030 ---- T usr32
----------------
IN: notmain
0x00010024: b508 push {r3, lr}
0x00010026: 2001 movs r0, #1
0x00010028: 4903 ldr r1, [pc, #12] (0x10038)
0x0001002a: 2206 movs r2, #6
0x0001002c: f7ff fff5 bl 0x1001a
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00010005 R15=00010024
PSR=00000030 ---- T usr32
----------------
IN:
0x0001001a: b580 push {r7, lr}
0x0001001c: 2704 movs r7, #4
0x0001001e: df00 svc 0
R00=00000001 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff348 R14=00010031 R15=0001001a
PSR=00000030 ---- T usr32
----------------
IN:
0x00010020: bd80 pop {r7, pc}
R00=00000006 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000004
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff340 R14=00010031 R15=00010020
PSR=00000030 ---- T usr32
----------------
IN: notmain
0x00010030: 2000 movs r0, #0
0x00010032: bc08 pop {r3}
0x00010034: bc02 pop {r1}
0x00010036: 4708 bx r1
R00=00000006 R01=0001003c R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff348 R14=00010031 R15=00010030
PSR=00000030 ---- T usr32
----------------
IN:
0x00010004: 2701 movs r7, #1
0x00010006: 2000 movs r0, #0
0x00010008: df00 svc 0
R00=00000000 R01=00010005 R02=00000006 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010044 R11=00000000
R12=00000000 R13=f6fff350 R14=00010031 R15=00010004
PSR=40000030 -Z-- T usr32
如果你触摸堆栈指针,它会变得不快乐,所以不要...
感谢您指出这个程序,当时并不知道它,会玩得开心...
编辑
抱歉,您只是想组装。
start.s
.thumb
.thumb_func
.global _start
_start:
mov r4,#10
top:
nop
sub r4,#1
bne top
mov r7,#0x1
mov r0,#0
swi #0
.word 0xFFFFFFFF
b .
.end
上面的链接描述文件
建设
arm-none-eabi-as --warn --fatal-warnings start.s -o start.o
arm-none-eabi-ld -o notmain.elf -T hello.ld start.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
运行
qemu-arm -d in_asm,cpu,cpu_reset -D hello -cpu cortex-m4 notmain.elf
转储日志
cat hello
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000000 -Z-- A usr26
CPU Reset (CPU 0)
R00=00000000 R01=00000000 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=00000000 R14=00000000 R15=00000000
PSR=40000010 -Z-- A usr32
Reserved 0xf7000000 bytes of guest address space
host mmap_min_addr=0x10000
guest_base 0x7f36110fc000
start end size prot
00010000-00011000 00001000 r-x
f67ff000-f6800000 00001000 ---
f6800000-f7000000 00800000 rw-
start_brk 0x00000000
end_code 0x00010014
start_code 0x00010000
start_data 0x00010014
end_data 0x00010014
start_stack 0xf6fff350
brk 0x00010014
entry 0x00010001
----------------
IN:
0x00010000: 240a movs r4, #10
0x00010002: 46c0 nop (mov r8, r8)
0x00010004: 3c01 subs r4, #1
0x00010006: d1fc bne.n 0x10002
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010000
PSR=00000030 ---- T usr32
----------------
IN:
0x00010002: 46c0 nop (mov r8, r8)
0x00010004: 3c01 subs r4, #1
0x00010006: d1fc bne.n 0x10002
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000009 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010002
PSR=20000030 --C- T usr32
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000008 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010002
PSR=20000030 --C- T usr32
----------------
IN:
0x00010008: 2701 movs r7, #1
0x0001000a: 2000 movs r0, #0
0x0001000c: df00 svc 0
R00=00000000 R01=f6fff4c2 R02=00000000 R03=00000000
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00010014 R11=00000000
R12=00000000 R13=f6fff350 R14=00000000 R15=00010008
PSR=60000030 -ZC- T usr32