COMMENT ~
 PROGRAM: BIGHIYA.ASM
  AUTHOR: Denis Boyles
 RELEASE: Public Domain (Dec 13, 1996)

 COMPILE: Arrowsoft Assembler (MASM v3.0)
      OS: MS-DOS (v6.20)

 PURPOSE: the biggest hello program!?
~

;--------------------------------------
;define a constant for CGA 8x8 font
;--------------------------------------

FONT EQU 0FA6Eh                        ;CGA 8x8 font offset located in BIOS

;--------------------------------------
;define the default segments
;--------------------------------------

CODE SEGMENT
    ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
    ORG 0100h

;--------------------------------------
;program begins here and jumps data
;--------------------------------------

MAIN:
    jmp     START

;--------------------------------------
;data used for that program
;--------------------------------------

string      db  'Hi,World!',0          ;our `hello' string to print
buffer      db  82 dup(?)              ;buffer for one line of text

;--------------------------------------
;program really starts here
;--------------------------------------

START:
    mov     SI,offset string           ;DS:SI -> string to print
    call    PrintBigString             ;print the string

    mov     AX,04C00h                  ;DOS terminate program with code (0)
    int     021h                       ;call DOS to end the program

;--------------------------------------
;PrintBigString - prints a BIG string
;
;   DS:SI <= offset of string to print
;--------------------------------------

PrintBigString proc
    mov     AX,0F000h                  ;sets up our ROM BIOS segment
    mov     ES,AX

    mov     CX,0                       ;initialize outer counter to 0

PBS0:
    cmp     cx,008h                    ;have we processed 8 scan lines?
    jz      PBS3                       ;YES then exit procedure

    push    SI                         ;NO save current SI to stack
    mov     DI,offset buffer           ;point to start of our buffer

PBS1:
    lodsb                              ;load a byte from DS:SI into AL
    cmp     AL,0                       ;is 0 and the end of our string?
    jz      PBS2                       ;YES then setup for next scanline

    mov     AH,0                       ;zero out the high byte of AX so...
    shl     AX,1                       ;we can left shift the character three
    shl     AX,1                       ;times (multiply by 8) to find the
    shl     AX,1                       ;offset of the character in the FONT

    add     AX,CX                      ;then add in the current scanline
    mov     BX,AX                      ;put that into BX so we can index it
    mov     AL,ES:[BX+FONT]            ;AL=the bit pattern for font scanline
    call    CheckBits                  ;prints out current scanline to screen
    jmp     PBS1                       ;keep looping until end of string

PBS2:
    mov     word ptr [DI],00A0Dh       ;add a CR/LF to our buffer and
    mov     byte ptr [DI+2],'$'        ;terminate it with a dollar sign so

    mov     AH,009h                    ;we can use DOS print a string
    mov     DX,offset buffer           ;DS:DX -> string to print
    int     021h                       ;call DOS to print our buffered line

    pop     SI                         ;restore our SI offset for next run
    inc     CX                         ;CX=CX+1 next scanline in font
    jmp     PBS0                       ;loop until all 8 scanlines printed

PBS3:
    ret                                ;back to caller
PrintBigString endp

;--------------------------------------
;CheckBits - prints the scanline bits
;
;   AL <= current scanline from font
;--------------------------------------

CheckBits proc                         ;save CX on stack, since we use it
    push    CX

    mov     CX,8                       ;CX=8 there are 8 bits to a scanline

CB0:
    push    AX                         ;save current AX value on stack
    test    AL,128                     ;is bit 7 on?
    jz      CB1                        ;NO then `pixel' is off, print space

    mov     byte ptr [DI],0DBh         ;write block to buffer
    jmp     CB2                        ;go setup for next bit in scanline

CB1:
    mov     byte ptr [DI],020h         ;write space to buffer

CB2:
    pop     AX                         ;restore the saved AX value
    shl     AL,1                       ;shift next scanline bit into position
    inc     DI                         ;increment our buffer pointer
    repnz   loop CB0                   ;go and check again for 8 times

    pop     CX                         ;restore saved CX from stack
    ret                                ;back to caller
CheckBits endp

CODE ENDS
END MAIN
