add disassemblies

This commit is contained in:
2024-03-01 02:36:21 +11:00
commit 8d9206bec7
5 changed files with 869 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.DS_Store

1
README.md Normal file
View File

@@ -0,0 +1 @@
# TECHNO.COM #

296
disassembly/technog.asm Normal file
View File

@@ -0,0 +1,296 @@
# TECHNO.COM (payload only) Disassembly by a dinosaur 2022, 2024 (original author unknown)
# Binary MD5: 4CB859537BCD7BFB9FC5BFD6D74F4782
# SHA256: BA33A41BA51C3D56B27107A94EF7842235B6D80A3A5B8710AEBDD87EB3A1905C
# Assemble with GAS: as technog.asm -o technog.o
# ld -Ttext 0x100 technog.o -o technog.elf
# objcopy -O binary technog.elf techno.com
.code16
.section .text
# .org 0x100
.global start
start:
push %cs
pop %ds
jmp main
nop
.global exit
exit:
call disable_timer2
mov $0x4C, %ah
int $0x21
# Params: SI=Bigchar Pointer
# DI=Screen pos
# AL=Character
# AH=Cell Attrib
# Side effects: SI += 7
.global draw_bigchar
draw_bigchar:
push %di
push %bx
push %cx
mov $7, %cx
next_line: # for (j=0; j<7; ++j):
push %cx
push %di
mov $8, %cx
mov (%si), %bl # BL = (*SI++)
inc %si
cont_line: # for (i=0; i<8; ++i):
shl $1, %bl # if (0x100 & BL <<= 1):
jb plot_char
inc %di
inc %di
loop cont_line
end_line:
pop %di
pop %cx
add $(2 * 80), %di # Next line
loop next_line
pop %cx
pop %bx
pop %di
ret
plot_char: # fn plot_char(AX, DI):
stosw # ES:[DI] = AX
loop cont_line
jmp end_line
# Arguments: DX = timer2 frequency
.global beep
beep:
push %ax
mov $0b10110110, %al # 0 - 16 bit mode
# 1-3 - Mode 3 (Square wave generator)
# 4-5 - Access mode: lobyte/hibyte
# 6-7 - Channel 2
out %al, $0x43 # Timer 8253-5 control bits
{load} mov %dl, %al
out %al, $0x42 # Timer 8253-5 lo byte
{load} mov %dh, %al
out %al, $0x42 # Timer 8253-5 hi byte
in $0x61, %al # Read 8255 port B state
or $0b00000011, %al # Enable Timer 2 Speaker
out %al, $0x61 # Write 8255 B state
pop %ax
ret
.global disable_timer2
disable_timer2:
push %ax
in $0x61, %al
and $0b11111100, %al
out %al, $0x61
pop %ax
ret
# Return: AX = 0040:006C - BIOS Counter
.global get_counter
get_counter:
push %ds
mov $0x40, %ax # Segment 0040 (BIOS)
mov %ax, %ds
mov 0x6C, %ax # AX = 0040:006C - BIOS Counter
pop %ds
ret
# Wait for next BIOS counter tick
.global wait_nexttick
wait_nexttick:
push %ax
push %bx
call get_counter
{load} mov %ax, %bx
busywait:
call get_counter # AX=BIOS counter
{load} cmp %ax, %bx
jz busywait
pop %bx
pop %ax
ret
.global main
main:
mov $0xF, %ah
int $0x10 # Get current video mode (AL=mode, BH=curent page)
{load} mov %al, %bl
mov $0xB800, %ax # Colour displays have their text buffer at B800:0000
cmp $0x7, %bl # Check if video mode is monochrome
jnz not_mda
mov $0xB000, %ax # Monochrome displays' buffer begins at B000:0000
not_mda:
mov %ax, %es # Store video segment in Extra Segment
mov $0x07DC, %ax # Initial character Light Grey on Black, 0xDC
mov $0xDFDC, %dx # Dancing cursor character pair, Lower half block, Upper half block
mov $phrase, %bx
mov $(80 * 25), %cx
mov $str_techno, %si # " TECHNO "
{load} xor %di, %di # DI = 0
main_loop:
mov %ax, %es:(%di) # Write cursor character
test $1, %cl # Skip over on odd cycles
jnz odd_skip # to run music code at half-speed
push %dx
cmpb $0, (%bx) # FZ at the end of the musical phrase
jnz goto_beep
push %ax
push %cx
mov $freqtbl, %bx
mov mangler, %ax
mov $4, %cx
loop_mangle_freqtbl: # for (int i=0; i<4; ++i):
xor %ax, (%bx) # Mangle the frequency LUT at the end of every measure
inc %bx
inc %bx
loop loop_mangle_freqtbl
pop %cx
pop %ax
mov $phrase, %bx
goto_beep:
push %bx
mov (%bx), %bl # Fetch current note index
dec %bl # Phrase uses 1-based indicies because of the 0 terminator
# So we need to convert it to 0-indexed
mov $0, %bh # BX &= 0xFF
shl $1, %bl
mov freqtbl(%bx), %dx # Store frequency from note index into DX
call beep # Beep with loaded frequency
pop %bx
pop %dx
inc %bx
odd_skip:
call wait_nexttick # Wait for next BIOS counter tick
lodsb # AL = DS:[SI] (get character)
cmp $0, %al
jnz skip_nulterm
mov $str_techno, %si # Reset string on null terminator
lodsb
skip_nulterm:
stosw # Write string character
#FIXME: Every GAS seems swap the operands no matter what
.byte 0x86, 0xD6 # xchg %dh, %dl # Swap cursor half-blocks
{load} mov %dl, %al
incw mangler
push %ax
check_keyboard:
mov $1, %ah
int $0x16 # Check for keypresses (AH=scan code, AL=char, ZF=1 if buffer empty)
jz no_keyboard_input
mov $0, %ah
int $0x16 # Read char from buffer (AH=scan code, AL=char)
cmp $0x1B, %al
jnz skip_earlyexit
incb esc_counter # Exit if escape pressed twice
cmpb $2, esc_counter
jnz skip_earlyexit
jmp exit
skip_earlyexit:
cmp $str_notuch, %si # Avoid restarting notouch prompt if already active
jnb notuch_skip
mov $str_notuch, %si # " >>Don't touch the keyboard<< "
notuch_skip:
jmp check_keyboard
no_keyboard_input:
pop %ax
loop main_loop # Loop over every character on the screen
call disable_timer2 # Stop beeping
mov $(8*160+13*2), %di # row=8, col=13
mov $0x07B0, %ax # FG=Light Grey on Black, Light shade block
mov $9, %cx
loop_rows: # for (j=0; j<9; ++j):
push %cx
push %di
mov $53, %cx # for (i=0; i<53; ++i):
rep stosw # (*ES:DI) = AX; DI += 2
pop %di
pop %cx
add $(80 * 2), %di # row += 1
loop loop_rows
mov $(9*160+15*2), %di # row=9, col=15
mov $0x70, %ah # BG=Either Light Grey or White + Blink depending on video mode
mov $bigtext, %si
mov $6, %cx
mov $(str_techno + 2), %bx # "TECHNO"
loop_bigchar: # for (i=0; i<6; ++i):
mov (%bx), %al # Load character into accum low
inc %bx # Next character
call draw_bigchar
add $0x10, %di
loop loop_bigchar
mov $20, %cx
wait_loop:
call wait_nexttick # Wait for 20 ticks
loop wait_loop
mov $0, %ah
int $0x16 # Wait for keypress
{load} xor %di, %di # DI = 0
mov $(80 * 25), %cx
mov $0x0720, %ax # FG=Light Grey on Black, space
rep stosw # Clear the whole screen
jmp exit
str_techno: .string " TECHNO "
str_notuch: .string " \257Don't touch the keyboard\256 "
mangler: .word 0x0404
freqtbl: .word 5424, 2712, 2416, 2280
phrase: .byte 3, 2, 1, 1, 2, 1, 1, 2, 1, 1, 3, 2, 1
.byte 1, 2, 1, 1, 2, 1, 1, 3, 2, 1, 1, 2, 1
.byte 1, 2, 1, 1, 3, 4, 1, 4, 1, 4, 1, 4, 0
bigtext:
.byte 0b1111111 # 'T'
.byte 0b0001000
.byte 0b0001000
.byte 0b0001000
.byte 0b0001000
.byte 0b0001000
.byte 0b0001000
.byte 0b1111111 # 'E'
.byte 0b1000000
.byte 0b1000000
.byte 0b1111100
.byte 0b1000000
.byte 0b1000000
.byte 0b1111111
.byte 0b0111111 # 'C'
.byte 0b1000000
.byte 0b1000000
.byte 0b1000000
.byte 0b1000000
.byte 0b1000000
.byte 0b0111111
.byte 0b1000001 # 'H'
.byte 0b1000001
.byte 0b1000001
.byte 0b1111111
.byte 0b1000001
.byte 0b1000001
.byte 0b1000001
.byte 0b1000001 # 'N'
.byte 0b1100001
.byte 0b1010001
.byte 0b1001001
.byte 0b1000101
.byte 0b1000011
.byte 0b1000001
.byte 0b0111110 # 'O'
.byte 0b1000001
.byte 0b1000001
.byte 0b1000001
.byte 0b1000001
.byte 0b1000001
.byte 0b0111110
esc_counter: .byte 0

288
disassembly/technom.asm Normal file
View File

@@ -0,0 +1,288 @@
; TECHNO.COM (payload only) Disassembly by a dinosaur 2022, 2024 (original author unknown)
; Binary MD5: 4CB859537BCD7BFB9FC5BFD6D74F4782
; SHA256: BA33A41BA51C3D56B27107A94EF7842235B6D80A3A5B8710AEBDD87EB3A1905C
;
; Assemble with Microsoft Macro Assembler: ml.exe /W3 technom.asm /Fotechno.com
; Assemble with JWasm: jwasm.exe -bin -Fo techno.com technom.asm
; Assemble with Turbo Assembler: tasm.exe technom.asm techno.obj
; tlink.exe /t techno.obj, techno.com
.model tiny
.8086
.code
org 100h
start:
push cs ; https://stackoverflow.com/a/53604793
pop ds
jmp main
ifndef ??version ; Only pad if we're not Turbo Assembler (which will pad anyway)
nop
endif
exit:
call disable_timer2
mov ah, 4Ch ; Quit with exit code (AL)
int 21h
; Params: SI=Bigchar Pointer
; DI=Screen pos
; AL=Character
; AH=Cell Attrib
; Side effects: SI += 7
draw_bigchar:
push di
push bx
push cx
mov cx, 7
next_line: ; for (j=0; j<7; ++j):
push cx
push di
mov cx, 8
mov bl, [si] ; BL = (*SI++)
inc si
cont_line: ; for (i=0; i<8; ++i):
shl bl, 1 ; if (0x100 & BL <<= 1):
jb plot_char ; plot_char()
inc di ; DI += 2
inc di
loop cont_line
end_line:
pop di
pop cx
add di, 2 * 80 ; Next line
loop next_line
pop cx
pop bx
pop di
ret
plot_char: ; fn plot_char(AX, DI):
stosw ; ES:[DI] = AX
loop cont_line
jmp end_line
; Arguments: DX = timer2 frequency
beep:
push ax
mov al, 10110110b ; 0 - 16 bit mode
; 1-3 - Mode 3 (Square wave generator)
; 4-5 - Access mode: lobyte/hibyte
; 6-7 - Channel 2
out 43h, al ; Timer 8253-5 control bits
mov al, dl
out 42h, al ; Timer 8253-5 lo byte
mov al, dh
out 42h, al ; Timer 8253-5 hi byte
in al, 61h ; Read 8255 port B state
or al, 00000011b ; Enable Timer 2 Speaker
out 61h, al ; Write 8255 B state
pop ax
ret
disable_timer2:
push ax
in al, 61h ; Read 8255 port state
and al, 11111100b ; Disable Timer 2 Speaker
out 61h, al ; Write 8255 state
pop ax
ret
; Return: AX = 0040:006C - BIOS Counter
get_counter:
push ds
mov ax, 40h ; Segment 0040 (BIOS)
mov ds, ax
mov ax, [ds:006Ch] ; AX = 0040:006C - BIOS Counter
pop ds
ret
; Wait for next BIOS counter tick
wait_nexttick:
push ax
push bx
call get_counter
mov bx, ax
busywait:
call get_counter ; AX=BIOS counter
cmp bx, ax
jz busywait
pop bx
pop ax
ret
main:
mov ah, 0Fh
int 10h ; Get current video mode (AL=mode, BH=curent page)
mov bl, al
mov ax, 0B800h ; Colour displays have their text buffer at B800:0000
cmp bl, 7 ; Check if video mode is monochrome
jnz not_mda
mov ax, 0B000h ; Monochrome displays' buffer begins at B000:0000
not_mda:
mov es, ax ; Store video segment in Extra Segment
mov ax, 07DCh ; Initial character Light Grey on Black, 0xDC
mov dx, 0DFDCh ; Dancing cursor character pair, Lower half block, Upper half block
mov bx, offset phrase
mov cx, 80 * 25
mov si, offset str_techno ; " TECHNO "
xor di, di ; DI = 0
main_loop:
mov es:[di], ax ; Write cursor character
test cl, 1 ; Skip over on odd cycles
jnz odd_skip ; to run music code at half-speed
push dx
cmp byte ptr [bx], 0 ; FZ at the end of the musical phrase
jnz goto_beep
push ax
push cx
mov bx, offset freqtbl
mov ax, [mangler]
mov cx, 4
loop_mangle_freqtbl: ; for (int i=0; i<4; ++i):
xor [bx], ax ; Mangle the frequency LUT at the end of every measure
inc bx
inc bx
loop loop_mangle_freqtbl
pop cx
pop ax
mov bx, offset phrase
goto_beep:
push bx
mov bl, [bx] ; Fetch current note index
dec bl ; Phrase uses 1-based indicies because of the 0 terminator
; So we need to convert it to 0-indexed
mov bh, 0 ; BX &= 0xFF
shl bl, 1 ;
mov dx, [freqtbl + bx] ; Store frequency from note index into DX
call beep ; Beep with loaded frequency
pop bx
pop dx
inc bx
odd_skip:
call wait_nexttick ; Wait for next BIOS counter tick
lodsb ; AL = DS:[SI] (get character)
cmp al, 0
jnz skip_nulterm
mov si, offset str_techno ; Reset string on null terminator
lodsb
skip_nulterm:
stosw ; Write string character
xchg dl, dh ; Swap cursor half-blocks
mov al, dl
inc [mangler]
push ax
check_keyboard:
mov ah, 1
int 16h ; Check for keypresses (AH=scan code, AL=char, ZF=1 if buffer empty)
jz no_keyboard_input
mov ah, 0
int 16h ; Read char from buffer (AH=scan code, AL=char)
cmp al, 1Bh
jnz skip_earlyexit
inc [esc_counter] ; Exit if escape pressed twice
cmp [esc_counter], 2
jnz skip_earlyexit
jmp exit
skip_earlyexit:
cmp si, offset str_notuch ; Avoid restarting notouch prompt if already active
jnb notuch_skip
mov si, offset str_notuch ; " >>Don't touch the keyboard<< "
notuch_skip:
jmp check_keyboard
no_keyboard_input:
pop ax
loop main_loop ; Loop over every character on the screen
call disable_timer2 ; Stop beeping
mov di, 8 * 160 + 13 * 2 ; row=8, col=13
mov ax, 07B0h ; FG=Light Grey on Black, Light shade block
mov cx, 9
loop_rows: ; for (j=0; j<9; ++j):
push cx
push di
mov cx, 53 ; for (i=0; i<53; ++i):
rep stosw ; (*ES:DI) = AX; DI += 2
pop di
pop cx
add di, 80 * 2 ; row += 1
loop loop_rows
mov di, 9 * 160 + 15 * 2 ; row=9, col=15
mov ah, 70h ; BG=Either Light Grey or White + Blink depending on video mode
mov si, offset bigtext
mov cx, 6
mov bx, offset str_techno+2 ; "TECHNO"
loop_bigchar: ; for (i=0; i<6; ++i):
mov al, [bx] ; Load character into accum low
inc bx ; Next character
call draw_bigchar
add di, 10h
loop loop_bigchar
mov cx, 20
wait_loop:
call wait_nexttick ; Wait for 20 ticks
loop wait_loop
mov ah, 0
int 16h ; Wait for keypress
xor di, di ; DI = 0
mov cx, 80 * 25
mov ax, 0720h ; FG=Light Grey on Black, space
rep stosw ; Clear the whole screen
jmp exit
str_techno db ' TECHNO ',0
str_notuch db ' ',0AFh,'Don',27h,'t touch the keyboard',0AEh,' ',0
mangler dw 0404h
freqtbl dw 5424, 2712, 2416, 2280
phrase db 3 dup(3, 2, 1, 1, 2, 1, 1, 2, 1, 1), 3, 4, 3 dup(1, 4), 0
bigtext db 1111111b ; 'T'
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 1111111b ; 'E'
db 1000000b
db 1000000b
db 1111100b
db 1000000b
db 1000000b
db 1111111b
db 0111111b ; 'C'
db 1000000b
db 1000000b
db 1000000b
db 1000000b
db 1000000b
db 0111111b
db 1000001b ; 'H'
db 1000001b
db 1000001b
db 1111111b
db 1000001b
db 1000001b
db 1000001b
db 1000001b ; 'N'
db 1100001b
db 1010001b
db 1001001b
db 1000101b
db 1000011b
db 1000001b
db 0111110b ; 'O'
db 1000001b
db 1000001b
db 1000001b
db 1000001b
db 1000001b
db 0111110b
esc_counter db 0
END start

283
disassembly/technon.asm Normal file
View File

@@ -0,0 +1,283 @@
; TECHNO.COM (payload-only) Disassembly by a dinosaur 2022, 2024 (original author unknown)
; Binary MD5: 4CB859537BCD7BFB9FC5BFD6D74F4782
; SHA256: BA33A41BA51C3D56B27107A94EF7842235B6D80A3A5B8710AEBDD87EB3A1905C
;
; Assemble with FASM: fasm technon.asm techno.com
; Assemble with NASM: nasm technon.asm -fbin -o techno.com
; Assemble with YASM: yasm -f bin technon.asm -o techno.com
use16
org 100h
start:
push cs ; https://stackoverflow.com/a/53604793
pop ds
jmp main
nop
exit:
call disable_timer2
mov ah, 4Ch ; Quit with exit code (AL)
int 21h
; Params: SI=Bigchar Pointer
; DI=Screen pos
; AL=Character
; AH=Cell Attrib
; Side effects: SI += 7
draw_bigchar:
push di
push bx
push cx
mov cx, 7
next_line: ; for (j=0; j<7; ++j):
push cx
push di
mov cx, 8
mov bl, [si] ; BL = (*SI++)
inc si
cont_line: ; for (i=0; i<8; ++i):
shl bl, 1 ; if (0x100 & BL <<= 1):
jb plot_char ; plot_char()
times 2 inc di ; DI += 2
loop cont_line
end_line:
pop di
pop cx
add di, 2 * 80 ; Next line
loop next_line
pop cx
pop bx
pop di
retn
plot_char: ; fn plot_char(AX, DI):
stosw ; ES:[DI] = AX
loop cont_line
jmp end_line
; Arguments: DX = timer2 frequency
beep:
push ax
mov al, 10110110b ; 0 - 16 bit mode
; 1-3 - Mode 3 (Square wave generator)
; 4-5 - Access mode: lobyte/hibyte
; 6-7 - Channel 2
out 43h, al ; Timer 8253-5 control bits
db 8Ah,0C2h ; mov al, dl
out 42h, al ; Timer 8253-5 lo byte
db 8Ah,0C6h ; mov al, dh
out 42h, al ; Timer 8253-5 hi byte
in al, 61h ; Read 8255 port B state
or al, 00000011b ; Enable Timer 2 Speaker
out 61h, al ; Write 8255 B state
pop ax
retn
disable_timer2:
push ax
in al, 61h ; Read 8255 port state
and al, 11111100b ; Disable Timer 2 Speaker
out 61h, al ; Write 8255 state
pop ax
retn
; Return: AX = 0040:006C - BIOS Counter
get_counter:
push ds
mov ax, 40h ; Segment 0040 (BIOS)
mov ds, ax
mov ax, [006Ch] ; AX = 0040:006C - BIOS Counter
pop ds
retn
; Wait for next BIOS counter tick
wait_nexttick:
push ax
push bx
call get_counter
db 8Bh,0D8h ; mov bx, ax
busywait:
call get_counter ; AX=BIOS counter
db 3Bh,0D8h ; cmp bx, ax
jz busywait
pop bx
pop ax
retn
main:
mov ah, 0Fh
int 10h ; Get current video mode (AL=mode, BH=curent page)
db 8Ah,0D8h ; mov bl, al
mov ax,0B800h ; Colour displays have their text buffer at B800:0000
cmp bl, 7 ; Check if video mode is monochrome
jnz not_mda
mov ax,0B000h ; Monochrome displays' buffer begins at B000:0000
not_mda:
mov es, ax ; Store video segment in Extra Segment
mov ax, 07DCh ; Initial character Light Grey on Black, 0xDC
mov dx,0DFDCh ; Dancing cursor character pair, Lower half block, Upper half block
mov bx, phrase
mov cx, 80 * 25
mov si, str_techno ; " TECHNO "
db 33h,0FFh ; xor di, di ; DI = 0
main_loop:
mov [es:di], ax ; Write cursor character
test cl, 1 ; Skip over on odd cycles
jnz odd_skip ; to run music code at half-speed
push dx
cmp byte [bx], 0 ; FZ at the end of the musical phrase
jnz goto_beep
push ax
push cx
mov bx, freqtbl
mov ax, [mangler]
mov cx, 4
loop_mangle_freqtbl: ; for (int i=0; i<4; ++i):
xor [bx], ax ; Mangle the frequency LUT at the end of every measure
times 2 inc bx
loop loop_mangle_freqtbl
pop cx
pop ax
mov bx, phrase
goto_beep:
push bx
mov bl, [bx] ; Fetch current note index
dec bl ; Phrase uses 1-based indicies because of the 0 terminator
; So we need to convert it to 0-indexed
mov bh, 0 ; BX &= 0xFF
shl bl, 1 ;
mov dx, [freqtbl + bx] ; Store frequency from note index into DX
call beep ; Beep with loaded frequency
pop bx
pop dx
inc bx
odd_skip:
call wait_nexttick ; Wait for next BIOS counter tick
lodsb ; AL = DS:[SI] (get character)
cmp al, 0
jnz skip_nulterm
mov si, str_techno ; Reset string on null terminator
lodsb
skip_nulterm:
stosw ; Write string character
; FIXME: xchg operands only need to be forced for YASM
db 86h,0D6h ; xchg dl, dh ; Swap cursor half-blocks
db 8Ah,0C2h ; mov al, dl
inc word [mangler]
push ax
check_keyboard:
mov ah, 1
int 16h ; Check for keypresses (AH=scan code, AL=char, ZF=1 if buffer empty)
jz no_keyboard_input
mov ah, 0
int 16h ; Read char from buffer (AH=scan code, AL=char)
cmp al, 1Bh
jnz skip_earlyexit
inc byte [esc_counter] ; Exit if escape pressed twice
cmp byte [esc_counter], 2
jnz skip_earlyexit
jmp exit
skip_earlyexit:
cmp si, str_notuch ; Avoid restarting notouch prompt if already active
jnb notuch_skip
mov si, str_notuch ; " >>Don't touch the keyboard<< "
notuch_skip:
jmp check_keyboard
no_keyboard_input:
pop ax
loop main_loop ; Loop over every character on the screen
call disable_timer2 ; Stop beeping
mov di, 8*160 + 13*2 ; row=8, col=13
mov ax, 07B0h ; FG=Light Grey on Black, Light shade block
mov cx, 9
loop_rows: ; for (j=0; j<9; ++j):
push cx
push di
mov cx, 53 ; for (i=0; i<53; ++i):
rep stosw ; (*ES:DI) = AX; DI += 2
pop di
pop cx
add di, 80 * 2 ; row += 1
loop loop_rows
mov di, 9*160 + 15*2 ; row=9, col=15
mov ah, 70h ; BG=Either Light Grey or White + Blink depending on video mode
mov si, bigtext
mov cx, 6
mov bx, str_techno + 2 ; "TECHNO"
loop_bigchar: ; for (i=0; i<6; ++i):
mov al, [bx] ; Load character into accum low
inc bx ; Next character
call draw_bigchar
add di, 10h
loop loop_bigchar
mov cx, 20
wait_loop:
call wait_nexttick ; Wait for 20 ticks
loop wait_loop
mov ah, 0
int 16h ; Wait for keypress
db 33h,0FFh ; xor di, di ; DI = 0
mov cx, 80 * 25
mov ax, 0720h ; FG=Light Grey on Black, space
rep stosw ; Clear the whole screen
jmp exit
str_techno db ' TECHNO ',0
str_notuch db ' ',0AFh,'Don',27h,'t touch the keyboard',0AEh,' ',0
mangler dw 0404h
freqtbl dw 5424, 2712, 2416, 2280
phrase: times 3 db 3, 2, 1, 1, 2, 1, 1, 2, 1, 1
db 3, 4, 1, 4, 1, 4, 1, 4, 0
bigtext db 1111111b ; 'T'
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 0001000b
db 1111111b ; 'E'
db 1000000b
db 1000000b
db 1111100b
db 1000000b
db 1000000b
db 1111111b
db 0111111b ; 'C'
db 1000000b
db 1000000b
db 1000000b
db 1000000b
db 1000000b
db 0111111b
db 1000001b ; 'H'
db 1000001b
db 1000001b
db 1111111b
db 1000001b
db 1000001b
db 1000001b
db 1000001b ; 'N'
db 1100001b
db 1010001b
db 1001001b
db 1000101b
db 1000011b
db 1000001b
db 0111110b ; 'O'
db 1000001b
db 1000001b
db 1000001b
db 1000001b
db 1000001b
db 0111110b
esc_counter db 0