Load a user generated character set, should work on
computers equipped with VGA cards.
Assembles with 16-bit NASM as an absolute binary image (.COM).

bits 16
org 100h
             jmp word drip0_start
    char_set: times 416 db 0
    msg       db '0o l0^d user char generated',0xd,0xa
              db 'bitmaps can also be used....',0xd,0xa,0x24
       drip0_start:
             mov ax, 0x1a00 ; is VGA/MCGA supported?
             int 0x10
             cmp al, 0x1a 
             jnz drip0_end  ; no. then exit
             mov ax, 0x13   ; set video mode to 13h
             int 0x10        
             mov ax, 0x3    ; back to text-mode
             int 0x10
             mov ax, 0x1130 ; Return current character set
             mov bh, 0x7    ; 9*16 char set
             int 0x10
             push ds       ; Returns ptr to char set in ES:BP
             push es       ; Swap DS & ES to copy char set in data area
             pop ds
             pop es
             add bp, 0x410
             mov di, char_set
             mov si, bp
             cld
             mov cx, 0x1a0 ; copy 416 bytes
             rep movsb
             push ds
             push es
             pop ds
             pop es
             mov bx, char_set
       char_modify:   
             mov al, 0x40     ; used to set bit 6
             or [bx+0xb], al  ; done here
             mov [bx+0xe], al
             mov [bx+0xd], al
             mov [bx+0xc], al
             add bx,byte +0x10 ; add 16 to offset in BX
             cmp bx,0x293      ; 293 = offset of the
                                              ; first byte of last 16 bytes
             jg load_user_gen_char
             jmp short char_modify
       load_user_gen_char:
             push ds
             push es
             pop ds
             pop es
             mov bp, char_set ; ES:BP pointer to user gen chars
             mov cx, 0x1a ; Change 26 characters
             mov dx, 0x41 ; Begin at ASCI char 'A' dec: 65
             mov bh, 0x10 ; Font Bitmap 16 bytes in length
             xor bl, bl   ; table zero
             mov ax, 0x1100  ; Load User Generated Char Set
             int 0x10
             push ds
             push es
             pop ds
             pop es
             mov ax, 0x1130  ; Return Character Set
             mov bh, 0x7     ; 9*16 Character Set
             int 0x10
             push ds
             push es
             pop ds
             pop es
             add bp, 0x610
             mov di, char_set
             mov si, bp
             cld
             mov cx, 0x1a0   ; Copy 416 bytes
             rep movsb
             push ds
             push es
             pop ds
             pop es
             mov bx, char_set
      char_modify2:
             mov al, 0x40
             or [bx+0xb], al
             or [bx+0xc], al
             or [bx+0xd], al
             or [bx+0xe], al
             add bx, byte +0x10
             cmp bx, 0x293   ; offset of the last 16 bytes in char_set
             jg load_user_char_gen2
             jmp short char_modify2
      load_user_char_gen2:
            push ds
            push es
            pop ds
            pop es
            mov bp, char_set  ; ES:BP user gen char set
            mov cx, 0x1a  ; Change 26 characters
            mov dx, 0x61  ; starting at ASCI char 'a' dec. 97 
            mov bh, 0x10  ; 16 bytes per font bitmask
            xor bl, bl    ; table zero
            mov ax, 0x1100 ; Load User Generated Character Set
            int 0x10
            push es
            pop ds
            mov ah, 0x9
            mov dx, msg
            int 0x21
            wait_key:
            mov ah, 0x6
            mov dl, 0xff
            int 0x21
            jz wait_key
      drip0_end:  
            mov ax, 0x4c00
            int 0x21

Comments or corrections are welcome.

Edited 7 Years Ago by NotNull: n/a

For the character set move you could do it manually

mov cx, 0x1a0 / 2   

CopyFnt:
   mov ax,es:[di]
   inc di
   mov ds:[si],ax
   inc si
   dec cx
   jne CopyFnt

Thanks for the reply wildgoose.
Changing the character set was one of the first things
I did while learning 8086/8088 assembly, and thought
it was really cool at the time.
I had just finished learning the basics of assembly
from a book called Programming From The Ground Up,
which only taught me AT&T syntax, this was a dilemma
for me because I could not find a good one-to-one comparison
for AT&T and INTEL syntax.
But after going through some DOS programming tutorials
MASM Bible and NGASM, I started making small DOS programs.

Good day.

Edited 7 Years Ago by NotNull: n/a

This article has been dead for over six months. Start a new discussion instead.