The MASM Forum Archive 2004 to 2012

Miscellaneous Forums => 16 bit DOS Programming => Topic started by: zak100 on August 28, 2009, 05:34:37 AM

Title: Displaying a character on two consecutive lines
Post by: zak100 on August 28, 2009, 05:34:37 AM
Hi,
I have a simple program which should display two As on two consecutive lines (line 1 and line 2) but its not working.
The code is given below:


.model tiny
.386
.code
start:

    jmp test1
test1:
    cld
    mov cx,2
    mov ax,0B800h
    next: mov es,ax
    push ax
    xor di,di
    mov ax,4A41h
    stosw
    pop ax
    add ax, 50h
    Loop next
loop1:
    jmp loop1

org 510

    dw 0AA55h

end start



It prints the next 'A' after four or five lines. Can somebody plz help me with this program??

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 28, 2009, 09:42:44 AM
mov ax,0b800h and mov ds,ax
those instructions sould be before the loop
once you have the ES register set to B800h, leave it alone

you want to add to DI, instead
and, i think you have to add 0A0h for each line - not 50h
that is because each character is 2 bytes (char and attribute)
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on August 28, 2009, 10:10:38 AM
Hi,
I have changed the code to following but still its not printing the next 'A' at the start of next line:


.model tiny
.386
.code
start:

    jmp test1
test1:
    cld
    mov cx,2
    xor di,di
    mov ax,0B800h
    mov es,ax
    mov ax,4A41h
next:stosw
    add di, 50h
    Loop next
loop1:
    jmp loop1

org 510

    dw 0AA55h

end start



My logic is to add 80D to B800H so that I would be at the start of next line. Note each line can have 80 characters.  At this point I dont want to use 0AH. However it can be done through it also.

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 28, 2009, 10:18:02 AM
Quotejmp test1
test1:
what is that ? - lol
get rid of those lines

        cld
        mov     ax,0B800h
        mov     es,ax
        xor     di,di

        mov     ax,4A41h
        mov     cx,2

next:   stosw
        add     di,158         ;160-2
        loop    next

loop1:  jmp loop1



Title: Re: Displaying a character on two consecutive lines
Post by: MichaelW on August 28, 2009, 10:52:30 AM
Quote from: zak100 on August 28, 2009, 10:10:38 AM
My logic is to add 80D to B800H so that I would be at the start of next line. Note each line can have 80 characters.  At this point I dont want to use 0AH. However it can be done through it also.

Adding 80 to the segment address will shift the absolute address 80 * 16 = 1280 bytes = 8 lines further down in the buffer. Before you decide to use segment indexing for this, you should first learn how segment addressing works:

absolute address = (segment address SHL 4) + offset address

In general, when dealing with a buffer that will fit in a single segment, you should leave the segment address fixed and manipulate the offset address.
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on August 28, 2009, 12:39:04 PM
Hi,
Thanks for the help. I am able to print 25 As, one one on each line.

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 28, 2009, 02:56:48 PM
ok Zulfi
you should be able to display whatever you like, and in multiple colors, too - lol
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on August 29, 2009, 10:13:15 AM
I have not checked but I want to know can we display images also using BIOS?

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 29, 2009, 10:29:01 AM
sure - set the video mode and put pixels in the buffer, rather than characters
the simplest graphics modes are:
320 x 200, 4 color
640 x 400, 16 color
320 x 200, 256 color
all other graphics modes are very tricky to program
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on August 29, 2009, 12:02:04 PM
Hi Zulfi.,

QuoteI have not checked but I want to know can we display images also using BIOS?

   Yes, INT 10H is the video BIOS interrupt.

   Use function 0 (zero) to set the video mode.


        MOV     AH,0    ; Function 0
        MOV     AL,13H  ; set 320 x 200 256 color mode
        INT     10H     ; Video BIOS Call


   Use function 0CH to write a pixel.


        MOV     AH,0CH  ; function 0CH
        MOV     BH,0    ; page number
        MOV     CX,100  ; X or column
        MOV     DX,100  ; Y or row
        MOV     AL,15   ; Color value
        INT     10H     ; Video BIOS Call


   Or some such.

'Luck,

Steve

Edit, fix wrong function 0B => 0C.

SRN
Title: Re: Displaying a character on two consecutive lines
Post by: MichaelW on August 29, 2009, 11:43:13 PM
Zulfi,

The BIOS SetPixel function is easy to use, but it's slow. For mode 13h (320x200, 256-color), drawing pixels by accessing the display buffer directly is simple and easy to do, and much faster than using the BIOS.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 29, 2009, 11:50:33 PM
i'm with Michael on that one
320 x 200, 256 color mode is simple to program
the pixels are a little too large for detailed work like pictures, though
but, you can make some fun stuff with that mode, nonetheless
each pixel is represented by a byte, which makes it very easy to do lines and circles and all that
i think it is an ideal mode for beginners to start out on graphics
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on August 30, 2009, 01:15:00 PM
Hi,

   Actually, Micheal is right.  Once you have done it a few
times, BIOS calls are less convenient (easy) than doing it
directly in mode 13H.  However, that wasn't the question
asked (nit pick!).  And I think it is a good way to start out.
Modes 4, 6, 12H, and 13H for instance use the same form
with the BIOS function, but are quite different with direct
memory writes.

   Dave is right that mode 13H is a bit coarse, so try 11H
and 12H for finer detail.  Less colors though, so images
need to be selected carefully to look good.

Cheers,

Steve N.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on August 30, 2009, 02:50:04 PM
the problem with larger resolutions is, the buffer no longer fits into a single segment
for those video modes, you either have to use BIOS calls to place pixels (slow) or get fancy with the video CRT registers
for mode 13h, the entire screen fits into a single segment and you can calculate the address of a pixel:
Address = 320 * Y + X
(X,Y = 0,0 is the upper left corner of the display)
you have a palette of 256 colors from 262,144 possible values
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on August 30, 2009, 04:48:01 PM
Hi,

   All of the standard VGA modes are addressed in a single
segment.  Only when you use SVGA or VESA modes does
that require more than one segment's address range.

   And yes, while 640 x 480 = 307,200, which would seem
to require more than one 65,536 byte segment, it doesn't.
You multiplex 8 pixels per byte, and start playing with
color "planes".  And getting used to that is a whole 'nother
kettle of fish.  Talk about ignoring the man behind the curtain.

   Starting with BIOS functions may be the first step on a
fairly interesting journey.  But it is a fairly easy step to take.

Cheers,

Steve N.
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on September 05, 2009, 01:30:32 PM
Hi,

   As the speed of BIOS functions versus writing to memory
is always brought up when a put pixel is mentioned, I put
together two throw-away programs.  One each for video
mode 12H and 13H.  And assembled for both BIOS calls
and direct memory writes.  Note: the memory write routines
are general purpose, and while good, are not optimized for
speed.

Enjoy,

Steve N.
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on September 07, 2009, 04:58:44 AM
Thanks for these replies. It would take sometime for me to start graphics.

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on September 08, 2009, 04:06:34 AM
Hi,
Steve, I ran your application and found them very interesting. I dont thing I would be doing such a beautiful stuff but its something I must appreciate. Its a new idea. I havent seen them before. I might consider such exercises for my graphics course.

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on September 09, 2009, 04:33:20 PM
Hi Zulfi,

   Glad you liked them.  Most benchmarks are a bit dull so I used
some existing code to make them a bit more colorful.

   Since I did print out the times for the 16 color program, I'll
post some results for our friends in the Laboratory sub-forum
that like to see numbers.  "Undocumented DOS" showed
that DOS interrupts could slow down by factor of ten when
run under a protected mode environment.  So I ran that
experiment, but didn't see that dramatic an effect.  Though
I may have to try that on the Win 98 machine.

Cheers,

Steve N.


Shows Pythagorean triangles.

  BIOS time:   Subroutine time:
                             Pentium III, Matrox Video
  0:01:14.47   0:00:36.47        OS/2 4.0 VDM
  0:01:11.07   0:00:25.65        Windows 2000 Command Prompt
  0:00:33.89   0:00:24.01        DOS 5.0 HIMEM.SYS
  0:00:32.63   0:00:23.18        DOS 5.0

                             Pentium, Western Digital Video
  0:01:45.57   0:00:56.91        DOS 6.2x
  0:02:32.86   0:01:02.78        DOS 6.2x HIMEM.SYS EMM386.SYS
  0:02:28.51   0:01:03.06        As above + Windows 3.11 MS-DOS Prompt
  0:02:38.71   0:01:03.59        OS/2 4.0 VDM

                             Pentium MMX, Nvidia Video
  0:03:59.97   0:00:45.98        Windows 98

                             AMD 64, RADEON Video
  0:00:58.55   0:00:25.98        Windows XP
  0:00:40.75   0:00:26.26        DOS 5.0
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on September 10, 2009, 06:13:35 AM
Hi,
I dont know much about what you have said and what you have done but as a programmer I want to tell something about win98. It gave me problem of spaces but later on when I was working on TurboC (DOS application) and trying hard to take the printout of graphics stuff, it came out that this can only be done on win 98.

Zulfi.
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on September 10, 2009, 06:20:57 AM
hi Zulfi
yah - some programmers wanted fast graphics
on older systems, that meant programming the video card directly
while some of that can be done under NT+ OS's, not all functionality may be available
in general, XP and other newer OS's do not allow direct i/o
i have played with it a little bit, and i see you are able to program the palette registers, etc (XP Pro, here)
from a boot floppy, though, you do not have any limitations, because you are providing the OS
Title: Re: Displaying a character on two consecutive lines
Post by: zak100 on September 11, 2009, 03:49:45 AM
Hi Steve,
I am also interested in your timing work.Have  you done it programmatically? Once I tried to compare the timings of a pool of threads with a standalone program.In that case, I used the prime number program. But I was not printing the timings. If its not a secret and if you have some spare time, kindly guide me how you accomplished this task??

Zulfi.   
Title: Re: Displaying a character on two consecutive lines
Post by: dedndave on September 11, 2009, 04:21:51 AM
Zulfi
most of us use timing macros by MichaelW
the macros are available in the first post of the first thread in the Laboratory Forum
there are two sets - slightly different
timers.asm and counter2.asm
d/l them, unzip them, and place them in the \masm32\macros folder
here is an example program....
Title: Re: Displaying a character on two consecutive lines
Post by: Magnum on September 11, 2009, 12:20:46 PM
Quote from: FORTRANS on September 05, 2009, 01:30:32 PM
Hi,

   As the speed of BIOS functions versus writing to memory
is always brought up when a put pixel is mentioned, I put
together two throw-away programs.  One each for video
mode 12H and 13H.  And assembled for both BIOS calls
and direct memory writes.  Note: the memory write routines
are general purpose, and while good, are not optimized for
speed.

Enjoy,

Steve N.

Good coding. Thanks a lot.
I may copy them to my floppy boot disk and compare the speed with running under XP.

Andy
Title: Re: Displaying a character on two consecutive lines
Post by: FORTRANS on September 13, 2009, 03:14:18 PM
Quote from: zak100 on September 11, 2009, 03:49:45 AM
Hi Steve,
I am also interested in your timing work.Have  you done it programmatically? Once I tried to compare the timings of a pool of threads with a standalone program.In that case, I used the prime number program. But I was not printing the timings. If its not a secret and if you have some spare time, kindly guide me how you accomplished this task??

Zulfi.   

Hi,

   Not a secret at all, I use the DOS function 2CH (44) "Get
Time".  I call it before running the benchmark, and then
again when the benchmark is complete.  Subtract the values,
format for printing, and print them.


; Let the program time stuff.
        SCALL GTIME      ; MS-DOS fn 2CH
        MOV     [FHun],DL
        MOV     [FSec],DH
        MOV     [FMin],CL
        MOV     [FHour],CH


   Calling again and subtracting is pretty dull, so I'll
skip that.  Here is the format and print.  SCALL is
a simple macro to call MS-DOS functions with a mnemonic.
CONOUT is "Console Output" function 2, which prints
a character.


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OutSaveT:       ; Output saved time.
                ; 26 September 2007, SRN
; Enter: BX, Offset into saved time array.
; Uses  AX, CX, DX.

        MOV     DL,' '
        SCALL CONOUT

; MS-DOS System Time
; CH = Hour, CL = Minute, DH = Seconds, DL = 1/100 s

        XOR     AH,AH
        MOV     AL,[Fhour+BX]   ; Play with hour
        AAM     ; ASCII Adjust AX after Multiply (unpack BCD digits).
        OR      AX,3030H
        CMP     AH,30H ; suppress leading zero?
        JNZ     OST_1
        MOV     AH,' '
OST_1:  PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,':'
        SCALL CONOUT

        MOV     AL,[FMin+BX]    ; Play with minutes
        XOR     AH,AH
        AAM                     ; unpack
        OR      AX,3030H        ; convert binary to ASCII
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,':'
        SCALL CONOUT

        XOR     AH,AH
        MOV     AL,[FSec+BX]    ; Play with seconds
        AAM
        OR      AX,3030H
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        MOV     DL,'.'
        SCALL CONOUT

        XOR     AH,AH
        MOV     AL,[FHun+BX]    ; Play with 1/100 seconds
        AAM
        OR      AX,3030H
        PUSH    AX
        MOV     DL,AH
        SCALL CONOUT
        POP     AX
        MOV     DL,AL
        SCALL CONOUT

        RET

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   Hm, probably should skip the hundredths of a second.

HTH,

Steve N.
Title: Re: Displaying a character on two consecutive lines
Post by: Magnum on September 13, 2009, 06:57:51 PM
Quote from: zak100 on August 29, 2009, 10:13:15 AM
I have not checked but I want to know can we display images also using BIOS?

Zulfi.

I dug this out of 16 bit code dungeon and attached to source code and com file.

Andy


;  AMB2.ASM  [ For DOS ] Much help from Annie from alt.lang.asm newsgroup
;  An ambulance races across the bottom of the screen
;  with its siren wailing and its light flashing.
;
;  Code added to turn off cursor allows this to work in a DOS box under
;  Win XP.
;
;   Animation code extracted from the "Ambulance"
;   by AK   10/02
;
.model  tiny
.386
.code
org     100h                    ; DOS .COM file

begin:
        jmp     start                   ; go start the program
;
BDA_addr                equ     40h     ; BDA (Bios Data Area) segment address
BDA_video_mode          equ     49h     ; BDA location of current video mode
BDA_timer_counter       equ     6Ch     ; BDA location of nmbr of timer ticks
                                        ; (18.2 per second) since midnight
counter dw      9
;
start:
        mov     ch,10h                  ; set bits to turn cursor off
        call    cursor                  ; do it
host:
        nop
;
real_start:
        call    find_displacement
        db      01h                     ; Used to make this add up to 3 bytes
find_displacement:
        pop     si
        sub     si, offset host
        call    payload
next_step:
        ret

payload:
        push    es
        mov     ax, word ptr [si+counter-4]
        and     ax, 00000111b
        cmp     ax, 00000110b          ; Show payload every eighth
                                        ; (starting with the sixth) time
;
; Did we already show the car?
;
        mov     ax, BDA_addr
        mov     es, ax
        call    show_payload
exit_payload:
        pop     es
        mov     ch,5                    ; set bits to turn cursor on
        mov     cl,6                    ; ditto
        call    cursor                  ; go do it
        int     20h                     ; exit to DOS
;
; Setup and show the 'ambulance car'
;
show_payload:
;
; Check video mode
;
; Text mode 3 (80x25) - video buffer address (color) = 0B800h
; Text mode 7 (80x25) - video buffer address (monochrome) = 0B000h
;
        push    ds
        mov     di, 0B800h
        mov     ax, BDA_addr
        mov     ds, ax
        mov     al, ds:BDA_video_mode
        cmp     al, 7                   ; Check which video mode we're
        jne     setup_video_n_tune      ; on, if not Monochrome text
        mov     di, 0B000h              ; mode 7, assume mode 3

setup_video_n_tune:
        mov     es, di
        pop     ds
        mov     bp, 0FFF0h              ; Setup number of tones to play
                                        ; (will increment up to 50h)
setup_animation:
        mov     dx, 0                   ; Setup ambulance_data column
        mov     cx, 16                  ; Number of characters that make
                                        ; up one ambulance_data line
do_ambulance:
        call    show_ambulance          ; Print the ambulance to screen
        inc     dx
        loop    do_ambulance
        call    play_siren              ; Play a tone of the 'siren'
        call    wait_tick               ; and wait for a tick
        inc     bp
        cmp     bp, 50h                 ; Already played the 'ambulance
        jne     setup_animation         ; siren' tune 12 times?
        call    speaker_off             ; If yes, then turn speaker off
        push    ds
        pop     es
        ret
;
; Turn the PC speaker off
;
; 8255 PPI - Programmable Peripheral Interface
; Port 61h, 8255 Port B output
;
; (see description below)
;
speaker_off:
        in      al, 61h
        and     al, 11111100b          ; Disable timer channel 2 and 'ungate'
        out     61h, al                 ; its output to the speaker
        ret
;
; Turn on the speaker and play the "ambulance siren" sound
;
; Select tone frequency to generate
;
; Tone frequency is selected by means of the 3rd least significant bit of BP
;
;
; Bit(s)                        Description
; ------                        -----------
; ... 3 2 1 0
; ... x 0 x x                    Play 1st tone frequency
; ... x 1 x x                    Play 2nd tone frequency
;
; If we consider A to be the 1st tone and B to be the 2nd tone,
; then the whole 'ambulance siren' tune will be: (AAAABBBB) x 12
;
play_siren:
        mov     dx, 07D0h               ; "ambulance siren" 1st tone freq.
        test    bp, 00000100b          ; Check if we are to play
        jz      speaker_on              ; the first or the second
                                        ; tone frequency
        mov     dx, 0BB8h           ; "ambulance siren" 2nd tone frequency
;
; Turn on the speaker
;
; 8255 PPI - Programmable Peripheral Interface
; Port 61h, 8255 Port B output
;
; Bit(s)                        Description
; ------                        -----------
; 7 6 5 4 3 2 1 0
; . . . . . . . 1                Timer 2 gate to speaker enable
; . . . . . . 1 .                Speaker data enable
; x x x x x x . .                Other non-concerning fields
;
speaker_on:
        in      al, 61h
        test    al, 00000011b          ; If speaker is already on, then
        jnz     play_tone               ; play the sound tone
        or      al, 00000011b          ; Else, enable timer channel 2 and
        out     61h, al                 ; 'gate' its output to the speaker
;
; Program the PIT
;
; 8253 PIT - Programmable Interval Timer
; Port 43h, 8253 Mode Control Register
;
; Bit(s)                        Description
; ------                        -----------
; 7 6 5 4 3 2 1 0
; . . . . . . . 0                16 binary counter
; . . . . 0 1 1 .                Mode 3, square wave generator
; . . 1 1 . . . .                Read/Write LSB, followed by write of MSB
; 1 0 . . . . . .                Select counter (channel) 2
;
        mov     al, 10110110b          ; Set 8253 command register
        out     43h, al                 ; for mode 3, channel 2, etc
;
; Generate a tone from the speaker
;
; 8253 PIT - Programmable Interval Timer
; Port 42h, 8253 Counter 2 Cassette and Speaker Functions
;
play_tone:
        mov     ax, dx
        out     42h, al                 ; Send LSB (Least Significant Byte)
        mov     al, ah
        out     42h, al                 ; Send MSB (Most Significant Byte)
        ret
;
; Show the 'ambulance car'
;
show_ambulance:
        push    cx
        push    dx
        lea     bx, [si+ambulance_data-4]
        add     bx, dx                  ; Setup which ambulance_data column
                                        ; we're going to print
        add     dx, bp                  ; Don't show ambulance_data columns
        or      dx, dx                  ; which aren't still visible
        js      ambulance_done
        cmp     dx, 50h                 ; Check if the column we're printing
        jae     ambulance_done          ; is past the screen limit
                                        ; If yes,  then don't print it
        mov     di, 3200                ; Point to start of screen's 64th line
        add     di, dx                  ; Point to the column we're supposed
        add     di, dx                  ; to be printing at
        sub     dx, bp                  ; Restore to initial column value
        mov     cx, 5                   ; Set it up so we're in the first line

decode_character:
        mov     ah,4d                    ; Set color attribute to red
;                                        ; 7 = white
; Decode the character
;
; It's really pretty ingenius. Each character is encoded in such a way
; that for each line beyond the first one, that character is incremented
; by one -- and for each column beyond the first, the same thing happens.
; So taking that into account, it's not difficult to understand how it
; all works, and how to decode the ambulance_data.
;
        mov     al, [bx]                ; Get the character
        sub     al, 7
        add     al, cl                  ; Account for which line we're in
        sub     al, dl                  ; Account for which column we're in
        cmp     cx, 5                   ; Are we in the first line?
        jne     print_character         ; If we are, then...
        mov     ah,1                    ; Set color attribute to hi-inten blue
        test    bp, 00000011b           ; Is this the ending tone of a AAAA or
                                        ; BBBB tune sequence?
        jz      print_character         ; If not, then go ahead and print the
                                        ; 'siren' characters
        mov     al, ' '                 ; Else, replace them with a ' ' (to
                                        ; accomplish the visual 'siren' effect
print_character:
        stosw                           ; Print the character to screen
        add     bx, 16                  ; Point to next ambulance_data line
        add     di, 158                 ; Point to next screen line
        loop    decode_character
ambulance_done:
        pop     dx
        pop     cx
        ret
;
; Wait for one tick (18.2 per second) to pass
;
wait_tick:
        push    ds
        mov     ax, BDA_addr
        mov     ds, ax
        mov     ax, ds:BDA_timer_counter ; Get ticks since midnight
check_timer:
        cmp     ax, ds:BDA_timer_counter ; Check if one tick has
        je      check_timer              ; already passed
        pop     ds
        ret
;
; Our cursor manipulation routine.
;
cursor:
        mov     ah,1                    ; function 1 - cursor control
        int     10h                     ; call ROM BIOS video services
        ret                             ; return to caller
;
; Data from here below
;
ambulance_data:
   first_line   db     22h, 23h, 24h, 25h, 26h, 27h, 28h, 29h, 66h, 87h, 3Bh
                db     2Dh, 2Eh, 2Fh, 30h, 31h
   second_line  db     23h, 0E0h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E6h, 0E7h
                db     0E7h, 0E9h, 0EAh, 0EBh, 30h, 31h, 32h
   third_line   db     24h, 0E0h, 0E1h, 0E2h, 0E3h, 0E8h, 2Ah, 0EAh, 0E7h
                db     0E8h, 0E9h, 2Fh, 30h, 6Dh, 32h, 33h
   fourth_line  db     25h, 0E1h, 0E2h, 0E3h, 0E4h, 0E5h, 0E7h, 0E7h, 0E8h
                db     0E9h, 0EAh, 0EBh, 0ECh, 0EDh, 0EEh, 0EFh
   fifth_line   db     26h, 0E6h, 0E7h, 29h, 59h, 5Ah, 2Ch, 0ECh, 0EDh, 0EEh
                db     0EFh, 0F0h, 32h, 62h, 34h, 0F4h