Hallo GeoK,
Assembler braucht man eigentlich nur, wenn man volle Kontrolle über die Maschine haben will. Das sind dann kritische Aufgaben, z.B. zeitkritisch: das Programm muß so schnell wie möglich laufen. Oder steuerungskritisch: Das Programm darf nicht irgendwie (Interrupts) unterbrochen werden. Und was Dich ganz aufgeregt macht, nämlich jemand anderem einen Virus, Trojaner oder Wurm unbemerkt in das System zu schleusen, das mache ich nicht mit. Um Assembler programmieren zu können, mußt Du anfangen zu denken wie die Maschine – und außerdem ist es wahnsinnig umständlich. Wenn Dich das aber interessiert, dann schaff dir ein Turbo-Pascal 6 oder 7 (nicht 5) an und ein Anfänger-Handbuch (nicht nur Turbo-Pascal sondern Assembler) und experimentiere mit dem ASM-END-Befehl herum.
Das meiste geht auch in QBasic. Die beiden Befehle OUT und INP steuern die Hardware an. Der PC ist so organisiert, daß die Ansteuerung des Speichers über einen Leitungsstrang (Bus) und die Ansteuerung der übrigen Hardware über einen anderen Strang erfolgt. Uns interessiert hier nur der „andere“ Strang, der ganz verschiedene Namen hat (z.B. PCI-Bus). Hier läuft es normalerweise so, daß zunächst eine Zahl in den Raum geworfen wird und ein Gerät sich angesprochen fühlt. Direkt hinter dieser „Adressierung“ folgt eine weitere Zahl, damit das angesprochene Gerät weiß, was es zu tun hat. Wenn man erst abwartet, bis das Gerät „hier!“ brüllt, dann spricht man von Handshake-Modus. Die erste Zahl, die gesendet wird, um die Aufmerksamkeit eines Geräts zu erringen, nennt man Port-Adresse. Die zwanghaft germanische Übersetzung in der QBasic-Hilfe spricht von Hardware-E/A-Anschluß. OUT (764), 8 heißt also: Zuerst 764, dann 8 senden.
Manche Geräte haben mehrere Port-Adressen. Schon allein an der Zahl, die gesendet wird, weiß das Gerät also schon: „Aha, der Wille des Prozessors geht in diese und jene Richtung“. Die zweite serielle Schnittstelle (COM2) fühlt sich angesprochen bei den Port-Adressen 760 bis 766.
Schnitt: An dieser Stelle mußt Du Dich mit Hexadezimalzahlen anfreunden. Hexadezimalzahlen sind die allgemein übliche Darstellungsform von Binär- (Dual-)zahlen. Und Binärzählen sind die Darstellung dessen, was sich da auf dem Bus tut. Der Bus auf Deinem AT hat sechzehn Leitungen, mit denen die Adressen und Befehle gesendet werden. Um die Zahl 764 zu senden, wird die Spannung auf den Leitungen (wir haben es ja mit Strom zu tun) wie folgt gesetzt (1 steht für Spannung=hoch, 0 steht für Spannung=niedrig/manchmal negativ): 0000001011111100. Du kannst Dir leicht vorstellen, daß man innerhalb kürzester Zeit wahnsinnig wird, wenn man mit solchen Ungetümen umgehen muß. Man faßt dieses Ding also zu Vierergruppen (bei Dreiergruppen sind wir im Oktalsystem) zusammen und zählt wie folgt:
Binär Dezimal Hexadezimal
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 8 8
1001 9 9
1010 10 A
1011 11 B
1100 12 C
1101 13 D
1110 14 E
1111 15 F
Sinn der Sache ist, daß vier Bits (Binärzahlen) immer nur durch eine Ziffer dargestellt werden soll. Die Zahl 764 wird im Hexadezimalsystem als 02FC dargestellt. Gewöhne Dir die führende Null an, sie erspart einem manches Mißverständnis. Um die Hexadezimalzahl für eine Dezimalzahl herauszukriegen ist der HEX$-Befehl in QBasic ideal. Auch der Rechner von Windows kann umrechnen.
QBasic würde „02FC“ als Variable und nicht als Zahl auffassen. Eine Angabe wie Port=02FC, würde also zu Port=0 führen, weil die Variable mit dem Namen „02FC“ zu diesem Zeitpunkt sicherlich noch nicht existiert hat. Also muß man QBasic extra erzählen, daß es sich hier um eine Hexadezimalzahl handelt. Dies geschieht, indem man ein „&H“ vor die Hexadezimalzahl schreibt, also: &H02FC. In Turbo Pascal ist es ein „$“ ($02FC) in C ein „0x“ (0x02FC), in Assembler wird hinten ein „h“ angehängt (02FCh).
Die serielle Schnittstelle sendet (und empfängt) grundsätzlich wie ein Radio: Es ist völlig egal, ob jemand zuhört, die Musik dudelt. Das ist flapsig ausgedrückt die Baudrate. Baudrate ist die Zahl der Bits, die pro Sekunde gesendet und empfangen werden. Wenn Du also ein „A“ durch die Leitung schicken willst, dann wird der Buchstabe in ein Byte (=8 Bits umgewandelt) und bitweise hintereinander gesendet ohne Rücksicht darauf, ob es am anderen Ende ankommt. Meistens wird noch ein neuntes Bit gesendet, das sogenannte Stoppbit. Wenn ich das aus den wichtigtuerischen Artikeln richtig herausgelesen habe, handelt es sich eher um eine Verschnaufpause für Uraltgeräte. Die Baudrate muß auf beiden Seiten gleich eingestellt sein, sonst gibt es Mißverständnisse. Bei einer Baudrate von 9600 (9600 Bits pro Sekunde) würde also der Buchstabe A mit 9 Bit eine Sendezeit von 9/9600 s, also etwa eine Tausendstel Sekunde benötigen. Das müßte für Nibbles eigentlich genügen. Die Baudrate direkt über Port-Adressierung einzustellen, ist etwas kompliziert, wie Du gleich bemerken wirst. Es muß auch programmiert werden, aus wievielen Bits ein Byte bestehen und was die überzähligen Bits bedeuten sollen.
Der RS232-Schnittstelle muß man auch noch erzählen, daß sie jetzt aufpassen soll, was an ihrem Ausgang passiert. Man simuliert mittels Programm ein Peripheriegerät, daß anfängt zu senden und zu empfangen. Dafür sind die Leitungen DTR und RTS im Kabel und die beiden letzten Bits des Ports &H02FC zuständig. Sind DTR (Data Terminal Ready) und RTS (Request To Send) hochgesetzt (unter Spannung), bedeutet das, die Schnittstelle (Terminal) ist bereit (ready) ist, zu senden und zu empfangen, und auch ein Peripheriegerät (hier der andere Computer) willig ist (request), Daten empfangen.
Bevor ich nachfolgend das nächste ungeprüfte Programm schicke, versuch mal, ob sich alles in Wohlgefallen auflöst, wenn Du ganz am Anfang meines letzten Programms folgende Zeile einfügst:
RESET
Versuch mal, ob folgendes Programm (auf beiden Rechnern gestartet) funktioniert. Es ist übrigens auch ein hervorragendes Beispiel, was sogenannter Spaghetti-Code ist.
REM Open Com
OUT (&H02FB), &H80 : REM Baudeingabe aktivieren
OUT (&H02F8), &H12 : REM Baudrate 9600
OUT (&H02F9), 0 : REM was auch immer
OUT (&H02FB), &H03 : REM 8 Bit, Kein Parity-Bit, 1 Stopbit
OUT (&H02FC), &H03 : REM DTR=1, RTS=1
Dummy = INP (&H02F8) : REM Empfangspuffer lesen und leeren
REM Los gehts
Tastaturabfrage:
A$ = INKEY$
If A$ = „“ THEN GOTO Empfangen ELSE GOTO Senden
Senden:
IF A$ = „e“ THEN GOTO Ende
WHILE (INP (&H02FD) AND &H20) = &H20: WEND : REM Warten bis Sendepuffer leer ist
B = ASC (A$)
OUT (&H02F8), B
GOTO Tastaturabfrage
Empfangen:
IF (INP (&H02FD) AND &H01) = &H01 THEN B=INP(&H02F8) : REM Zeichen lesen, wenn Zeichen anliegt
A$ = CHR$(B)
PRINT A$
GOTO Tastaturabfrage
Ende:
OUT (&H02FC), 0 : REM Schließen – DTR=0, CTS=0
END
Sollte es nicht klappen, dann beschreibe bitte genau, was Du in welcher Reihenfolge getan hast und wie der Computer reagiert hat. Übrigens, das Nullmodemkabel muß an beiden Seiten an der zweiten seriellen Schnittstelle hängen, da ich davon ausgehe, daß an COM1 die Mäuse angeschlossen sind.
Alles weitere direkt, wobei ich allerdings ein bißchen einschränken möchte, daß ich keinen Fernunterricht mache. Nicht böse sein :o))).
Grüsse
ralph