1. Aufgabe: Lex-Programmierung [ 8 Punkte ] In einem großen Hobbylager stehen viele Halbleiterbausteine von vielen Herstellern zur Verfügung. Die Bausteine von verscheidenen Herstellern werden üblicherweise sehr unter- schiedlich bezeichnet; es gibt viele Normen und Systeme, manche Bezeichnungen beginnen mit Großbuchstaben, z.B. BA243, KY307, BU208, SFT1445A. Eine amerikanische Norm schreibt aber ein kompaktes Bezeichnungssystem vor: die Halbleiterbausteine werden mit sechsstelligen Codes bezeichnet, wobei jede Bezeichnung aus einer Ziffer (‚1’ bezeichnet die Dioden, ‚2’ die Transistoren), dem Buchstaben ‚N’ und einer vierstelligen Zahl, deren erste Ziffer verschieden von Null sein muß, besteht – z.B. bezeichnen die Codes 1N4148, 1N5009 Dioden, 2N3055, 2N4344 Transistoren usw.
Aufgabe: Es ist ein Lex-Programm zu schreiben, das einen beliebigen Text (z.B. eine Bestandsliste des Lagers) liest, nach Bausteinbezeichnungen durchsucht und die Liste von Dioden und Transistoren, die nach der amerikanischen Norm (wie oben angeführt) bezeichnet sind, ausgibt. Es sind auch die Anzahlen der gefundenen Dioden und Transistoren (separat) zu zählen und auszugeben, z. B.:
Halbleiter mit amerikanischen Bezeichnungen ---
Von unserem Lager koennen wir Ihnen folgende Halbleiter mit amerikanischen Bezeichnungen anbieten:
1N4148 1N4007 1N4009 2N2238 2N3055
Insgesamt 3 Dioden und 2 Transistoren.
Auf Wiedersehen !
%{
/* Filtern von amerikanischen Halbleiterbezeichnungen - Code vom Text */
/* --- */
int count_di = 0; /* Zähler der erkannten Dioden */
int count_tr = 0; /* Zähler der erkannten Transistoren */
%}
diode [1]
trans [2]
digit [0-9]
digit19 [1-9]
num_bez {digit19}{digit}{digit}{digit}
%%
{diode}N{num_bez} { printf ("\t\t %s \n", yytext); count_di++; } {trans}N{num_bez} { printf ("\t\t %s \n", yytext); count_tr++; }
\n { ; } . { ; }
%%
main () {
printf ("\n\t Halbleiter mit amerikanischen Bezeichnungen \n");
printf ("\t --- \n\n");
printf ("\t Von unserem Lager koennen wir Ihnen folgende Halbleiter \n");
printf ("\t mit amerikanischen Bezeichnungen anbieten: \n\n");
yylex ();
printf ("\n\t Insgesamt %i Dioden und %i Transistoren. \n", count_di, count_tr);
printf ("\t Auf Wiedersehen ! \n\n\n");
}
%{
/* Filtern von amerikanischen Halbleiterbezeichnungen - Code vom Text */
/* --- */
int count_di = 0; /* Zähler der erkannten Dioden */
int count_tr = 0; /* Zähler der erkannten Transistoren */
%}
diode 1N[1-9][0-9][0-9][0-9]
trans 2N[1-9][0-9][0-9][0-9]
%%
{diode} { printf ("\t\t %s \n", yytext); count_di++; } {trans} { printf ("\t\t %s \n", yytext); count_tr++; }
\n { ; } . { ; }
%%
yywrap (void) { {
printf ("\n\t Insgesamt %i Dioden und %i Transistoren. \n", count_di, count_tr);
printf ("\t Auf Wiedersehen ! \n\n\n");
}
%{
/* Filtern von amerikanischen Halbleiterbezeichnungen - Code vom Text */
/* --- */
int count_di = 0; /* Zähler der erkannten Dioden */
int count_tr = 0; /* Zähler der erkannten Transistoren */
%}
quadrupel [1-9]([0-9]){3}
%%
1N{quadrupel} { printf ("\t\t %s \n", yytext); count_di++; } 2N{quadrupel} { printf ("\t\t %s \n", yytext); count_tr++; }
\n { ; } . { ; }
%%
main () {
printf ("\n\t Halbleiter mit amerikanischen Bezeichnungen \n");
printf ("\t --- \n\n");
printf ("\t Von unserem Lager koennen wir Ihnen folgende Halbleiter \n");
printf ("\t mit amerikanischen Bezeichnungen anbieten: \n\n");
yylex ();
printf ("\n\t Insgesamt %i Dioden und %i Transistoren. \n", count_di, count_tr);
printf ("\t Auf Wiedersehen ! \n\n\n");
}
4. Aufgabe: Codegenerierung und Speicherverwaltung [ 12 Punkte ] Gegeben ist das folgende Programm in C:
#include <stdio.h>
#define N 10 int k;
void main() { int u, v=5, z;
void f(int), g(int);
z = N;
f(v);
u = k;
g(u);
z = k * u - z;
}
void f (int a) { int b;
b = 2*a;
k = b + --a;
}
void g (int c) { int d, e=0;
d = c + N;
e += ++c;
k = d + e - k;
}
Aufgabe:
Variante mit allen Daten im Laufzeitstack
a) Links von diesem Programm skizzieren Sie die Blockstruktur des Programms. [ 1 Pkt. ] b) In der folgenden Tabelle vervollständigen Sie, welcher Zwischencode vom Compiler
nach der erfolgreichen Analyse des Programms generiert wird. Die Liste von Befehlen, die Sie für die Generierung verwenden sollen, finden Sie hinter der Tabelle. [ 6 Punkte ] Marke (Adresse) Befehlscode Operanden Bemerkung, Erklärung, Bedeutung, ...
L0: INC 1 k
L1: INC 3 u, v, z
L2: LIT 5
L3: STO 0, 1 v = 5
L4: JMP L43 Sprung zum Rumpf des Hauptprogramms
L5: INC 2 a, b
L6: STO 0, 0 Wert des Parameters a
L7: LIT 2
L8: LOD 0, 0 a
L9: MPY 2 * a
L10: STO 0, 1 b = 2 * a
L11: LOD 0, 1 b
L12: LOD 0, 0 a
L13: LIT 1
L14: SUB -- a
L15: STO 0, 0 -- a abspeichern
global k
main u, v, z
f() a, b
g() c, d, e
L16: LOD 0, 0 a
L17: ADD b + --a
L18: STO 1, 0 k = b + --a
L19: RET return to main
L20: INC 3 c, d, e
L21: STO 0, 0 Wert des Parameters c
L22: LIT 0
L23: STO 0, 2 e = 0
L24: LOD 0, 0 c
L25: LIT 10
L26: ADD c + N
L27: STO 0, 1 d = c + N
L28: LOD 0, 2 e
L29: LOD 0, 0 c
L30: LIT 1
L31: ADD ++c
L32: STO 0, 0 ++c abspeichern
L33: LOD 0, 0 c
L34: ADD e + ++c
L35: STO 0, 2 e = e + ++c
L36: LOD 0, 1 d
L37: LOD 0, 2 e
L38: ADD d + e
L39: LOD 1, 0 k
L40: SUB d + e – k
L41: STO 1, 0 k = d + e – k
L42: RET return to main
L43: LIT 10
L44: STO 0, 2 z = N
L45: LOD 0, 1 v
L46: CAL L5 Aufruf von f (v)
L47: LOD 1, 0 k
L48: STO 0, 0 u = k
L49: LOD 0, 0 u
L50: CAL L20 Aufruf von g(u)
L51: LOD 1, 0 k
L52: LOD 0, 0 u
L53: MPY k * u
L54: LOD 0, 2 z
L55: SUB k * u - z
L56: STO 0, 2 z = k * u - z
L57: RET Return to system
4. Aufgabe: Codegenerierung und Speicherverwaltung [ 12 Punkte ] Gegeben ist das folgende Programm in C:
#include <stdio.h>
#define N 10 int k;
void main() { int u, v=5, z;
void f(int), g(int);
z = N;
f(v);
u = k;
g(u);
z = k * u - z;
}
void f (int a) { int b;
b = 2*a;
k = b + --a;
}
void g (int c) { int d, e=0;
d = c + N;
e += ++c;
k = d + e - k;
}
Aufgabe:
Variante mit lokalen Daten im Programmcode
c) Links von diesem Programm skizzieren Sie die Blockstruktur des Programms. [ 1 Pkt. ] d) In der folgenden Tabelle vervollständigen Sie, welcher Zwischencode vom Compiler
nach der erfolgreichen Analyse des Programms generiert wird. Die Liste von Befehlen, die Sie für die Generierung verwenden sollen, finden Sie hinter der Tabelle. [ 6 Punkte ] Marke (Adresse) Befehlscode Operanden Bemerkung, Erklärung, Bedeutung, ...
L0: JMP L2 Programmanfang
L1: INC 1 Speicherplatz für k (globale Variable)
L2: JMP L4 Umsprung von lokalen Daten
L3: INC 3 u, v, z lokale Daten von main
L4: LIT 5
L5: STO L2+4 v = 5
L6: JMP L43 Sprung zum Rumpf des Hauptprogramms
L7: INC 2 a, b
L8: STO L7 Wert des Parameters a
L9: LIT 2
L10: LOD L7 a
L11: MPY 2 * a
L12: STO L7+4 b = 2 * a
L13: LOD L7+4 b
L14: LOD L7 a
L15: LIT 1
global k
main u, v, z
f() a, b
g() c, d, e
L16: SUB -- a
L17: STO L7 -- a abspeichern
L18: ADD b + --a
L19: STO L1 k = b + --a
L20: RET return to main
L21: INC 3 c, d, e
L22: STO L21 Wert des Parameters c
L23: LIT 0
L24: STO L21+8 e = 0
L25: LOD L21 c
L26: LIT 10
L27: ADD c + N
L28: STO L21+4 d = c + N
L29: LOD L21+8 e
L30: LOD L21 c
L31: LIT 1
L32: ADD ++c
L33: STO L21 ++c abspeichern
L34: ADD e + ++c
L35: STO L21+8 e = e + ++c
L36: LOD L21+4 d
L37: LOD L21+8 e
L38: ADD d + e
L39: LOD L1 k
L40: SUB d + e – k
L41: STO L1 k = d + e – k
L42: RET return to main
L43: LIT 10
L44: STO L3+8 z = N
L45: LOD L3+4 v
L46: CAL L8 Aufruf von f (v)
L47: LOD L1 k
L48: STO L3 u = k
L49: LOD L3 u
L50: CAL L22 Aufruf von g(u)
L51: LOD L1 k
L52: LOD L3 u
L53: MPY k * u
L54: LOD L3+8 z
L55: SUB k * u - z
L56: STO L3+8 z = k * u - z
L57: RET Return to system
Transportoperationen:
LIT n Bringe einen Literalwert n in den Stack
LOD lev, a bringe den Wert der Variablen mit der Relativdistanz a und der Niveaudifferenz lev in den Stack
STO lev, a bringe das oberste Stack-Element in die Variable mit der Relativdistanz a und der Niveaudifferenz lev
INC n Reserviere n Plätze im Laufzeit-Stack für den nächsten Datenraum
Sprungbefehle
JMP a springe zur Anweisung mit der Adresse a
CAL a Aufruf der Prozedur mit der Codeadresse a. Lege einen neuen Datenraum im Stack an, initialisiere den Header und springe dann zur Adresse a
RET Rückkehr aus einer Prozedur:
der aktuelle Datenraum wird freigegeben und die Programmausführung hinter der Aufrufstelle fortgesetzt Arithmetische Operationen
ADD addiere zwei Summanden am Gipfel des Stack SUB subtrahiere das oberste Stackelement vom darunter
stehenden
MPY multipliziere zwei Multiplikanden am Gipfel des Stack DIV dividiere das vorletzte Stackelement durch das oberste NEG negiere das oberste Stackelement
e) Skizzieren Sie den Inhalt des Laufzeit-Stack, falls der Zwischencode direkt interpretiert wird (zeichnen Sie den Stackinhalt nach der Interpretation jedes Befehls des Zwischen-
code): [ 5 Punkte ]
Variante mit allen Daten im Laufzeitstack
L0: L1: L2: L3: L4: L5: L6:
L7: L8: L9: L10: L11: L12: L13:
L14: L15: L16: L17: L18: L19: L20:
k k
u v z
k u v z 5
k u v=5
z
k u v=5
z
o L43
k u v=5 z=10
a b 5
k u v=5 z=10
a=5 b
k u v=5 z=10
a=5 b 2
k u v=5 z=10
a=5 b 2 5
k u v=5 z=10
a=5 b 10
k u v=5 z=10
a=5 b=10
k u v=5 z=10
a=5 b=10
10
k u v=5 z=10
a=5 b=10
10 5
k u v=5 z=10
a=5 b=10
10 5 1
k u v=5 z=10
a=5 b=10
10 4
k u v=5 z=10
a=4 b=10
10
k u v=5 z=10
a=4 b=10
10 4
k u v=5 z=10
a=4 b=10
14
k=14 u v=5 z=10
a=4 b=10
k=14 u v=5 z=10
RETURN
k=14 u=14 v=5 z=10
c d e 14
L21: L22: L23: L24: L25: L26: L27:
L28: L29: L30: L31: L32: L33: L34:
L35: L36: L37: L38: L39: L40: L41:
L42: L43: L44: L45: L46: L47: L48:
L49: L50: L51: L52: L53: L54: L55:
L56: L57:
k=14 u=14 v=5 z=10 c=14 d e
k=14 u=14 v=5 z=10 c=14 d e 0
k=14 u=14 v=5 z=10 c=14 d e=0
k=14 u=14 v=5 z=10 c=14 d e=0
14
k=14 u=14 v=5 z=10 c=14 d e=0
14 10
k=14 u=14 v=5 z=10 c=14 d e=0
24
k=14 u=14 v=5 z=10 c=14 d=24 e=0
k=14 u=14 v=5 z=10 c=14 d=24 e=0
0
k=14 u=14 v=5 z=10 c=14 d=24 e=0
0 14
k=14 u=14 v=5 z=10 c=14 d=24 e=0
0 14
1
k=14 u=14 v=5 z=10 c=14 d=24 e=0
0 15
k=14 u=14 v=5 z=10 c=15 d=24 e=0
0
k=14 u=14 v=5 z=10 c=15 d=24 e=0
0 15
k=14 u=14 v=5 z=10 c=15 d=24 e=0
15
k=14 u=14 v=5 z=10 c=15 d=24 e=15
k=14 u=14 v=5 z=10 c=15 d=24 e=15 24
k=14 u=14 v=5 z=10 c=15 d=24 e=15 24 15
k=14 u=14 v=5 z=10 c=15 d=24 e=15 39
k=14 u=14 v=5 z=10 c=15 d=24 e=15 39 14
k=14 u=14 v=5 z=10 c=15 d=24 e=15 25
k=25 u=14 v=5 z=10 c=15 d=24 e=15
k=25 u=14 v=5 z=10
RETURN
k u v=5
z 10
k u v=5 z=10
k u v=5 z=10
5
k u v=5 z=10
5
o L5
k=14 u v=5 z=10
14
k=14 u=14 v=5 z=10
k=14 u=14 v=5 z=10
14
k=14 u=14 v=5 z=10
14
o L20
k=25 u=14 v=5 z=10
25
k=25 u=14 v=5 z=10
25 14
k=25 u=14 v=5 z=10
340
k=25 u=14 v=5 z=10
340 10
k=25 u=14 v=5 z=10
330
k=25 u=14 v=5 z=340
k=25 u=14 v=5 z=340
RETURN
DSA(global) DSA(main)
DSA(f) DSA(g)