(*-----------------------------------------------*) (* Z80-INFO.INC *) (*ein Modul zum Austesten von Inline-Anweisungen *) (* der Sprache TURBO PASCAL *) (* (c)1991 H. Hagemeyer & CPC International *) (*-----------------------------------------------*) PROCEDURE Z80_INFO; TYPE str1 = STRING [10]; (*----------------------------------------------- Die Hauptregister des Z80 - Prozessors A, B, C, D, H, L und das Flagregister F sind als Byte definiert, ebenso die Hintergrundregister A', B', ... Die Reihenfolge der Definitionen darf nicht veraendert werden,da in den Inline - Anweisungen ausgenutzt wird, das F hinter A, C hinter B etc. liegt ! Die Indexregister IX und IY sind als Integer definiert, welche 2 Bytes belegen, ebenso der Stack - Pointer (Stapel - Zeiger SP) und der Programm - Counter (Programm - Zaehler PC). -------------------------------------------------*) VAR A, F, B, C, D, E, H, L, (* Hauptregister *) As,Fs,Bs,Cs,Ds,Es,Hs,Ls : BYTE; (*Hintergrundregister des Z 80 Prozessors*) IX,IY,SP,PC : INTEGER; (*Index- und Adressregister *) (*-----------------------------------------------*) (* Gibt den Hex.-Wert, eines Byte als String zurueck *) FUNCTION hexbyte (B : BYTE) : str1; (* Gibt den Hexcode eines Nibbles (4 Bit) zurueck) *) FUNCTION hexteil (x : BYTE): CHAR; CONST null = 48; (* ASCII von 0 *) A = 55; (* " von A *) BEGIN CASE x OF 0.. 9 : hexteil := Chr(x + null); (* Ziffer 0 .. 9 *) 10..15 : hexteil := Chr(x + A ); (* Ziffer A .. F *) END; END (* hexteil *); BEGIN (* hexbyte *) hexbyte := hexteil(B SHR 4) + hexteil(B AND $0F) END; (*-----------------------------------------------*) (* Gibt den Hex.-Wert zweier Bytes als String zurueck *) FUNCTION hexint (i : INTEGER) : str1; BEGIN hexint := hexbyte(i SHR 8) + hexbyte(i AND $00FF); END; (*-----------------------------------------------*) (* Gibt den Binaerwert eines Bytes als String zurueck *) FUNCTION binaerbyte (A : BYTE) : str1; VAR i : BYTE; s : str1; BEGIN s := ''; i := $80; REPEAT IF ((i AND A) <> 0) THEN s := s + '1' (* Ausblenden mit i *) ELSE s := s + '0'; IF i = $10 THEN s := s + '.'; (* In der Mitte einen . *) i := i SHR 1 (* naechstes Bit *) UNTIL i = $00; (* Herausgeschoben *) binaerbyte := s + ' '; (* Blank fuer Ausgabe anhaengen *) END; (*-----------------------------------------------*) (* Ausgabe auf dem Bildschirm der einzelnen Register. A, F, B, C, ... sind *) (*als lokale Variablen (inerhalb der Procedure Z80_info) definiert.*) PROCEDURE ausgabe; VAR ch : CHAR; BEGIN ClrScr; Write('':32); WriteLn('Z 80 - STATUS'); WriteLn; WriteLn('Erstregister:'); WriteLn; WriteLn(' A SZ-H.-PNC B C', ' D E ', ' H L'); WriteLn; Write(binaerbyte(A),binaerbyte(F)); Write(binaerbyte(B),binaerbyte(C)); Write(binaerbyte(D),binaerbyte(E)); Writeln(binaerbyte(H),binaerbyte(L)); WriteLn('$' + hexbyte(A): 6,'$' + hexbyte(F):10,'$' + hexbyte(B):10, '$' + hexbyte(C):10,'$' + hexbyte(D):10,'$' + hexbyte(E):10, '$' + hexbyte(H):10,'$' + hexbyte(L):10); WriteLn; WriteLn; WriteLn('Zweitregister'); WriteLn; WriteLn(' A SZ-H.-PNC B C', ' D E ', ' H L'); WriteLn; Write(binaerbyte(As),binaerbyte(Fs)); Write(binaerbyte(Bs),binaerbyte(Cs)); Write(binaerbyte(Ds),binaerbyte(Es)); Writeln(binaerbyte(Hs),binaerbyte(Ls)); WriteLn('$' + hexbyte(As): 6,'$' + hexbyte(Fs):10,'$' + hexbyte(Bs):10, '$' + hexbyte(Cs):10,'$' + hexbyte(Ds):10,'$' + hexbyte(Es):10, '$' + hexbyte(Hs):10,'$' + hexbyte(Ls):10); WriteLn; WriteLn; WriteLn('Index- und Adressregister'); WriteLn; WriteLn(' IX IY SP PC'); WriteLn; WriteLn('$' + hexint(IX):7,'$' + hexint(IY):10,'$' + hexint(SP):10, '$' + hexint(PC):10); WriteLn; WriteLn; Write('Weiter / Halt (W/H) ? '); REPEAT Read(Kbd,ch); ch := UpCase(ch); UNTIL ch IN ['H','W']; IF ch = 'H' THEN Halt; (* Programm abbrechen *) END; (*-----------------------------------------------*) BEGIN (* Z80_info *) INLINE( (* Registerinhalte in die entsprechenen Variablen bringen: *) $ED/$53/E/ (* LD (E),DE ;Lade D und E mit Reg. DE *) $22/L/ (* LD (L),HL ;Lade H und L mit Reg. HL *) $ED/$43/C/ (* LD (C),BC ;Lade B und C mit Reg. BC *) $F5/ (* PUSH AF ;Flags u. A *) $E1/ (* POP HL ;nach HL bringen *) $22/F/ (* LD (F),HL ;Lade (A) u. (F) mit HL = AF ! *) $08/ (* EX AF,AF' ;Tausche Register AF mit AF' *) $D9/ (* EXX ; " " *) $ED/$53/Es/(* LD (Es),DE ;Lade Ds und Es mit Reg. DE' *) $22/Ls/ (* LD (Ls),HL ;Lade Hs und Ls mit Reg. HL' *) $ED/$43/Cs/(* LD (Cs),BC ;Lade Bs und Cs mit Reg. BC' *) $F5/ (* PUSH AF ;Flags und Reg. A nach *) $E1/ (* POP HL ;HL bringen *) $22/Fs/ (* LD (Fs),A ;Lade (As) u.(Fs) mit Reg. HL *) $DD/$22/IX/ (* LD (IX),IX ;Lade (IX) mit Reg. IX *) $FD/$22/IY/ (* LD (IY),IY ;Lade (IY) mit Reg. IY *) $ED/$73/SP/ (* LD (SP),SP ;Lade (SP) mit Reg. SP *) $E1/ (* POP HL ;Rueckkehradresse holen *) $E5/ (* PUSH HL ;und retten *) $22/PC/ (* LD (PC),HL ;Lade (PC) mit Reg. HL *) $CD/ausgabe/ (* CALL AUSGABE *) (* Da bei der Ausgabe die Register veraendert werden, wird im folgenden der urspruengliche Zustand wiederhergestellt. *) $2A/Fs/ (* LD HL,(Fs) ;Lade HL mit Speicher As u. Fs *) $E5/ (* PUSH HL ; und *) $F1/ (* POP AF ;bringe dieses nach AF *) $ED/$5B/Es/ (* LD DE,(Es) ;Lade DE mit Speicher Ds u. Es *) $2A/Ls/ (* LD HL,(Ls) ;Lade HL mit Speicher Hs u. Ls *) $ED/$4B/Cs/ (* LD BC,(Cs) ;Lade BC mit Speicher Bs u. Cs *) $08/ (* EX AF,AF' ;Tausche Register AF mit AF'*) $D9/ (* EXX ; " " *) $2A/F/ (* LD HL,(F) ;Lade HL mit Speicher A u. F *) $E5/ (* PUSH HL ; und *) $F1/ (* POP AF ;bringe dieses nach AF *) $ED/$5B/E/ (* LD DE,(E) ;Lade DE mit Speicher D u. E *) $2A/L/ (* LD HL,(L) ;Lade HL mit Speicher H u.L *) $ED/$4B/C/ (* LD BC,(C) ;Lade BC mit Speicher B u. C *) $DD/$2A/IX/ (* LD IX,(IX) ;Lade IX mit Speicher IX *) $FD/$2A/IY/ (* LD IY,(IY) ;Lade IY mit Speicher IY *) $ED/$7B/SP (* LD SP,(SP) ;Lade SP mit Speicher SP *) ); END;