Teil 4 „The Sinclair ZX81 as a pocket calculator“

Der C-Kurs
Antworten
Benutzeravatar
bodo
User
Beiträge: 319
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Teil 4 „The Sinclair ZX81 as a pocket calculator“

Beitrag von bodo » 10.09.2008, 21:34

C für BASIC-Programmierer

Arbeiten mit dem z88dk Cross-Compiler

von Jens Sommerfeld und Bodo Wenzel

Teil 4

Kommen wir zum Kapitel „The Sinclair ZX81 as a pocket calculator“. Dieses behandelt neben der Ausgabe mit PRINT vor allem die binären Operatoren und die Zahlendarstellung. Die Ausgabe wird in Kapitel 17 ausführlich behandelt, deshalb gehen wir hier zunächst auf einige Operatoren von C ein. Weitere werden in kommenden Teilen behandelt.

Die folgenden Beispiele zeigen immer nur ein Statement. Dieses müsst ihr zum Ausprobieren natürlich in ein entsprechendes Programmgerüst einsetzen, weil C ja keinen „Kommandomodus“ kennt. Dieses Programmgerüst sieht so aus, mit einer Addition als Beispiel:

Code: Alles auswählen

#include <stdio.h>

int main(void) {
    printf("Ergebnis = %d\n", 1 + 2);
    return 0;
}
Hier unterscheidet sich C zunächst nicht von BASIC, wie wir es kennen: es gibt die vier Grundrechenarten, die auch nach der Punkt‑vor‑Strich‑Regel ausgewertet werden. Allerdings gibt es keinen Operator für „hoch“, also die Exponentialrechnung, das wird anders berechnet.

Wie üblich, kann die Auswertereihenfolge mit Klammern geändert werden:

Code: Alles auswählen

    printf("Ergebnis = %d\n", 3 * 2 + 2);
ergibt 6 + 2, also 8, wogegen

Code: Alles auswählen

    printf("Ergebnis = %d\n", 3 * (2 + 2));
natürlich 3 * 4, also 12 ergibt.

Das, was im C-Statement hinter dem Komma steht, wird „Ausdruck“ genannt. Es hat einen Wert und einen Typ. Überall, wo C eine Zahl erwartet, kann ein Ausdruck stehen.

Und damit kommen wir bereits jetzt auf das Konzept der Datentypen, das in C relativ lax gehandhabt wird. Das „lax“ bedeutet, dass fast alle vordefinierten Datentypen ineinander umgewandelt werden, ohne dass ihr das explizit hinschreiben müsst. Der Compiler fügt den entsprechenden Umwandlungscode automatisch ein. Darauf kommen wir später noch einmal zurück.

Aber welche Datentypen gibt es überhaupt? Das zeigt die folgende Tabelle, wobei die angegebenen Werte für das z88dk gelten (Das Forum kennt keine Tabellen...):

Code: Alles auswählen

Typ            Größe   Minimum     Maximum
char           1 Byte  -128        +127
unsigned char  1 Byte  0           255
short          2 Bytes -32768      +32767
unsigned short 2 Bytes 0           65535
int            2 Bytes -32768      +32767
unsigned int   2 Bytes 0           65535
long           4 Bytes -2147483648 2147483647
unsigned long  4 Bytes 0           4294967295
float          6 Bytes ?            ?
double         6 Bytes ?            ?
Wir kommen auf die Typen nochmal zurück, wenn wir Variablen behandeln. Dummerweise kann das z88dk für unseren Liebling keine Kommazahlen (float) bearbeiten, daher beschränken wir uns auf die Ganzzahlen (int und Genossen). Bei einer zukünftigen Version werden uns die Kommazahlen sicher einmal zur Verfügung stehen.

Außer den vier Grundrechenarten kennt C noch eine ganze Menge weiterer binärer Operatoren. Einige davon werden wir im Laufe des Kurses kennenlernen, aber mit den folgenden, die sich von den bekannten Operatoren in BASIC unterscheiden, könnt ihr euch hier schon vertraut machen:

<< Das Ergebnis ist der Wert auf der linken Seite nach links verschoben um die Anzahl Bits wie auf der rechten Seite angegeben.
>> Wie <<, nur nach rechts.
% Dividiere den Wert auf der linken Seite durch den Wert auf der rechten Seite, das Ergebnis ist der Rest der Division (modulo-Rechnung).
&Das Ergebnis ist die bitweise UND-Verknüpfung der beiden Werte.
| Das Ergebnis ist die bitweise ODER-Verknüpfung der beiden Werte.
^ Das Ergebnis ist die bitweise EXCLUSIV-ODER-Verknüpfung der beiden Werte, für Assemblerfreaks: XOR.

Außer dem positiven und dem negativen Vorzeichen gibt es u.a. noch folgenden interessanten unären Operator:

~ Das Ergebnis ist die bitweise Invertierung des Wertes, also das 1er-Komplement.

Die verschiedenen Operatoren sind wie gewohnt priorisiert, eine vollständige Darstellung steht in hoffentlich jedem C-Buch. (Wenn ihr mehr in C programmieren wollt, lohnt sich die Anschaffung z.B. der Bibel „Programmieren in C“ von Kernighan und Ritchie, aber bitte die 2. Auflage mit dem Untertitel „ANSI-C“. Gute C-Referenzen findet ihr aber auch durch Nachschlagen in der Wikipedia oder durch Googlen. Ein gratis E-Buch gibt es beispielsweise unter http://download.galileo-press.de/openbo ... _bis_z.zip.)

Ganze Zahlen könnt ihr zunächst wie gewohnt dezimal schreiben. Wenn ihr aber Hexzahlen bevorzugt, wird die Zahl mit '0x' eingeleitet, danach könnt ihr alle zehn Ziffern und die Buchstaben (groß oder klein) 'A' bis 'F' angeben. Beispiel: 0x40AB.

Um deutlich zu machen, dass der Wert ohne Vorzeichen sein soll (z.B. für unsigned int), setzt ihr ein 'U' dahinter: 54321U. Ein „breiter“ Wert (long) wird durch ein 'L' gekennzeichnet, beides zusammen geht auch: 7654321UL. Ansonsten gelten Zahlen immer als int.

Hausaufgaben
  1. Schreibt ein Programm, das die Summe der beiden Hexzahlen ABC und 123 ausgibt.
  2. Nehmt einen fähigen Taschenrechner und ermittelt die binäre Schreibweise der Operanden in folgenden Ausdrücken. Berechnet zuerst von Hand das Ergebnis und vergleicht es danach mit der Ausgabe des C-Programms:
    printf(„%d\n“, 85 & 240);
    printf(„%d\n“, 85 | 240);
    printf(„%d\n“, 85 ^ 240);
    printf(„%d\n“, 170 & 15);
    printf(„%d\n“, 170 | 15);
    printf(„%d\n“, 170 ^ 15);
  3. Lasst euch die 12 Ergebnisse von „1 jeweils nach links um 1 bis 12 Bits geschoben“ ausgeben. Tipp: das sind natürlich 12 printf-Statements.
  4. Lasst euch die 12 Ergebnisse von „12345 jeweils nach rechts um 1 bis 12 Bits geschoben“ ausgeben.
Zuletzt geändert von bodo am 10.11.2008, 19:29, insgesamt 1-mal geändert.
B0D0: Real programmers do it in hex.

Benutzeravatar
Peter Liebert-Adelt
User
Beiträge: 529
Registriert: 13.03.2004, 23:07
Wohnort: D-31246 Ilsede-Oberg
Kontaktdaten:

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von Peter Liebert-Adelt » 26.10.2008, 20:06

Hallo,

habe eine Anfrage bezüglich des Z88dk bekommen. Wer kann helfen?
Es geht um die Datei bin2p.exe, die wohl nicht vorhanden ist.
Woher bekommt man die?

Danke

Peter

t0m
Site Admin
Site Admin
Beiträge: 582
Registriert: 04.03.2004, 13:32
Wohnort: CH-5506 Mägenwil
Kontaktdaten:

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von t0m » 27.10.2008, 06:01

Hallo Peter,

das Programm ist tatsächlich nicht einfach aufzutreiben, aber auch nicht mehr nötig. Mit -create-app wird das im zcc eingebaute bin2p verwendet.

z.B. zcc +zx81 -Wall -create-app xxx.c

Ansonsten habe ich den Source sicher noch irgendwo rumliegen. Den konnte ich damals mit dem gcc problemlos übersetzten. Muss mal suchen. Werde Ihn dann hier posten.
t0m

There are 10 types of people in this world: those who understand binary and those who don't.

Benutzeravatar
bodo
User
Beiträge: 319
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von bodo » 28.10.2008, 22:02

Peter, schau dir noch einmal Teil 2 an... :wink:
B0D0: Real programmers do it in hex.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 31.10.2008, 10:13

So, ich habe erfolgreich die ersten einfachen C-Programme getestet auf dem zx81-Emulator. Funktionieren gut.

Wie kann man eigentlich jetzt mit dem z88dk die WRX-Grafik benutzen?
Einen einfachen Punkt setzen oder eine Linie setzen?

Wie kann man damit Poke und Peek auf dem zx81 benutzen?

Wie kann man die Sytemvariablen vom zx81 setzen?

Danke.

mfg
peter

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 31.10.2008, 10:59

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  char line[5];

  SLOW();
  printf(" ZX81 XModem\n\nenter start address:");
  fgets(line,5, stdin);

}

Dieses Programm wird bei mir nicht compiliert.
LEN habe ich mal durch eine Zahl ersetzt.
Wenn ich SLOW(); rausnehme, geht es.

mfg
Zuletzt geändert von zx81fan am 31.10.2008, 15:25, insgesamt 3-mal geändert.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 31.10.2008, 13:07

Mit der Routine kann ich eine Zahl/Buchstabe (1 Tastendruck) eingeben, der auch gleich geprintet wird auf dem Schirm.
Compiliert werden muss mit "-startup=2".

Mit "Return" wird das Programm beendet.

Man könnte jetzt dieses noch ausbauen.

mfg

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>

int main(void) {
   int c;

   while( (c = getchar()) !=13){ 
	    putchar(c); 
            printf("\n"); 
	}
   
}
Zuletzt geändert von zx81fan am 02.11.2008, 15:30, insgesamt 1-mal geändert.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 31.10.2008, 17:20

Hier wird der eingegebene Text solange dargestellt bis der String > 15 Char ist oder die Returntaste gedrückt wurde.
Dann wird der eingebene Text auf der nächsten Zeile ausgegeben.

Code: Alles auswählen


#include <stdio.h>
#include <stdlib.h>

int main(void) {
   	unsigned char c;
	unsigned char i;
	unsigned char satz[16];
      unsigned char zaehler;
	unsigned char test; 

      zaehler=0;
      c=0;
      test=0;

      while (1)
	{
      c = getchar();
	if ((c==13) || (zaehler==15))
		{
            test=1;
	      }
  	      else if (c>31)
		{
		putchar(c); 
		satz[zaehler]=c;
      	zaehler=zaehler+1;
		}
		
	if (test==1)
		{
		printf("\n"); 
		for(i=0;i<zaehler; i=i+1)
			{
			putchar(satz[i]); 
			}
		printf("\n"); 
		test=0;
		zaehler=0;
		}

	} 
}
Zuletzt geändert von zx81fan am 02.11.2008, 15:31, insgesamt 1-mal geändert.

Benutzeravatar
bodo
User
Beiträge: 319
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von bodo » 01.11.2008, 16:47

Moin, zx81fan(Peter)!

Herzlich Willkommen in unserem C-Kurs. Ich beantworte deine Postings hier einmal gesammelt:

-------------------------------------------------------
Wie kann man eigentlich jetzt mit dem z88dk die WRX-Grafik benutzen?
Falls du warten kannst: das kommt in Teil 18 unseres Kurses. Wenn nicht, hm, ... schreib mir 'ne PM, bitte. Die Rate der Veröffentlichungen hier richtet sich nach dem Erscheinen der Artikel im ZX-Team-Magazin, denn dieser Thread dient ja nur als Unterstützung.
Wie kann man damit Poke und Peek auf dem zx81 benutzen?
Auch das wird später (in Teil 25) erklärt, ist aber dann ganz einfach. Leider erfordert es das Verständnis eines Konzepts, von dem es heißt, es wäre soooo schwer: Zeiger und Adressen. Das stimmt nicht wirklich und wird ab Teil 21 behandelt.
Wie kann man die Sytemvariablen vom zx81 setzen?
Durch Poken, wie gehabt.

-------------------------------------------------------
Dieses Programm wird bei mir nicht compiliert.
Wenn ich SLOW(); rausnehme, geht es.
SLOW() gibt es nicht, aber zx_slow(). Dafür brauchst du auch ein #include <zx81.h>. Aber eigentlich ist das unnötig, wenn du mit -startup=2 compilierst. Denn dann ist das Programm gleich in SLOW.
LEN habe ich mal durch eine Zahl ersetzt.
Du wirst mit LEN sicher meinen, dass der Rechner die Größe der Eingabezeile einsetzen soll. Dafür gibt es auch einen Operator, den wir in Teil 16 bekommen.

Das fgets() mag der Compiler nicht, denn sie (die z88dk-Macher) haben dort wohl noch Probleme. Leider müssen wir das normale gets() benutzen, das leider keine Längenbeschränkung für die Eingabe hat...

Ein letztes noch: "return 0;" fehlt als letzte Zeile in main(). Es ist (hier!) nicht weiter schlimm, aber kann in anderen Situationen zu langer, überflüssiger Fehlersuche führen. Leider hat der ZCC dafür keine Warnmeldung.

-------------------------------------------------------
Mit der Routine kann ich eine Zahl/Buchstabe (1 Tastendruck) eingeben, der auch gleich geprintet wird auf dem Schirm.
Nicht schlecht. In Teil 19 unseres Kurses kommen wir zu Funktionen, die für solche Dinge gemacht sind und auch schnelle Spiele ermöglichen...

-------------------------------------------------------
Hier wird der eingegebene Text solange dargestellt bis der String > 15 Char ist oder die Returntaste gedrückt wurde.
Dann wird der eingebene Text auf der nächsten Zeile ausgegeben.
Oh, das ist ja schon ein komplexes Programm; winzige Kritik: mit korrekter Einrückung wäre es noch besser lesbar... ;-) Hat jemand Lust, es zu vereinfachen? (Ja, das geht!)
while (1)
Besser ist es, ein "for (;;)" zu benutzen, weil dort das "forever" besser zur Geltung kommt und keine magische Zahl (1) als "wahr" erkannt werden muss.

-------------------------------------------------------

Viel Spaß beim C-Programmieren!
B0D0: Real programmers do it in hex.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 01.11.2008, 17:56

mit korrekter Einrückung wäre es noch besser lesbar.
In meinem Notepad stimmen die eingerückten Zeilen.
Habe ihn auf "C" eingestellt, da dann auch bestimmter "C-code" dann hervorgehoben wird.
Wird irgendwie hier nicht original übernommen.

mfg

Benutzeravatar
bodo
User
Beiträge: 319
Registriert: 14.02.2007, 17:21
Kontaktdaten:

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von bodo » 01.11.2008, 18:47

Das liegt sicher daran, ob du Leerzeichen oder Tabulatorzeichen eingegeben hast. Aus diesem Problem heraus fordern praktisch alle professionellen Programmierrichtlinien die Verwendung von Leerzeichen und verbieten Tabulatoren.
B0D0: Real programmers do it in hex.

Benutzeravatar
Jens
User
Beiträge: 1142
Registriert: 23.08.2005, 13:31
Wohnort: D-31582 Nienburg/Weser

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von Jens » 01.11.2008, 21:25

die sind aber auch gemein!

:-)

gruß
jens
Der ZX81 rechnet mit allem, nur nicht mit seinem Besitzer...
Neues aus der KI-Welt... Die Automate kann sich selbst essen.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 03.11.2008, 18:04

Habe jetzt meine erste ASM-Einbindung vom z88dk erstellt.
Habe den EMU Eightyone auf WRX eingestellt und 32kb , damit er Grafikfähig ist.

Auf dem Screen(ab Adr 26496 und 26498)erscheinen dann 2 Byte die an das Unterprogramm übergeben wurden.
Funktioniert !

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>

void screen_test(unsigned char code, unsigned char code1){
#asm

    ld hl,4   //sp+4   code = 129
    add hl,sp
    ld a,(hl)
    
    ld bc,26496 // speicherstelle=Screenanfang des Grafikbereiches (WRX-Grafik)
    ld (bc),a
    
    dec hl   //sp+2   code1 = 255
    dec hl
    ld a,(hl)
    
    ld bc,26498
    ld (bc),a
     
    ret

#endasm
}


int main(void){
  unsigned char c;

  screen_test(129,255);

  c = getchar(); 
  
  return 0;
}

Zuletzt geändert von zx81fan am 04.11.2008, 08:18, insgesamt 3-mal geändert.

zx81fan
User
Beiträge: 86
Registriert: 30.10.2008, 08:26

Re: C für BASIC-Programmierer - der z88dk-Cross-Compiler

Beitrag von zx81fan » 03.11.2008, 18:44

ZX-Team-Magazin
1. Wo kann man die anschauen.

2. Ich habe festgestellt, das diese Abteilung als Lehrwerkzeug für den z88dk gedacht ist.
Kann man denn mein Fragengerümpel anderswo hinpacken oder...
da der z88dk sehr komplex ist für den zx81 und ein sehr, sehr gutes Werkzeug ist für den zx81, mein vorschlag:
Ein Kursus-Untertitel extra dafür in diesem Forum einfügen ohne unsere Zugangsberechtigung, das hat der Autor verdient und
der z88dk und diese Frageabteilung lassen.

Ich habe auch schon die Grafikroutinen getestet für den zx81 auf dem EMU von z88dk, da läuft einem das Programmierwasser im
Mund zusammen, so eine feine Sache ist das...jetzt bin ich still und freue mich auf dem weiteren z88dk-Kursus.


mfg
peter

Antworten