Arm 引导加载程序和内核可视化错误

问题描述 投票:0回答:1

我想为ARM系统制作微型操作系统。我有这个引导加载程序:

.global _start

.text
_start:
    /* Set up the stack */
    ldr sp, =stack_top

    /* Call the kernel entry point */
    bl kernel_entry

    /* Infinite loop */
hang:
    b hang

.bss
.space 1024
stack_top:

这里内核:

void kernel_entry(void) {
    const char *msg = "Hello, ARM world!\n";
    char *uart = (char *)0x101f1000;  // UART base address for ARM

    while (*msg) {
        *uart = *msg++;
    }

    while (1);
}

我写了make文件来编译:

all: bootloader.bin

bootloader.bin: bootloader.elf
    arm-none-eabi-objcopy -O binary bootloader.elf bootloader.bin

bootloader.elf: bootloader.o kernel.o
    arm-none-eabi-ld -Ttext 0x8000 -o bootloader.elf bootloader.o kernel.o

kernel.o: kernel.c
    arm-none-eabi-gcc -ffreestanding -nostdlib -c -o kernel.o kernel.c

bootloader.o: bootloader.s
    arm-none-eabi-as -o bootloader.o bootloader.s

run: bootloader.bin kernel.img
    ./run.sh

clean:
    rm -f *.o *.elf *.bin

我使用命令来运行 qemu 子系统:

qemu-system-arm -M genericpb -m 128M -kernel "C:/Users/Ukraine/Documents/FlowyOS/bootloader.bin" -initrd "C:/Users/Ukraine/Documents/FlowyOS/kernel.img" - d 整数

我有“错误”,因为在 wm 中我没有看到

hello world
文本:

enter image description here

有什么可能是错误的以及如何修复它吗?

c assembly arm qemu
1个回答
0
投票

带子

.globl _start
_start:
    mov sp,#0x20000
    bl notmain
hang:
    b hang

.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

notmain.c

void PUT32 ( unsigned int, unsigned int );
int notmain ( void )
{
    unsigned int ra;
    for(ra=0;;ra++)
    {
        ra&=7;
        PUT32(0x101f1000,0x30+ra);
    }
    return(0);
}

内存映射

/* memmap */
MEMORY
{
    ram  : ORIGIN = 0x00000000, LENGTH = 32K
}

SECTIONS
{
   .text : { *(.text*) } > ram
   .bss  : { *(.text*) } > ram
}

构建

arm-none-eabi-as --warn --fatal-warnings -march=armv5t strap.s -o strap.o
arm-none-eabi-gcc -c -Wall -O2 -nostdlib -nostartfiles -ffreestanding -march=armv5t notmain.c -o notmain.o
arm-none-eabi-ld strap.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf -O binary notmain.bin

检查

00000000 <_start>:
   0:   e3a0d802    mov sp, #131072 ; 0x20000
   4:   eb000002    bl  14 <notmain>

00000008 <hang>:
   8:   eafffffe    b   8 <hang>

0000000c <PUT32>:
   c:   e5801000    str r1, [r0]
  10:   e12fff1e    bx  lr

00000014 <notmain>:
  14:   e92d4070    push    {r4, r5, r6, lr}
  18:   e3a04000    mov r4, #0
  1c:   e59f5014    ldr r5, [pc, #20]   ; 38 <notmain+0x24>
  20:   e2044007    and r4, r4, #7
  24:   e2841030    add r1, r4, #48 ; 0x30
  28:   e1a00005    mov r0, r5
  2c:   ebfffff6    bl  c <PUT32>
  30:   e2844001    add r4, r4, #1
  34:   eafffff9    b   20 <notmain+0xc>
  38:   101f1000    andsne  r1, pc, r0

要作为垃圾箱运行,需要前面的入口点。

跑步的一种方法是

qemu-system-arm -M versatilepb -m 128M -nographic -kernel notmain.bin

会喷出来

01234567012345670123456701234567012345670...

停止/退出 ctrl-a 然后 x

或者

qemu-system-arm -M versatilepb -m 128M -kernel notmain.bin

然后 ctrl-alt-3 (当然是 Linux,如果是 Windows 我不知道怎么做,但可能)进入串行控制台。

这就是立场独立,无需尝试。 让我们看看地址空间发生了什么。

.globl GETPC
GETPC:
    mov r0,pc
    bx lr

hexstring(GETPC());

给出 0x10054(未显示不同的二进制文件)。 所以基于 0x10000(今天我的机器上不是 0x8000)。

所以可以试试这个

MEMORY
{
    ram  : ORIGIN = 0x00010000, LENGTH = 32K
}

SECTIONS
{
   .text : { *(.text*) } > ram
   .bss  : { *(.text*) } > ram
}

Disassembly of section .text:

00010000 <_start>:
   10000:   e3a0d802    mov sp, #131072 ; 0x20000
   10004:   eb000002    bl  10014 <notmain>

00010008 <hang>:
   10008:   eafffffe    b   10008 <hang>

0001000c <PUT32>:
   1000c:   e5801000    str r1, [r0]
   10010:   e12fff1e    bx  lr

00010014 <notmain>:
   10014:   e92d4070    push    {r4, r5, r6, lr}
   10018:   e3a04000    mov r4, #0
   1001c:   e59f5014    ldr r5, [pc, #20]   ; 10038 <notmain+0x24>
   10020:   e2044007    and r4, r4, #7
   10024:   e2841030    add r1, r4, #48 ; 0x30
   10028:   e1a00005    mov r0, r5
   1002c:   ebfffff6    bl  1000c <PUT32>
   10030:   e2844001    add r4, r4, #1
   10034:   eafffff9    b   10020 <notmain+0xc>
   10038:   101f1000    andsne  r1, pc, r0

并运行 elf 文件

qemu-system-arm -M versatilepb -m 128M -nographic -kernel notmain.elf

效果很好。

void notmain ( void )
{
    const char *msg = "Hello, ARM world!\n";
    char *uart = (char *)0x101f1000;  // UART base address for ARM

    while (*msg) {
        *uart = *msg++;
    }
}

由于语言原因,这不应该起作用的原因有很多,但是......

00010014 <notmain>:
   10014:   e3a03048    mov r3, #72 ; 0x48
   10018:   e59f2014    ldr r2, [pc, #20]   ; 10034 <notmain+0x20>
   1001c:   e59f1014    ldr r1, [pc, #20]   ; 10038 <notmain+0x24>
   10020:   e5c13000    strb    r3, [r1]
   10024:   e5f23001    ldrb    r3, [r2, #1]!
   10028:   e3530000    cmp r3, #0
   1002c:   1afffffb    bne 10020 <notmain+0xc>
   10030:   e12fff1e    bx  lr
   10034:   0001003c    andeq   r0, r1, ip, lsr r0
   10038:   101f1000    andsne  r1, pc, r0

r1 指向串口,r2 指向字符串。

它创建了一个 .rodata 部分,即使我没有指定。

Disassembly of section .rodata.str1.4:

0001003c <.rodata.str1.4>:
   1003c:   6c6c6548    cfstr64vs   mvdx6, [ip], #-288  ; 0xfffffee0
   10040:   41202c6f            ; <UNDEFINED> instruction: 0x41202c6f
   10044:   77204d52            ; <UNDEFINED> instruction: 0x77204d52
   10048:   646c726f    strbtvs r7, [ip], #-623 ; 0xfffffd91
   1004c:   Address 0x000000000001004c is out of bounds.

qemu-system-arm -M versatilepb -m 128M -nographic -kernel notmain.elf
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
Hello, ARM world!
QEMU: Terminated

您需要一个用于 uart 指针的易失性,或其他解决方案。 想要控制链接描述文件。

-Ttext 0x8000 将采用一个/常用/默认链接器脚本,并基本上通过更改 .text 所在的位置来修改它。 您将只想控制整个链接而不是这样做,您可以看到链接器脚本是多么微不足道,尽管几乎每个人都严重过度复杂化了他们的链接器脚本。

如果我使用打印数字的二进制文件并执行此操作

ENTRY(_start)
MEMORY
{
    ram  : ORIGIN = 0x0002000, LENGTH = 32K
}

SECTIONS
{
   .text : { *(.text*) } > ram
   .bss  : { *(.text*) } > ram
}

告诉链接器将入口点放入二进制文件中(而不是内存映像中第一个内容的默认值)。 和小精灵一起奔跑。

00002054 

你的 0x8000 和其他内核精灵图像也会这样做,只是为了强制进入点......

b .
b .
b .
b .
b .

.globl _start
_start:
reset:
    mov sp,#0x10000
    bl notmain
hang:
    b hang


Disassembly of section .text:

00002000 <_start-0x14>:
    2000:   eafffffe    b   2000 <_start-0x14>
    2004:   eafffffe    b   2004 <_start-0x10>
    2008:   eafffffe    b   2008 <_start-0xc>
    200c:   eafffffe    b   200c <_start-0x8>
    2010:   eafffffe    b   2010 <_start-0x4>

00002014 <_start>:
    2014:   e3a0d801    mov sp, #65536  ; 0x10000
    2018:   eb000026    bl  20b8 <notmain>

0000201c <hang>:
    201c:   eafffffe    b   201c <hang>

00002020 <GETPC>:
    2020:   e1a0000f    mov r0, pc
    2024:   e12fff1e    bx  lr

00002028 

所以它实际上是在使用入口点,而不是简单地从头开始执行。

您可能根本没有查看控制台输出屏幕。 如果没有看到二进制文件的反汇编/转储,很难判断为什么你的二进制文件不起作用。 想要启动裸机,请在尝试运行之前检查反汇编和转储二进制文件。

© www.soinside.com 2019 - 2024. All rights reserved.