Skip to content

Instantly share code, notes, and snippets.

@georgy7
Last active January 17, 2021 20:27
Show Gist options
  • Save georgy7/2aaca7fd0f9ccf689747b992e2227684 to your computer and use it in GitHub Desktop.
Save georgy7/2aaca7fd0f9ccf689747b992e2227684 to your computer and use it in GitHub Desktop.
It's flat assembler (FASM). Re-uploaded. It used to be in the w32utils repository (April 2018).
; 99 Bottles of Beer
; ------------------
format PE console 4.0
entry start
include 'win32a.inc'
include 'macro/if.inc'
NEWLINE equ 10
NULL equ 0
macro printDecimal n {
mov eax, n
call printDecimal_body
}
macro print n {
mov eax, n
call print_body
}
section '.const' data readable
DECIMAL db '%d', 0
COMMA_SPACE db ', ', 0
DOT db '.', 0
NO_MORE_CAPITAL db 'No more', 0
NO_MORE_LOWER db 'no more', 0
BOTTLES_OF_BEER_ON_THE_WALL db ' bottles of beer on the wall', 0
BOTTLES_OF_BEER_DOT_ENDL db ' bottles of beer.', NEWLINE, 0
BOTTLE_OF_BEER_ON_THE_WALL db ' bottle of beer on the wall', 0
BOTTLE_OF_BEER_DOT_ENDL db ' bottle of beer.', NEWLINE, 0
TAKE_ONE_DOWN db 'Take one down and pass it around, ', 0
GO_TO_THE_STORE db 'Go to the store and buy some more, ',\
'99 bottles of beer on the wall.', NEWLINE, 0
NEWLINE_STRING db NEWLINE, 0
section '.var' data readable writeable
bottlesCount dd ?
section '.code' code readable executable
start:
cinvoke printf, NEWLINE_STRING
mov [bottlesCount], 99
phase1:
call strophe1
.if [bottlesCount] >= 3
jmp phase1
.endif
call strophe2
call strophe3
call strophe4
invoke ExitProcess,0
strophe1_line1:
printDecimal [bottlesCount]
print BOTTLES_OF_BEER_ON_THE_WALL
print COMMA_SPACE
printDecimal [bottlesCount]
print BOTTLES_OF_BEER_DOT_ENDL
ret
strophe1_line2:
print TAKE_ONE_DOWN
printDecimal [bottlesCount]
print BOTTLES_OF_BEER_ON_THE_WALL
print DOT
print NEWLINE_STRING
print NEWLINE_STRING
ret
strophe1:
call strophe1_line1
dec [bottlesCount]
call strophe1_line2
ret
strophe2:
call strophe1_line1 ; 2 bottles of beer
dec [bottlesCount]
print TAKE_ONE_DOWN
printDecimal [bottlesCount] ; and 1 bottle of beer left
print BOTTLE_OF_BEER_ON_THE_WALL
print DOT
print NEWLINE_STRING
print NEWLINE_STRING
ret
strophe3:
printDecimal [bottlesCount] ; 1 bottle of beer on the wall
print BOTTLE_OF_BEER_ON_THE_WALL
print COMMA_SPACE
printDecimal [bottlesCount]
print BOTTLE_OF_BEER_DOT_ENDL
print TAKE_ONE_DOWN
print NO_MORE_LOWER
print BOTTLES_OF_BEER_ON_THE_WALL
print DOT
print NEWLINE_STRING
print NEWLINE_STRING
ret
strophe4:
print NO_MORE_CAPITAL
print BOTTLES_OF_BEER_ON_THE_WALL
print COMMA_SPACE
print NO_MORE_LOWER
print BOTTLES_OF_BEER_DOT_ENDL
print GO_TO_THE_STORE
print NEWLINE_STRING
ret
printDecimal_body:
cinvoke printf, DECIMAL, eax, NULL
ret
print_body:
cinvoke printf, eax, NULL, NULL
ret
section '.idata' import data readable writeable
library kernel32,'kernel32.dll',\
msvcrt,'msvcrt.dll'
import kernel32,\
ExitProcess,'ExitProcess'
import msvcrt,\
printf,'printf'
; April 2018
; To the extent possible under law, Georgy Ustinov has waived
; all copyright and related or neighboring rights to beer.asm.
;
; This work is published from: Russian Federation.
;
; http://creativecommons.org/publicdomain/zero/1.0/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment