Hallo.
Ich beschäftige mich seit 2-3 Jahren mit Assemblerprogrammierung am MOS 6502 und Intel 8080. Meine Programme sind natürlich nichts weltbewegendes, aber ich habe schon das ein oder andere Tool programmiert, das mir persönlich, bei meinen Projekten weitergeholfen hat. Ohne Assemblerkenntnisse hätte ich auch niemals meinen Imsai 8080 sauber zum Laufen gekriegt, versteht sich. Das ist ja noch "Computer pur".
Um irgendwelche Spiele und Demos zu programmieren, fehlt mir zum einen die Zeit und zum anderen hab ich da auch überhaupt keine Ideen. Dazu muß man eine künstlerische und eine technische Ader haben. Ich würde mich eher als "technisch kalt" bezeichnen. Ohne Ideen für irgendwelche Grafiken, Spiele-Ideen oder dergleichen.. Natürlich hab ich am C64 schon mit den Rasterinterrupts gespielt und den ein oder anderen Lauftext unten, mit stehender Überschrift oben und SID-Sound Untermalung Code gebastelt. Aber das war es künstlerisch dann auch schon.
Zwischendurch hab ich dann mal mit Z80 Assembler angefangen, aber da find ich irgendwie nicht hin. Ich habe da auch nur einen Vintage-Rechner, den Kaypro II, da. Und wenn ich da dringend was bräuchte, könnte ich das auch in 8080 Assembler tippen. Das ist ja schließlich kompatibel.
Da ich auch Fan der Marke mit dem Nadelstreifenanzug und der Bügelfaltenhose bin, würde ich jetzt gerne mal was an meinem IBM 5160 machen, also im X86 Assembler. Bzw. auch für meinen IBM 5170 und den Cordata PPC...
Die Kenntnisse beim 8080 machen es mir vielleicht ein bißchen leichter beim Erlernen des x86 Assemblers bzw. der Mnemonics. Allerdings ist das "Außenrum" natürlich anders.
1. Da wäre der Speicher. Bisher hatte ich meine 64kb, also von 0000h bis FFFFh. Linear adressierbar. Beim IBM mit seinen 640kb RAM hab ich 16 Bit Register, aber hardwareseitig einen 20 Bit Adressbus (also bis 1 MB). Natürlich kann man mit 16 Bit keine 20 Bit linear adressieren. Deswegen gibt es die Segmente und in denen die Offsetadresse. 1 MB sind hardwareseitig adressierbar, 64kb sind über 16 Bit Register adressierbar. Jetzt könnte man meinen, man teilt einfach 1MB durch 16. Dann hat man 16 Segmente á 64 kb, was 1 MB ergäbe. Und ein Segment würde direkt nach dem anderen beginnen. Das würde normalem Bankswitching entsprechen, wie es bei anderen Rechnern der Fall ist. So "einfach" ist das aber beim 8088 nicht.
(Ich will künftig jetzt 8088 schreiben anstatt x86, weil ab 80386 das Problem wegen der 32 Bit breiten Register nicht mehr besteht).
Es ist nicht so einfach, weil in den Segmenten eine Überlappung sein kann. Ein neues Segment darf frühestens 16 Bytes nach dem letzten beginnen. Das würde ja bedeuten, dass Byte 17 von Segment 1 exakt die gleiche Speicherstelle ist wie Byte 00 von Segment 2. Oder sehe ich das falsch ? Vielleicht kann mir das jemand genauer erklären ?!
2. Eine COM-file hat max 64kb, läuft also immer innerhalb eines Segmentes. Eine EXE-Datei kann im Prinzip den kompletten Speicher nutzen. Deswegen muß im Assembler (in meinem Fall MASM 5.0) allerdings mehr definiert werden, zB der Stack. Beim 6502 ist der Stack automatisch auf Page 1. Beim 8080 definiere ich den Stack über das Stackpointer Register und reserviere dazu genügend bytes am Ende des Programms. Rückwärts, versteht sich. Wo befindet sich der Stack einer COM-file, wenn er nicht explizit definiert wurde. Setzt diesen MASM automatisch am Ende des Programms, so wie ich es im 8080 Assembler manuell mache ?
3. Ich schreibe ein helloworld-Programm mit dem MASM mit org 0100h. CP/M und DOS Programme beginne immer ab 0100h. Ich lade das Programm, es steht im Speicher. Wenn ich in den Debugger gehe und mit "-d 0100" den Dump anschauen will, steht da nichts. Wie finde ich raus, in welchem Segment das Programm steht ?
4. "INT"-Anweisungen stehen für System-Calls (8080 Slang) oder Kernal-Routinen (Cevi Slang). Ich schiebe also die gewollten Daten in die dementsprechenden Register und führe die Int(errupt) Funktion aus. Der Name INTerrupt wahrscheinlich deswegen, weil er das Hauptprogramm kurz verlässt, es also unterbricht, diese "Unterbrechungsroutine" wird ausgeführt und dann springt er wieder zurück ins Hauptprogramm. Der XT hat weniger "Kernalfunktionen" als zB der AT oder der XT286. Man hat zB nicht die Funktion "Festplatte parken" beim XT. Dann gibt es neben den "Kernalroutinen" auch noch die INT-Routinen von MS-DOS. Dabei handelt es sich quasi um eine Erweiterung der "Kernalroutinen" eine Ebende höher..
Die große Frage ist, wie greife ich zB auf die Funktionen des Festplattencontrollers zu ? Das XT Bios, oder genauer gesagt die Firmware im ROM, hat keine Funktion bzw. keinen INT, um einen Seek in Richtung Festplatte zu schicken. Ich müsste diesen Seek direkt am Festplattencontroller aufrufen, um zB die heads zum parken in die landing zone zu fahren. Damit könnt ich mir ein kleines Festplattenparkprogramm, 100% angepasst auf meine Platte, schreiben.. Wie geht man da vor ?
5. Vom 8080 kenne ich die Portadressierung, vom 6502 den Weg der Speicheradressierung.. Wenn ich beim zB 8080 eine "1" aus der Seriellen Schnittstelle COM1 an Port 22h ausgeben will, dann schreibe ich einfach:
org 0100h ; Programmstart 0100h
mvi a,31h ; 31h (Ascii-Code für Ziffer "1") in den Akkumulator
out 22h ; Akku-Inhalt an Port 22h ausgeben
ret ; Return from Subroutine
Wie man das beim 8088 über eine "Kernalroutine" macht, das weiß ich. Direkt über einen Port hab ich nicht probiert. Aber was hat das mit diesen IRQs (interrupt requests) zu tun ? Warum liegen die COM-Schnittstellen zB auf IRQ3 und IRQ4 ?
Vielleicht kann mir jemand helfen ?!
Vielen Dank !!!!
Gruß Jan