Autor Thema: Bochs: write_virtual_checks(): write beyond limit, r/w  (Gelesen 8578 mal)

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
Hallo zusammen,

ich habe da ein kleines Problem. Ich teste mein OS mit Bochs. Das OS ist in einem HD Image. Zunächst habe ich einen "sehr kleinen" Bootloader. Dieser soll den zweiten Sektor laden und dann dort hin springen. Das funktioniert auch wunderbar. Jetzt habe ich folgendes Problem. Den folgenden Kernel schreibe ich in C. Zum compilieren und linken nutze ich gcc/ld. Da ich mich noch nicht im pMode befinde habe ich in der kernel.c die asm direktive .code16gcc benutzt um 16Bit Opcode zu erzeugen. Das funktioniert auch. Was nicht funktioniert ist das schreiben in den Videospeicher bei 0xA8000 (oder 0xB8000 ich glaube aber ersteres, spielt aber auch erstmal keine Rolle in beiden Fällen klappt es nicht). Ein Debug mit Bochs ergibt folgendes. Bei der asm Anweisung mov byte ptr ds:[eax], xx bekomme ich den Fehler:

Bochs: write_virtual_checks(): write beyond limit, r/w

xx ist ein beliebiger Wert, ds ist 0 und eax ist 0xA8000. Ich verstehe nicht warum nun eine solche Fehlermeldung auftritt. Die Adresse müsste doch auch im Realmode addressierbar sein, oder nicht? Ich hoffe ihr könnt ein bisschen Klarheit in die Sache bringen. Danke.

boot.asm
; ----------------------------
; BOOTLOADER
; ----------------------------
[BITS 16]

section .text
extern main
global start

start:
mov eax, 0
mov ebx, 0
mov ecx, 0
mov edx, 0
mov ax, cs
mov ds, ax
mov es, ax
mov esi, 0
mov edi, 0

cli ;Interrupts löschen

mov ax, 0x9000 ;------------------
mov ss, ax ;Stack einrichten
mov sp, 0 ;------------------

sti ;Interrupts zulassen

mov si, loadmsg
call putstr

mov ah, 2
mov al, 1
mov cl, 2
mov ch, 0
mov dh, 0
mov dl, 0x80
mov ebx, 0x00007E00

int 13h

failure: jc failure

jmp 0x7E00

; +----------------------+
; |putstr |
; |----------------------|
; |Funktion: |
; |Gibt String aus |
; |----------------------|
; |si, String |
; +----------------------+

putstr:
lodsb
or al, al
jz short putstrd

mov ah, 0x0E
mov bx, 0x0005
int 10h
jmp putstr
putstrd:
retn

; ------------------------
; Funktionen und Variablen
; ------------------------
loadmsg db "OS wird geladen...",0

times 512-($-$$)-2 db 0
dw 0AA55h

asm(".code16gcc\n");

int main()
{
  // Pointer zum Videospeicher
  char *video = (char*)0xA8000;
  // String zum Ausgeben
  char *hello = "Executing Kernel...";
 
  // Zuerst den Speicher leeren
  for(video+=4000; video !=(char*)0xA8000 ;video--)
     *video=0;
 
  // String ausgeben
  while (*hello) {
    *video = *hello;
    video++;
    *video = 0x07;
    video++;
    hello++;
  }
 
  // jetzt wo wir schon im Kernel drin sind, wollen wir auch nicht mehr raus ;)
  while (1);
  return 0;
}

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #1 am: 12. August 2009, 16:01 »
Im Realmode kann man nicht auf Adressen zugreifen, deren Offset größer als 0xFFFF ist. Daher kann man nicht auf 0xA8000 zugreifen.
Die Realmodeadresse wäre beispielsweise 0xA800:0x0000.  :wink:

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 12. August 2009, 16:08 »
Hallo,

danke erst mal. Es ist mir klar, das man nicht "direkt" darauf zugreifen kann aber eben über ds. Das Problem, das ich habe, ist folgendes. GCC erzeugt folgende Zeile:

mov byte ptr ds:[eax], 0x00 (wie schon erwähnt ds=0 und eax=0xA0000).

Die Frage ist nun, um präziser zu sein, wie bringe ich GCC dazu nicht nur 16-Bit Opcode zu generieren sondern das ganze auch Realmode konform zu machen, sodass GCC folgendes erzeugt:

mov ax, 0xA000
mov ds, ax
mov ax, 0x00
mov [ax], 0x00

Geht das überhaupt oder kann GCC das gar nicht?

Vielen Dank

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #3 am: 12. August 2009, 16:48 »
Soweit ich weiß, kann man mit GCC keinen 16-Bit-Code erzeugen...

Du könntest das aber natürlich per Inline-Assembler lösen:
inline void far_pokeb(uint32_t lin_addr, uint8_t val)
{
  __asm__ __volatile__ ("movw %ax,%es;"
        "movb %dl,%es:(%bx)"::
        "a"((lin_addr & 0xF0000) >> 4),"b"(lin_addr & 0xFFFF),"d"(val));
}

Ich kenne mich übrigens nicht so mit AT&T aus, das kann also doch fehlerhaft sein... :wink:
« Letzte Änderung: 12. August 2009, 17:03 von XanClic »

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 12. August 2009, 18:08 »
Ja, ich habe mitlerweile auch noch ein paar Sachen gelesen.

Also zunächst ist es doch so, dass man mit GCC generell 16-Bit Code erzeugen kann (Inline ASM direktive). Das heißt dann, das der Assembler 16 Bit Opcodes erzeugt. Der entstehende Code ist aber für den PMode ausgelegt, z.B. direkte Addressierung ohne Segmentregister.
DJGPP ist ja die Portierung des GCC auf DOS. DOS ist aber soviel ich weiß Realmode. D.h. es müsste eine Möglichkeit geben den GCC auf die Erzeugung von Realmode-Code zu portieren. Weiß jemand wie das geht. Inline-ASM ist zwar ne Möglichkeit aber dann kann ich auch direkt Assembler schreiben. Das macht mir generell nichts aus, aber ich möchte z.B. ein wenig mit FAT rumexperimentieren und dann wäre es sehr schön wenn ich C-Features wie Strukturen nutzen könnte. Vielleicht hat ja noch jemand ne Idee.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 12. August 2009, 19:01 »
DJGPP ist ja die Portierung des GCC auf DOS. DOS ist aber soviel ich weiß Realmode. D.h. es müsste eine Möglichkeit geben den GCC auf die Erzeugung von Realmode-Code zu portieren.
DJGPP und damit erzeugte Programme sind keine nativen DOS Programme, sondern sind für DPMI (DOS Protected Mode Interface). Das heißt sie brauchen dieses Hilfswerkzeug, welches zwischen Protected Mode und Real Mode vermittelt, aber die Programme selbst sind 32 Bit Protected Mode Programme.

Der DJGPP ist also im Prinzip kein Port auf DOS, sondern auf DPMI.
Dieser Text wird unter jedem Beitrag angezeigt.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 12. August 2009, 19:31 »
Das macht mir generell nichts aus, aber ich möchte z.B. ein wenig mit FAT rumexperimentieren und dann wäre es sehr schön wenn ich C-Features wie Strukturen nutzen könnte. Vielleicht hat ja noch jemand ne Idee.

Wenn du unbedingt im Real Mode arbeiten willst konnte dir Bruce Evans' C compiler vielleicht weiter helfen. Du könntest aber auch einfach den Protected Mode schalten  :-D.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #7 am: 12. August 2009, 23:00 »
Letzteres ist empfehlenswert. Realmode will keiner (tm). :mrgreen:
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

svler

  • Beiträge: 18
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 14. August 2009, 10:47 »
@PorkChicken: Aha, danke für die Erklärung, das war mir nicht klar.
@bluecode: Ja, ich habe mich jetzt auch umentschieden und arbeite jetzt im PMode.

@all: Vielen Dank für eure schnelle und kompetente Hilfe. Das bekommt man ja heute nicht mehr oft in Foren. Keine einzige "unnötige" Antwort. Das Lowlevel-Forum (und die Seite) ist wirklich eine Goldgrube für OS Developer!

schönes Wochenende
svler

 

Einloggen