Skip to content

Instantly share code, notes, and snippets.

@muspellsson
Created February 15, 2011 20:06
Show Gist options
  • Save muspellsson/828130 to your computer and use it in GitHub Desktop.
Save muspellsson/828130 to your computer and use it in GitHub Desktop.
99 bottles of beer in FASM bootsector
;=======================================================================
; an x86 bootsector implementation of
; 99 bottles of beer
; by Ivan Sukin <isukin.intelliware@gmail.com>
; based on template made by shoorick
;=======================================================================
;=======================================================================
; Drive info
;=======================================================================
_bps equ 512 ; bytes per sector
_spt equ 18 ; sectors per track
_hds equ 2 ; number of heads
_trs equ 80 ; number of tracks
;=======================================================================
; First 3 bytes of bootsector
; Must be E9XXXX or EBXX90.
; 7C00h is the address where
; bootsector is put by BIOS
;=======================================================================
org 7C00h ; starting address
mov cx, 99 ; set CX to 99 right here
jmp short start ; short jmp (EB XX)
;=======================================================================
; Bootsector record (1 byte after standard)
;=======================================================================
more db "o more " ; OEM name and version (8 B)
more_l = $ - more ; !!! dirty hack
; !!! I've put some string here
dw _bps ; bytes per sector
db 1 ; sectors per allocation unit
dw 1 ; reserved sectors
db 2 ; number of FATs
dw 224 ; number of root dir entries
dw 2880 ; total sectors in logical volume
db 0F0h ; media descriptor byte
dw 9 ; number of sectors per FAT
dw _spt ; sectors per track
dw _hds ; number of heads
dd 0 ; number of hidden sectors
dd 0 ; total sectors in logical volume
; if volume size > 32 MiB
db 0 ; physical drive number
db 0 ; reserved
db 29h ; Extended Boot Signature record (29h)
dd 0 ; 32-bit binary volume ID
is db "Ivan Sukin " ; volume label (11 B)
db "(C) 2011" ; reserved (8 B)
is_l = $ - is ; !!! dirty hack
; !!! I've put my name here
;=======================================================================
; Entry point
;=======================================================================
start:
; Point segment registers to the beginning of current segment
mov ax, cs
mov ds, ax
; loop: begin
@@:
call put_cx_99
cmp cl, 1
je short cx_is_1
call print_bott1
call put_cx_99
call print_bott2
call print_endl1
call print_bott3
; print cx - 1
dec cx
call put_cx_99
; if next_value_of_cx == 1 then goto cx_will_be_1
cmp cl, 1
je short cx_will_be_1
; else
call bott4_endl
jmp short @b
; loop: end
cx_will_be_1:
mov dx, b5_l
call bott5_helper
jmp short @b
; loop: end
cx_is_1:
mov dx, b6_l
call bott5_helper
mov al, ","
call put_char
mov al, " "
call put_char
call put_cx_99
mov dx, b7_l
call bott5_helper
call print_endl1
call print_bott3
mov al, "N"
call put_char
call print_more
call bott4_endl
cx_is_0:
mov ax, "N"
call put_char
call print_more
call print_bott1
mov al, "n"
call put_char
call print_more
call print_bott2
call print_endl1
mov dx, store_l
mov si, stor
call put_str
mov cx, 99
call put_cx_99
call bott4_endl
mov dx, is_l
mov si, is
call put_str
xor ah, ah
int 16h ; INT 16h -- function 00, Get keystroke
int 19h ; INT 19h -- Bootstrap loader
; (reboot)
;=======================================================================
; Many helper and printer procedures
; written for code shortening
;=======================================================================
bott4_endl:
call print_bott4
call print_endl
ret
print_more:
mov dx, more_l
mov si, more
call put_str
ret
bott1_helper:
mov si, bott_1
call put_str
ret
bott5_helper:
mov si, bott_5
call put_str
ret
print_bott1:
mov dx, b1_l
call bott1_helper
ret
print_bott2:
mov dx, b2_l
call bott1_helper
ret
print_bott3:
mov dx, b3_l
mov si, bott_3
call put_str
ret
print_bott4:
mov dx, b4_l
call bott1_helper
ret
print_endl:
mov dx, endl_l
mov si, endl
call put_str
ret
print_endl1:
mov dx, endl_l1
mov si, endl
call put_str
ret
;=======================================================================
; Simple printing procedures
;=======================================================================
;=======================================================================
; Procedure put_char
; al -- character to output
; Uses: ax
;=======================================================================
put_char:
mov ah, 0Eh
int 10h
ret
;=======================================================================
; Procedure put_cx_99
; Puts a value of CX
; assuming that it's in range
; 0 - 99
; Uses: ax, bx
;=======================================================================
put_cx_99:
mov ax, cx
mov bl, 10
div bl
mov bh, ah
test al, al
jz short @f
add al, '0'
call put_char
@@:
mov al, bh
add al, '0'
call put_char
mov al, " "
call put_char
ret
;=======================================================================
; Procedure put_str
; dx -- string lenth
; ds:si -- string address
; Uses: ah, dx
;=======================================================================
put_str:
lodsb
call put_char
dec dx
jnz short put_str
ret
;=======================================================================
; String data needed for the song
;=======================================================================
bott_1 db "bottles of beer on the wall, "
b1_l = $ - bott_1
b2_l = 15
bott_3 db "Take one down pass it around, "
b3_l = $ - bott_3
b4_l = b1_l - 2
bott_5 db "bottle of beer on the wall.", 13, 10, 10
b5_l = $ - bott_5
b6_l = b5_l - 4
b7_l = b5_l - 16
endl = $ - 4
endl_l1 = 3
endl_l = 4
stor db "Go to store and buy some more, "
store_l = $ - stor
rb 7E00h-2-$ ; reserve the rest of bootsector except last two bytes
db 055h, 0AAh ; bootsector signature
;=======================================================================
@muspellsson
Copy link
Author

You may build this code with FASM (http://flatassembler.net) and then write it to diskette or try in emulator (the best choice is DOSBox).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment