CSEG        SEGMENT
            ASSUME CS:CSEG,DS:DSEG

CR          EQU  13           ; Carriage Return
LF          EQU  10           ; Line Feed

DISP_BLOCK  PROC NEAR
            MOV  AX,DSEG      ; Initialisierung DS mit Adresse vom Segment DSEG
            MOV  DS,AX
            MOV  BX,0         ; BX : Indizierung BLOCK
            MOV  CX,16        ; CX (DISP_BLOCK) : Anzahl Zeilen
LINE_LOOP:
            CALL DISP_LINE
            MOV  AH,02h       ; MS-DOS Funktion 2, Zeichenausgabe
            MOV  DL,CR        ; entspricht MOV DL,13
            INT  21h
            MOV  DL,LF        ; entspricht MOV DL,10
            INT  21h
            ADD  BX,16        ; naechste Zeile
            LOOP LINE_LOOP    ; alle Zeilen bearbeitet ?
            MOV  AX,4C00h
            INT  21h
DISP_BLOCK  ENDP

DISP_LINE   PROC NEAR
            PUSH CX           ; CX aus DISP_BLOCK sichern
            MOV  CX,16        ; CX (DISP_LINE) : Anzahl Spalten
            PUSH BX           ; Index sichern (Zeilenanfang)
HEX_LOOP:
            MOV  DL,BLOCK[BX] ; hoeherwertige Bits ausgeben
            PUSH CX           ;   hoeherwertige Bits rechtsschieben
            MOV  CL,4
            SHR  DL,CL
            POP  CX
            CALL WRITE_DIGIT
            MOV  DL,BLOCK[BX] ; niederwertige Bits ausgeben
            AND  DL,0Fh       ;   niederwertige Bits maskieren
            CALL WRITE_DIGIT
            MOV  AH,02h       ; MS-DOS Funktion 2, Zeichenausgabe
            MOV  DL,' '
            INT  21h
            INC  BX           ; naechste Spalte
            LOOP HEX_LOOP     ; alle Spalten (Zahlen) bearbeitet ?

            POP  BX           ; Index restaurieren (Zeilenanfang)
            PUSH BX           ; Index sichern (Zeilenanfang)
            MOV  CX,16        ; CX (DISP_LINE) : Anzahl Spalten
ASCII_LOOP:
            MOV  AH,02h       ; MS-DOS Funktion 2, Zeichenausgabe
            MOV  DL,BLOCK[BX]
            CMP  DL,20h       ; Zeichen druckbar ?
            JAE  DRUCKBAR     ; ja, ausgeben
            MOV  DL,'.'       ; nein, stattdessen . ausgeben
DRUCKBAR:
            INT  21h
            INC  BX           ; naechste Spalte
            LOOP ASCII_LOOP   ; alle Spalten (Zeichen) bearbeitet ?

            POP  BX           ; Index ruecksichern (Zeilenanfang)
            POP  CX           ; CX fuer DISP_BLOCK restaurieren
            RET
DISP_LINE   ENDP

WRITE_DIGIT PROC NEAR
            ADD  DL,30h       ; ASC-II Code der Ziffer generieren
            CMP  DL,3Ah       ; Ziffer gehoert der Gruppe 0..9 an ?
            JB   DIGIT_OK
            ADD  DL,07h       ; ASC-II Code korrigieren
DIGIT_OK:
            MOV  AH,02h       ; MS-DOS Funktion 2, Zeichenausgabe
            INT  21h
            RET
WRITE_DIGIT ENDP

CSEG        ENDS

DSEG        SEGMENT
BLOCK       DB   16 DUP (30h) ; 16 Zeilen * 16 Spalten
            DB   16 DUP (31h)
            DB   16 DUP (32h)
            DB   16 DUP (33h)
            DB   16 DUP (34h)
            DB   16 DUP (35h)
            DB   16 DUP (36h)
            DB   16 DUP (37h)
            DB   16 DUP (38h)
            DB   16 DUP (39h)
            DB   16 DUP (3Ah)
            DB   16 DUP (3Bh)
            DB   16 DUP (3Ch)
            DB   16 DUP (3Dh)
            DB   16 DUP (3Eh)
            DB   16 DUP (3Fh)
DSEG        ENDS

SSEG        SEGMENT STACK
            DW   256 DUP (?)
SSEG        ENDS
               
            END  DISP_BLOCK