Programmieren
 
 
 
 
 
C-Grundkurs
 
 
 
 
 
.. Beispiel: Satz von Pythagoras (mit Eingaben IPC@CHIP)
 
 

 
 
 
 
 
Aufgabe:
In der zweiten Version der Funktion pythagoras() wurde die Eingabe der Kathetenwerte zur Laufzeit, über die Tastatur verwirklicht. Daran ändert sich in dieser Version nichts. Die Problemstellung die hier hinzukommt, ergibt sich aus dem Mangel einer Tastatur und eines Monitors beim IPC@CHIP und dem Umstand, dass dieser Rechner multitaskfähig ist. Er kann also mehrere Tasks (Programme) nebeneinander abarbeiten. Eines dieser Programme ist das Betriebssystem und dessen Server das zweite Programm ist das untere, also pythagoras.cpp, das von nun an pyth.cpp heissen muss. Diese Namensänderung ergibt sich aus dem Umstand, dass DOS-Rechner nur mit Dateinamen umgehen können, die 8 Zeichen lang sind. Die Erweiterung darf nur 3 Zeichen betragen.

Zurück zum Problem. Beide Programme, das Betriebssystem und pyth.exe können sich Eingaben von der Tastatur wünschen und hier beginnt das Dilemma. Bei welchem der beiden laufenden Programme sollen die Eingaben der Tastatur am PC landen?
Der Strom der Tastatureingaben muss also umschaltbar gemacht werden. Er ist entweder auf das Betriebssystem gerichtet, oder auf das Programm pyth.cpp. Diese Umschaltung leistet ein Unterprogramm im Betriebssystem des IPC@CHIP, das den Namen set Focus trägt.

Dieses Programm leitet über in die Architektur von IBM-kompatiblen PCs, und den Aufruf von Unterprogrammen in deren Betriebssystemen. Hierzu wird die Kenntnis der Softwareinterrupts einer 80x86 CPU benötigt, und als Mittel zu deren Aufruf die Inlineassembler-Programmierung. Doch zuvor die Vorstellung der C-Funktion setStdio(), welche die Kanalumschaltung zwischen Betriebssystem und Benutzerprogramm über den Aufruf von setFocus bewirkt und letztlich zu einem lauffähigen Programm auf dem IPC@CHIP führt.
Nebenbei mit dieser zusätzlichen Funktion ist das Programm nicht mehr auf einem PC lauffähig, denn dieser benötigt die Kanalumschaltung nicht und kann auch mit dem Unterprogramm setFocus nichts anfangen.
 
 
 
 
 
SetStdio()
Als C-Funktion programmiert sieht setStdio() etwas kryptisch aus, funktioniert aber auf jeder C-IDE .. Auch solchen ohne Assemblerprogramm
 

 


 

#include <dos.h>
static union  REGS  inregs;
static union  REGS  outregs;

...

void setStdio (char kanal)
{
  inregs.h.ah = 0x11;        // SoftINT: A0h, Fkt 11h
  inregs.h.al = kanal;       // im RTOS des IPC@CHIP
  int86(0xA0, &inregs, &outregs);
}

 

 

 

 

Als Funktion in C-Inlineassembler programmiert, lässt sich setStdio() besser erklären, kann aber nur dann verwendet werden, wenn im Umfang der IDE auch ein Assemblerprogramm enthalten ist.

 

 

 

 

void setStdio (char kanal)
{
  asm { mov ah, 11h         // SoftINT: A0h, Fkt 11h
        mov al, kanal 
        int 0A0h
      }
}

 

 

 

 

 

 

 

Mit der Kenntnis, was die Werte für den Parameter kanal bewirken, kann man die Funktion setStdio() anwenden, ohne ihre Programmierung zu verstehen. Die nachfolgende Tabelle erklärt die Wirkung für die möglichen Werte des Übergabeparameters kanal.

 

 

 

kanal

Eingaben von der Tastatur ..

Ausgaben zum Monitor ..

 

 

1

.. gelangen zum Betriebssystem

.. kommen nur vom Betriebssystem

 

 

2

.. gelangen zum Benutzerprogramm

.. kommen nur vom Benutzerprogramm

 

 

3

.. gelangen zum Betriebssystem

.. können sowohl vom Betriebssystem als auch vom Benutzerprogramm stammen. Dieser Zustand entspricht der Voreinstellung

 

 


Durch den Aufruf von setStdio(2); am Anfang des Programms pyth.exe werden Eingaben an der Tastatur, auf dieses Programm gerichtet. Seine Ausgaben gelangen wie zuvor zum Terminalbildschirm. Am Ende des Programms wird der Fokus durch setStdio(3); wieder auf das Betriebssystem gerichtet.

 

 

 

 

 


 

// pyth.cpp
// --------------  Version 20.11.2007
//                 Model: small
//                 Fliesskommaemulation ein (beim IPC@CHIP)
//                 Schwarzer, www.GoBlack.de

// Funktion zur Berechnung der Hypotenusenlänge nach dem Satz von
// Pythagoras


// Einbinden von Headerdateien mit Bibliotheksfunktionen
#include <stdio.h>             // für printf()
#include <math.h>              // für sqrt()


// Einbinden einer eigenen Headerdatei, die sich im gleichen
// Verzeichnis wie der Quelltext befindet. Zwischen den
// Gänsefüsschen muss eine Pfadangabe stehen, wenn sich die Datei
// nicht im gleichen Verzeichnis wie der Quelltext befindet.

#include "fstrgin.h"

//                                  fstrgin.h zum Kopieren ansehen
// ===============================================================

// Deklarationen von eigenen Funktionen
double pythagoras(double, double);
void   setStdio  (char kanal);


// Definition der Fkt. pythagoras()
// Berechnet die Länge der Hypotenuse in einem rechtwinkligen
// Dreieck.
// Übergaben: Länge der Katheten a und b
// Rückgabe:  Länge der Hypotenuse

double pythagoras( double a, double b)
{ 
 return(sqrt(a*a + b*b));    // Rückgabe von Wurzel aus a²+b²
}


// Definition der Fkt. setStdio()
// Schaltet beim IPC@CHIP den Fokus auf dieses Programm, bzw. das
// Betriebssystem. Beispiel Inlineassembler
// Übergabe: Kanal 1,2,3
// Rückgabe: keine

void setStdio (char kanal)
{
  asm { mov ah, 11h         // SoftINT: A0h, Fkt 11h
        mov al, kanal       // im RTOS des IPC@CHIP
        int 0A0h
      }
}


// main()
// Testprogramm für die Funktion Pythagoras auf IPC@CHIP Rechnern
// Mit Eingaben über ein Terminalprogramm auf dem PC

void main(void)
{
  double kath1;                 // Deklaration von kath1
  double kath2;                 // Deklaration von kath2
  double hypo;                  // Deklar. Von hypotenuse

  setStdio(2);                  // Fokus auf dieses Programm
 
  char txtbuf[60];              // ein Textbuffer für 60 Bytes

  printf("\r\nKathete1= ");     // Eingabeaufforderung Kathete1
  fstrgin(txtbuf, 10, FLT,"");  // Eingaben in txtbuf[] sammeln 
  kath1= atof(txtbuf);          // ASCII-Code zu Zahl wandeln

  printf("\r\nKathete2= ");     // Eingabeaufforderung Kathete2
  fstrgin(txtbuf, 10, FLT,"");  // Eingaben in txtbuf[] sammeln 
  kath2= atof(txtbuf);          // ASCII-Code zu Zahl wandeln


  hypo = pythagoras (kath1, kath2);   // Aufruf der Funktion

  printf ("\r\nHypotenuse = %f", hypo);

  setStdio(3);                  // Fokus auf das Betriebssystem
}

 


 

 

Die Ausgabeabfolge des obigen Beispiels sieht wie folgt aus:

Kathete1= _          Eingabe max. 10 Zeichen
Kathete2= _          Eingabe max. 10 Zeichen
Hypotenuse =         Ergebnis

 

 
 
 
 
Mit dem Programm verbundene Themen
Die Funktion setStdio() hat es 'in sich'. Das bezieht sich weniger auf ihre Funktionalität, die nicht übermäßig schwer zu begreifen ist, als vielmehr auf die Hintergründe, welche für die gewünschte Umschaltung verantwortlich sind.

Die Funktion setStdio() ist in C-Inlineassembler programmiert was an dem Schlüsselwort asm{} zu erkennen ist .. und daraus ergibt sich die Notwendigkeit einen kleinen Ausflug in die Assemblersprache der 80x86 CPU zu machen. Bei der Programmierung in Assembler wird aber direkt auf die Arbeitsspeicher (Register) der 80x86 CPU zugegriffen, womit auch diese betrachtet werden müssen.
Zudem ruft die Funktion ein Unterprogramm auf, welches sich im Betriebssystem (hier des IPC-Steuerrechners) befindet und dies bedingt die Behandlung der Softwareinterruptvektoren der 80x86 CPU. Die letzte Frage, wie man von den Unterprogrammen in einem Betriebssystem Kenntnis erhält, gestaltet sich dann wieder einfach, denn man muss nur das Benutzerhandbuch des jeweiligen Betriebssystems lesen, wenn man es denn erhält. Für dem ICP@CHIP ist es verfügbar und viele seiner Unterprogramme werden unter dem Menüpunkt [Betriebssystem] aufgeführt und beschrieben.
Folgende Themen stehen also zur Behandlung an ..

  Schlüsselwort asm{..}

            Inlineassemblerprogrammierung
                     Benutzerregister der 80x86 CPU
                     Assemblersprache der 80x86 CPU

            Softwareinterrupts
 

 

 

 

www..de