Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: bscreator am 27. April 2010, 21:20
-
Hallo,
ich hab folgendes im Internet gefunden:
Der Bootloader :
[BITS 16]
EXTERN _main
start:
jmp 07c0h:main_entry
main_entry:
mov ax,cs
mov ds,ax
mov es,ax
cli
mov ss,ax
mov sp,9000h
sti
mov ah,02h
mov al,1
mov cl,2
mov ch,0
mov dl,0
mov dh,0
lea bx,[kernel]
int 13h
call _main
jmp $
;##Funktion zur Stringausgabe / Begrenzungszeichen: ASCII 0
GLOBAL _prnt
_prnt:
push bp
mov bp, sp
push ax
push si
mov ax, [bp + 4]
mov si,ax
prnt1:
mov al,[si]
cmp al,0
JE prnte
inc si
mov ah,0eh
int 10h
jmp prnt1
prnte:
pop si
pop ax
pop bp
ret
GLOBAL _boot
_boot db "Der erste C Kernel",13,10,0
times 510-($-$$) db 0
dw 0aa55h
kernel:
Der Kernel:
extern "C" void prnt(char *var);
extern char boot;
int main()
{
char *str;
str=&boot;
prnt(str);
return 0;
}
Aus beiden wird ne OBJ-Datei gemacht, mit JLOC verlinkt und dann mit RawWrite auf ne Disk geschrieben und funktioniert.
Ein paar Fragen dazu:
1. Befinden sich hier Kernel und Bootloader im selben Segment?
2. An welche Segment:Offset-Adresse wird der Kernel eigentlich geladen?
3. Was passiert bei lea bx,[kernel] ?
Gruss,
bsc
-
Zu 2:
Soweit ich weiß, wird der C-Kernel hinter den Bootloader geladen, also an 0x7D00.
Dies passiert mit lea bx,[kernel] (kernel ist die Adresse hinter dem Bootloader)
(zu 3)
Zu 1:
Ich denke schon, sonst müsste cs geändert werden.
-
Zu 2:
Soweit ich weiß, wird der C-Kernel hinter den Bootloader geladen, also an 0x7D00.
Ich weiß nicht wie JLOC das genau anstellt, aber da es angeblich klappt, muss der Kernel wohl nach 0x07c0:0x0200 geladen sein.
Das ist dann die lineare Adresse 0x7e00. (da 512 = 0x200)
-
Ich habe eher das Gefühl, dass beides Teil des Bootloaders ist (Symbol _main muss im Assemblerteil bekannt sein und Symbol _boot/_prnt im C-Teil). Es wird halt nur der zweite Sektor (des Bootloaders) nachgeladen. Meiner Einschätzung nach dürfte das nicht wirklich das sein, was du willst. :wink:
-
Ich habe eher das Gefühl, dass beides Teil des Bootloaders ist
Denk ich auch :-D
Soweit ich weiß, wird der C-Kernel hinter den Bootloader geladen
Diese Einschätzung teil ich auch :-D
1. Wenn ich den Kernel an eine andere Stelle, z.B. nach 0x1000:0x0000 laden will, dann klappt ja kein CALL mehr, da anderes Segment. Kann ich dann mit JMP 0x1000:0x0000 oder mit JMP 0x1000:_main den C-Kernel starten ?
2. Wenn ich die C-Funktionen in NASM geschrieben hab, kann ich diese ASM-Datei dann irgendwie mit INCLUDE an den C-Kernel "festmachen" , bzw. in den C-Kernel inkludieren ?
Gruss und danke,
bsc
-
Wenn du Assemblercode in einer C-Datei #includest, wird dir der Compiler den Code um die Ohren hauen, weil Assembler kein gültiges C ist. #include macht ja nichts anderes, als einfach den Text der anderen Datei an dieser Stelle einzufügen. Umgekehrt gilt dasselbe.
Wenn du Assembler und C in eine Binary zusammenbringen willst, brauchst du kein Include, sondern einen Linker.
-
[
Wenn du Assemblercode in einer C-Datei #includest, wird dir der Compiler den Code um die Ohren hauen, weil Assembler kein gültiges C ist
Ach mist, du hast ja sooooooo recht
1. Aber ich könnt ja immer noch z.B. eine eigene Datei nur für in C geschriebene C-Funktionen erstellen und die Datei dann in den Kernel includieren, oder ?
2. 1. Wenn ich den Kernel an eine andere Stelle, z.B. nach 0x1000:0x0000 laden will, dann klappt ja kein CALL mehr, da anderes Segment. Kann ich dann mit JMP 0x1000:0x0000 oder mit JMP 0x1000:_main den C-Kernel starten ?
Gruss,
bsc
-
Hallo,
2. 1. Wenn ich den Kernel an eine andere Stelle, z.B. nach 0x1000:0x0000 laden will, dann klappt ja kein CALL mehr, da anderes Segment. Kann ich dann mit JMP 0x1000:0x0000 oder mit JMP 0x1000:_main den C-Kernel starten ?
Die CALLs innerhab der zusammengelinkten flachen Executable sind entweder NEAR und funktionieren in jedem Segment oder die sind FAR und Du musst sie vor der ersten Benutzung relozieren. Falls Du in Assembler und C die selbe Code-Sektion benutzt kannst Du von NEAR ausgehen, außerdem sollte der Linker eine nackte Binary nur dann erzeugen wenn keine unaufgelösten Relozierungen übrig bleiben.
Der Sprung von Deinem Assembler-Code, nachdem Du die Executable im Speicher umkopiert hast sollte IMHO 'JMP 0x1000:_main' sein.
Probiere das einfach mal aus.
Grüße
Erik
-
Der Sprung von Deinem Assembler-Code, nachdem Du die Executable im Speicher umkopiert hast sollte IMHO 'JMP 0x1000:_main' sein.
Aha, vielen dank.
Probiere das einfach mal aus.
Das werd ich.
Vielen Dank euch allen,
bsc
-
Nochne Frage:
Wenn ich meinem C-Kernel Funktionen zur Verfügung stellen will, muss ich ja diese erst in C oder Assembler schreiben.
Frage:
1. Wenn ich diese C-Funktionen in Assembler schreibe, diese Funktionsdatei in ein anderes Segment als Kernel geladen wird, die Funktionen aber als GLOBAL und im C-Kernel als EXTERN deklariert werden, kann ich diese verwenden, auch wenn sie sich in einem anderen Segment befinden, stimmts ?
2. Wie kann ich einen C-Kernel exakt 512 Bytes gross machen? Gibts da auch so ne times-Funktion wie in NASM oder stellt der Inline-Assembler von C auch die times-Funktion zur Verfügung ?
Gruss und danke, :-D
bsc
-
Der Compiler sollte halt wissen, dass er einen Far-Call erzeugen muss, nehme ich an. Und das klingt compilerspezifisch. Welchen Compiler benutzt du denn? Das Internet weiß da sicher was dazu.
Ich frage mich nur, warum du dir den ganzen Real-Mode-Quatsch überhaupt antust. ;)
-
Ich frage mich nur, warum du dir den ganzen Real-Mode-Quatsch überhaupt antust.
Das fragen sich viele
Der Compiler sollte halt wissen, dass er einen Far-Call erzeugen muss
Jo, da hast recht
Als Compiler nur den Turbo C 3.0, aber wie der das handhabt, hab ich keine Ahnung.
Wie immer ein paar Fragen: :?
1. Aber falls ich das mit dem Far-Call nicht hinkrieg, kann ich ja immer noch eine C-Datei (die in C geschriebene Funktionen enthält) in den Kernel inkludieren, oder ?
2. Wie kann ich einen C-Kernel exakt 512 Bytes gross machen? Gibts da auch so ne times-Funktion wie in NASM oder stellt der Inline-Assembler von C auch die times-Funktion zur Verfügung ?
Gruss,
bsc
-
Hallo,
was du möchtest, ist, Funktionen und Symbole einer Datei in einer anderen Datei nutzen. Das ist compiler- und linkerspezifisch, da musst du dich mit deinem Linker (TLINK) prügeln, nicht mit Compiler oder Assembler. Ob die Funktionen selbst nun ASM oder C sind, spielt nämlich keine Rolle - solange das Objectformat stimmt und die Symbole vorhanden sind.
Im laufenden Betrieb kannst du mit einem FAR CALL auch Code in anderen Segmenten ausführen, aber du musst dem Compiler sagen, dass er auch einen solchen Sprung erzeugen muss, auch das ist compilerspezifisch.
Eventuell solltest du als Assembler den TASM nutzen, da der wahrscheinlich besser mit TC und TLINK zusammenarbeitet als NASM. Ist aber nur so 'ne Vermutung.
Um eine Datei auf 512 Bytes zu padden, kannst du "dd" benutzen:
dd if=eingabe of=ausgabe bs=512 count=1 conv=sync
Und "dd" gibt es auch für Win32, wahrscheinlich auch für DOS. Ansonsten baust du dir halt in C schnell selbst ein solches Programm.
Die "times"-Anweisung in C ist mir nicht bekannt und ist - sofern vorhanden - auch compilerspezifisch. Sowas braucht man in C auch nicht...
Gruß,
Svenska
-
Ah, ok
Also dass der ganze "Sch..." compilerspezifisch ist, ist nicht in meinem Sinn. Also werd ich am besten den ganzen Mist über 16-Bit-C-Kernel wieder vergessen.
Ansonsten baust du dir halt in C schnell selbst ein solches Programm.
Oh man Svenska, du hast echt die besten Ideen.
Und da der ganze Mist compilerspezifisch ist, werd ich, da ich im Real-Mode bleiben will, mein OS in Assembler fertigstellen und in C ein paar "Hilfsprogramme", wie z.B. das 512-Byte padden, schreiben.
Im Real-Mode regiert also Assembler.
Jedenfalls danke euch allen! :-D
-
Hallo,
@bscreator:
FAR CALLs haben den Nachteil das sie immer absolute Adressen benutzen (zumindest im RM) und die stehen zur Compile-/Link-Zeit noch nicht fest sondern werden erst beim laden des Executables reloziert. Normalerweise macht dass das OS aber in Deinem Fall müsste es der Assembler-Teil des Boot-Loaders erledigen.
Kennst Du den Unterschied zwischen .COM und .EXE bei DOS?
Einen Loader für das DOS-EXE-Format zu schreiben sollte nicht allzu schwer sein (denke ich zumindest, genau weiß ich es nicht). Willst Du das wirklich tun? Wenn Du im RM mal mehr als 64 kBytes Speicher nutzen willst dann kommst Du da definitiv nicht drum herum (oder Du baust ein eigenes Format, was aber sicher noch komplizierter ist weil Du dann noch mindestens nen eigenen Linker brauchst, glaube mir ich weiß wovon ich da schreibe, ich mach das gerade). Vielleicht lässt Du dich mal von den Sourcen von Free-DOS inspirieren.
Ich frage mich nur, warum du dir den ganzen Real-Mode-Quatsch überhaupt antust.
Das fragen sich viele
Ich mich auch. Ich hab oft genug RM-Programme entwickelt (das meiste in C/C++ aber auch einiges in Assembler) und dieser Kram macht IMHO echt keinen Spaß.
Grüße
Erik
-
Hallo,
ein kleines Programm in C zu schreiben, welches eine Datei öffnet, die aktuelle Dateigröße ermittelt, auf ganze 512er addiert und den Inhalt (plus viele Nullbytes) wieder in eine Datei schreibt, sollte wirklich nicht zu schwer sein (fopen, fclose, read und write?). Außerdem gibt es "dd".
MS-DOS ist in Assembler geschrieben, die meisten anderen Programme für den Real-Mode in einer Hochsprache. Assembler hat den Nachteil der Unportabilität und Unlesbarkeit - es sei denn, die Kommentare machen den Gutteil des Codes aus - und Hochsprachen haben Vorteile.
Was ich bereits vorher zur Overlay- und damit indirekt auch zur Segment-Technik geschrieben habe, gilt auch weiterhin - die meisten Compiler können damit nichts anfangen und produzieren langsamen Code. Das ist dem primitiv-segmentbasierten Speichermodell geschuldet, welches einfach überholt ist. Die Compilertechnologie hat sich weiterentwickelt, diese Architektur halt nicht so recht.
Was die compilerspezifischen Sachen angeht, das betrifft den Zwischencode - den Binärcode zwischen Endergebnis und Quelltext. Der ist halt nicht universell, damit musst du leben. Das ganze gibt es dann auch noch in groß, wenn man versucht, Visual C nach gcc zu portieren oder umgekehrt. Oder Code für mein STM8-Board auf den PC. Der ist nicht nur hochgradig compilerabhängig, sondern dazu auch noch hardwarespezifisch...
Entweder, du baust dir ein vernünftiges Executable-Format, welches dir die Zerstückelung in Segmente erlaubt, oder aber du baust deinen Kernel in maximal 64K auf. Die Gedanken sind die gleichen, ob du nun ASM schreibst (und es selbst machen musst) oder ob du C nutzt (und damit den TLINK für eine EXE nutzen kannst, aber den EXE-Loader brauchst du selbst).
Ich wiederhole Erik, glaube ihm, er weiß, was er schreibt. Setz dich mit dem Linker deiner Wahl tiefgründig auseinander und informier dich über Executables verschiedener Formate.
Gruß,
Svenska
-
Mein Hauptproblem ist, dass ich keine Ahnung hab, wie man in Turbo C einen FAR-CALL erzeugt.
In Assembler ist das ganze ja kein Problem, aber Turbo C keine Ahnung.
FAR CALLs haben den Nachteil das sie immer absolute Adressen benutzen (zumindest im RM) und die stehen zur Compile-/Link-Zeit noch nicht fest sondern werden erst beim laden des Executables reloziert. Normalerweise macht dass das OS aber in Deinem Fall müsste es der Assembler-Teil des Boot-Loaders erledigen.
Meinst Du, dass ich eine (als GLOBAL deklarierte) ASM-Funktion für FAR-JUMPS im Bootloader schreiben soll? Wenn sich mein OS in nem anderen Segment befindet, kann ich damit aber trotzdem nix anfangen.
Kennst Du den Unterschied zwischen .COM und .EXE bei DOS?
Den kenn ich. COM hat Daten- und Code im selben Segment, EXE bekommt verschiedene Segmente.
ein kleines Programm in C zu schreiben, welches eine Datei öffnet, die aktuelle Dateigröße ermittelt, auf ganze 512er addiert und den Inhalt (plus viele Nullbytes) wieder in eine Datei schreibt, sollte wirklich nicht zu schwer sein
Das ist einfach. Bin ja in Visual C++ kein Anfänger mehr.
Setz dich mit dem Linker deiner Wahl tiefgründig auseinander und informier dich über Executables verschiedener Formate.
Es geht nicht darum, dass mein OS Executables ausführen soll. Die Programme für mein OS schreib ich alle selber.
Aber vielleicht könnt ihr mir noch hier helfen:
Mein OS soll nur eine FAT12-Diskette auslesen können. Nicht auf Disk schreiben, keine Dateien öffnen können, nur den Inhalt der Disk anzeigen. Hab keine Ahnung wie, und das Tutorial von glaube PHIL oder TeeJay helfen mir auch nicht.
Könnt ihr mir da helfen ?
Viele Grüße,
bsc
-
Und da der ganze Mist compilerspezifisch ist, werd ich, da ich im Real-Mode bleiben will, mein OS in Assembler fertigstellen und in C ein paar "Hilfsprogramme", wie z.B. das 512-Byte padden, schreiben.
Im Real-Mode regiert also Assembler.
Da sind dann nicht nur Far Calls, sondern die gesame Syntax assemblerspezifisch. Bin mir nicht sicher, ob das in dieser Hinsicht eine Verbesserung ist. ;)
-
Aber vielleicht könnt ihr mir noch hier helfen:
Mein OS soll nur eine FAT12-Diskette auslesen können. Nicht auf Disk schreiben, keine Dateien öffnen können, nur den Inhalt der Disk anzeigen. Hab keine Ahnung wie, und das Tutorial von glaube PHIL oder TeeJay helfen mir auch nicht.
Könnt ihr mir da helfen ?
Das kriegst du in 64k locker unter, hast also gar keinen Bedarf, mehrere Segmente zu verwenden. Die bräuchtest du erst, wenn du was ernsthafteres machen wolltest.
-
Da sind dann nicht nur Far Calls, sondern die gesame Syntax assemblerspezifisch. Bin mir nicht sicher, ob das in dieser Hinsicht eine Verbesserung ist.
Ja schon, aber wenn du mir sagen kannst, wie ich FAR-CALLs in Turbo C machen kann, dann gehts in C weiter. Und ohne FAR-Calls keine Chance.
Das kriegst du in 64k locker unter, hast also gar keinen Bedarf, mehrere Segmente zu verwenden. Die bräuchtest du erst, wenn du was ernsthafteres machen wolltest.
Ich will mal klein anfangen, also nur die Dateien auf einer FAT12-Diskette auslesen. Aber ich weiß nicht, wie und wo ich anfangen soll.
Also nochmal:
Wie die Syntax in Turbo C für FAR-CALLs lautet, das steht im LINKER-Tutorial, oder ?
-
Hallo,
Mein Hauptproblem ist, dass ich keine Ahnung hab, wie man in Turbo C einen FAR-CALL erzeugt.
Gar nicht! Das ist Aufgabe des Compilers. Dazu muss man dem Compiler natürlich sagen was für ein Speicher-Model er benutzen soll. Wenn Du z.B. Large oder Huge auswählst werden die Funktionsaufrufe oft (also für Funktionen die als extern deklariert sind) als FAR-CALL generiert und in den betreffenden Funktionen als letztes ein RETF eingebaut.
FAR CALLs haben den Nachteil das sie immer absolute Adressen benutzen (zumindest im RM) und die stehen zur Compile-/Link-Zeit noch nicht fest sondern werden erst beim laden des Executables reloziert. Normalerweise macht dass das OS aber in Deinem Fall müsste es der Assembler-Teil des Boot-Loaders erledigen.
Meinst Du, dass ich eine (als GLOBAL deklarierte) ASM-Funktion für FAR-JUMPS im Bootloader schreiben soll? Wenn sich mein OS in nem anderen Segment befindet, kann ich damit aber trotzdem nix anfangen.
Nein, ich meine das der Linker noch nicht die entgültigen Segmente in die FAR-CALLs einträgt, die weiß er einfach nicht. Das macht normalerweiser der EXE-Loader von DOS, das nennt sich dann relozieren (http://www.at-mix.de/relozieren.htm). Mit diesem Vorgang solltest Du Dich mal genauer beschäftigen. Da Du ein eigenes OS entwickeln willst musst Du das selber machen. Alternativ kannst Du Dich natürlich auch auf ein einzelnes Segment mit max. 64 kBytes beschränken.
Kennst Du den Unterschied zwischen .COM und .EXE bei DOS?
Den kenn ich. COM hat Daten- und Code im selben Segment, EXE bekommt verschiedene Segmente.
Fast. Der wesentliche Unterschied ist das .EXE relozierbar sind und .COM eben nicht.
Es geht nicht darum, dass mein OS Executables ausführen soll. Die Programme für mein OS schreib ich alle selber.
Diese 2 Sätze wiedersprechen sich. Erst soll Dein OS keine Programme (also die Dinge die nicht direkt fest im Kernel mit drin sind) ausführen können und dann willst Du diese Programme selber schreiben. :?
Mein OS soll nur eine FAT12-Diskette auslesen können. Nicht auf Disk schreiben, keine Dateien öffnen können, nur den Inhalt der Disk anzeigen.
Also quasi ein 'dir'-Befehl ausführen. Das ist wahrlich nicht schwer. Wenn Du dich auf die kurzen 8.3 Dateinamen beschränken kannst dann ist das in 1 oder 2 Tagen in C programmiert. Alle nötigen Infos finden man bei Wikipedia (http://de.wikipedia.org/wiki/File_Allocation_Table).
MS-DOS ist in Assembler geschrieben
Das stimmt nicht! Selbst von der IO.SYS und MSDOS.SYS ist nur ein kleiner Teil in Assembler geschrieben. Die meisten Programme in MS-DOS in ganz normal in C (oder einer anderen Hoch-Sprache). HIMEM.SYS und EMM386.EXE könnten noch einen erheblichen Assembler-Anteil haben.
Assembler hat den Nachteil der Unportabilität und Unlesbarkeit - es sei denn, die Kommentare machen den Gutteil des Codes aus - und Hochsprachen haben Vorteile.
Da muss ich Dir entschieden wiedersprechen! Außer bei der Portabilität natürlich. Mann kann in Assembler sehr wohl eleganten, lesbaren und wartbaren Code schreiben. Natürlich muss man den etwas besser Kommentieren aber das bedeuten nicht das man mehr Kommentare als Befehle benötigt. Mann muss das als Programmierer nur wollen und dann auch konsequent durchziehen. Ordentlich programmieren können muss man natürlich auch. ;)
Grüße
Erik
-
Na gut.
Was MS-DOS in Assembler angeht, so habe ich die OEM-Sourcen für MS-DOS 3.30 da, inklusive Referenzanleitung, um eine eigene IO.SYS (die einzige systemabhängige Datei) in Assembler zu basteln, am Beispiel des IBM-PC. In dem Dokument steht auch drin, dass MS-DOS vollständig in Assembler geschrieben ist.
Über die Programme kann ich nichts sagen, auch nicht über spätere Versionen von MS-DOS. Die gab es nur noch für den IBM-PC und kompatible, also auch keine OEM-Quelltexte mehr. Ich vermute trotzdem, dass die das nicht komplett umgeschrieben haben...
Gruß,
Svenska
-
OK, wo fang ich an? :?
Gar nicht! Das ist Aufgabe des Compilers. Dazu muss man dem Compiler natürlich sagen was für ein Speicher-Model er benutzen soll. Wenn Du z.B. Large oder Huge auswählst werden die Funktionsaufrufe oft (also für Funktionen die als extern deklariert sind) als FAR-CALL generiert und in den betreffenden Funktionen als letztes ein RETF eingebaut.
Nene, das ist nicht das Problem. Ich möchte nur in C auf entfernte Segmente und absolute Speicherstellen z.B. Videospeicher (0xB8000) zugreifen.
Bei NASM: ca. 3 Zeilen (mov bx,0xB800; mov es,bx; xor bx,bx) -> schon beim Videospeicher
Bei 16-Bit-C: noch keine Ahnung.
Nein, ich meine das der Linker noch nicht die entgültigen Segmente in die FAR-CALLs einträgt, die weiß er einfach nicht. Das macht normalerweiser der EXE-Loader von DOS, das nennt sich dann relozieren.
Mein OS soll lediglich die einfachsten Dinge können, d.h. Single Task und ein konstanter Speicherbereich (z.B. 0x30000) für Programme. Da ist nichts mit Paging oder relozieren. Das werd ich erst viel später realisieren.
Diese 2 Sätze wiedersprechen sich. Erst soll Dein OS keine Programme (also die Dinge die nicht direkt fest im Kernel mit drin sind) ausführen können und dann willst Du diese Programme selber schreiben.
OK, falsch ausgedrückt. Meine simplen "Programme" schreib ich in Assembler. Mein OS lädt das Programm z.B. von der Floppy in den Arbeitsspeicher (um beim Bsp. zu bleiben, nach 0x30000). Dann wird das Programm durchs OS ausgeführt. Aber EXE und COM oder andere ausführbare Dateiformate muss mein OS nicht ausführen können.
Wenn Du dich auf die kurzen 8.3 Dateinamen beschränken kannst dann ist das in 1 oder 2 Tagen in C programmiert.
Aber wenn ich in C keine Chance hab, auf andere Segmente zuzugreifen, dann muss ichs in ASM machen. Nocheinmal: wie? :?
MS-DOS ist in Assembler geschrieben
Ach Leute, darum gehts doch gar nicht. Aber soviel ich weiss, ist auf jeden Fall der Kernel komplett in ASM gehalten.
Grüsse,
bsc
-
Wisst ihr, wie man in C auf andere Segmente zugreift ? Gibt es vielleicht eine andere Möglichkeit, als mit einem FAR-JUMP ?
Dazu muss man dem Compiler natürlich sagen was für ein Speicher-Model er benutzen soll. Wenn Du z.B. Large oder Huge auswählst werden die Funktionsaufrufe oft (also für Funktionen die als extern deklariert sind) als FAR-CALL generiert und in den betreffenden Funktionen als letztes ein RETF eingebaut.
1. Wenn ich so ein Speichermodell wie HUGE oder LARGE hab, kann ich dann auch FAR-JUMPS zu absoluten Adressen machen?
2. Wenn ich so ein Speichermodell möchte, dann steht das bei Turbo C in der Linker-Anleitung, oder ?
-
Ich kenne mich mit Turbo C nicht wirklich aus, soviel vorweg. Wenn du als Speichermodell HUGE oder LARGE einträgst, dann erzeugt er dir standardmäßig eine EXE-Datei, die von DOS reloziiert wird und dann aus mehreren Segmenten besteht. Was wo in welchem Segment ist, darum kümmert sich der Compiler auch selbst.
Du möchtest aber die Segmentinhalte einzeln haben, also musst du dem Compiler(!) sagen, dass er far-pointer erzeugen muss. Das steht also in der Anleitung zum Compiler, evtl sogar in der Hilfe. In jedem Fall sind verschiedene Pointergrößen compiler- & systemabhängig.
Alternativ kannst du auch einfach eine "flat binary" erzeugen, die genau ein Segment darstellt und lädst dann halt mehrere dieser Dinger in verschiedene Segmente. Die Symbole musst du dann allerdings selbst auflösen und das reloziieren darfst du auch machen. Das hilft dir aber trotzdem nicht für absolute Adressen. Guck mal in den Beispielprogrammen zum Compiler, da dürfte bestimmt ein Zugriff auf den Video-RAM dabei sein; und wenn es über eine LIB geht, dann musst du halt da reingucken. Wenn sie im Source vorliegt.
Unter Linux kannst du als Compiler immernoch den bcc angucken, der erzeugt auch 16-Bit-Code und wird für den Pseudo-Linux-Port auf 8086 benutzt (ELKS-Projekt).
Ich kann dir sonst nicht weiterhelfen. Tut mir Leid.
Gruß,
Svenska
-
Hallo, hab das hier gefunden:
Video output doesn't work
Perhaps you are accessing video memory like this:
*(unsigned char *)0xB8000 = 'A';
This works only if the base address of the kernel data segment is 0.
Meinen die mit Kernel Data Segment die Offset-Adresse oder die Segment-Adresse des Kernels ?
-
Damit meinen die die Basisadresse des Kerneldatensegments (im Realmode der Wert der in ds steht mal 16). Wobei es eh fraglich ist wie das obere von einem 16Bit-Compiler kompiliert wird, da es ja kein 16Bit-Offset ist...