Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Themen - RW2003

Seiten: [1]
1
Lowlevel-Coding / Probleme mit aarch64
« am: 11. July 2021, 12:17 »
Hallo allerseits.
Ich wollte mich mal etwas an arm versuchen und habe mich an das ARM-OS-Dev Tutorial aus dem Wiki gehalten.
Naja, mit ein paar Änderungen, da ich nciht für 32-bit sondern für armv8 bzw. aarch64 entwickeln möchte.

Nun ja, der kernel wird kompiliert und von qemu gestartet. Ausgaben auf den Bildschirm bzw. seriellen Schnittstelle funktionieren halbwegs.
Es scheint Probleme mit den Variablen bzw. Speicherzugriffen zu geben...

Einzelne Zeichen auszugeben funktioniert.
Wenn ich das aber in einer Schleife machen möchte, dann tut er sich mit der Zählervariablen schwer...
Im ersten Durchlauf funktioniert es. Dann wird die Schleife aber nciht mehr fortgeführt, weil s == 0 sei...
irgendwie verkackt er hier den Zugriff über die Variable i.
Wenn man die Zeichen per Zahl, also s[1], s[2], etc. ausgibt dann bekommt man auch das Zeichen und kein '\0'.
Gleiches gilt auch, wenn man den Wert in der Schleife auf einen konkreten Wert setzt: z.b. i = 4;.
Das Inkrementieren von i hingegen scheint einfach nciht zu funktionieren. Danach bekommt er aus s == '\0' raus und beendet die Schleife.

Vllt. könnt ihr mir helfen und mir meine Fehler aufzeigen; und mir sagen ob ich die Adresse für den Stack richtig zugewiesen habe, oder dort vllt. das Problem liegt...


Da man hier leider keine zip archive hochladen kann, gibt es hier meine Dateien als Text.

Start.S
/* Init ist eine Funktion aus init.c */
.extern init
.org 0x0

/* Hier befinden sich die Einsprungspunkte für Exceptions, der erste wird beim
   Reset aufgerufen. Da die Einsprungspunkte nur vier Byte voneinander entfernt
   sind, bleibt jeweils nur Platz für einen Opcode – und damit springen wir
   woanders hin. */
b       _start
/* Hier folgen jetzt die Einsprungspunkte für Undefined Instruction, SWI,
   Prefetch Abort, Data Abort, eine bisher reservierte Exception, IRQ und FIQ.
   Da all diese Exceptions noch nicht behandelt werden können, legen wir dort
   einfach Endlosschleifen hin. */
b       end
b       end
b       end
b       end
b       end
b       end
b       end

.global start
_start:
/* Stack initialisieren  */
mov x0, #kernel_stack
mov     sp, x0


sub  sp, sp, #8
mov  x0, #17
str  x0, [sp]

/* C-Code aufrufen */
bl      init

/* Falls wir jemals aus init zurueckkommen sollten, gehen wir in eine
   Endlosschleife */
b       end

end:
ldr x0, =0x84000008
hvc #0


/* Enthält die Adresse des Kernelstacks */
kernel_stack_addr:
.8byte kernel_stack

/* 8 kB Stack für den Kernel. Das Label steht hinter dem freien Speicher,
   weil der Stack nach unten wächst */
.section .bss
.space 8192
kernel_stack:


init.c
// Data register of first UART (PL011)
volatile unsigned int * const UART0_DR = (unsigned int *) 0x09000000;


// Stop guest so Qemu terminates
void system_off() {
__asm__("ldr x0, =0x84000008;hvc #0;");
}


void print(const char *s) {
    short int i = 0;
    while(s[i] != '\0' || i <5){
        //*UART0_DR = 48 + i;

        *UART0_DR = s[i];

        *UART0_DR = 48 + i;
        *UART0_DR = 48 + i;
       
        *UART0_DR = s[i];
        *UART0_DR = s[i + 1];

        i = i + 1;

        *UART0_DR = 48 + i;
        *UART0_DR = '\n';
    }
}

void init(int value) {
   const char *hw = "Hello World!\n";
   char text[25];

   *UART0_DR = (48 + value);
   *UART0_DR = '\n';
   *UART0_DR = '\n';

   print(hw);
   //print(text);
   print("U");

   system_off();
}


makefile
SRCS = $(shell find -name '*.[cS]')
OBJS = $(addsuffix .o,$(basename $(SRCS)))

CC = aarch64-linux-gnu-gcc
LD = aarch64-linux-gnu-ld

ASFLAGS = -march=armv8-a
CFLAGS = -march=armv8-a -O3 -ffreestanding -nostartfiles -nostdinc -nodefaultlibs -Wall -Wextra -fno-stack-protector
LDFLAGS = -e 0x00000000 -T link.ld

kernel: $(OBJS)
$(LD) $(LDFLAGS) -o $@ $^

%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $^

%.o: %.S
$(CC) $(ASFLAGS) -c -o $@ $^

clean:
rm $(OBJS)

.PHONY: clean


link.ld
/* Wir nehmen einen ARMv8-Prozessor an */
OUTPUT_ARCH("aarch64")
/* Diese Datei muss im Speicher nach 0x00000000 geladen werden */
STARTUP(start.o)

/*
 * Hier wird festgelegt, in welcher Reihenfolge welche Sektionen in die Binary
 * geschrieben werden sollen
 */
SECTIONS
{
    /* Die Standardsektionen einfach hintereinander weg ab 0x00000000 einbinden. */
    .text 0x00000000 : AT(0x00000000) {
        *(.text)
    }
    .data ALIGN(4096) : {
        *(.data)
    }
    .rodata ALIGN(4096) : {
        *(.rodata)
    }
    .bss ALIGN(4096) : {
        *(.bss)
    }
}


Aso.. wenn ich hier schon dabei bin zu posten..
vllt. kann mir jemand das .global in Assembler erklären.
Ich wollte die system_off(); funktion in C benutzen und hatte sie davor in der Assemblerdatei wie folgt stehen:
.global _system_off
_system_off:
ldr x0, =0x84000008
hvc #0
In C hab ich das als extern void _system_off(); deklariert.
Damit konnte der Linker aber nichts anfangen, und warf mir doppelte Definierung vor.
Deshalb hab ich den Code dann in C kopiert...
Wie hätte ich das definieren müssen?


Ich hoffe ihr könnt mir dabei helfen  :-)

Seiten: [1]

Einloggen