📄 wrtio.asm
字号:
;/++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; we use the side effect of getinode subroutine, it set the inodeinfo
; structure correctly, by using this information, we can load the Minix
; file from floppy diskette zone by zone and write to harddisk with the
; same file name in current directory, we don't have any dedicate buf
; we share the same buf of zonespace, don't worry about the confliect
; with the directory buf, we are in single user mode after all, process
; anything in series order, at this point, the directory buf is no use
; we call bmap subroutine frequently and use the value it return to do
; the floppy I/O, it will be well taken cared by getzone subroutine. by
; the way before doing this, we will check the inode attrib, attrib rather
; than ordinary file will be ejected.
;
; The entry points into this file are
; bmap: map the logic file blk # into LBA
; wrtfile: write file blk into kernel preload address space
; clrmem: clean kernel core memory
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++/
include const.inc
include comstruc.inc
sseg segment stack
db 128 dup (0)
sseg ends
overlap segment para common 'strucinfo'
; this is the only way to reference
; extern struct
inodeinfo minixinode <>
superinfo minixsuper <>
dent dirent <>
overlap ends
dseg segment para public 'global'
public newline
extrn prom:byte
extrn dbuf:byte
extrn zonespace:byte
extrn dirp:word ; path charcter indicator
extrn parambuf:byte
extrn paramnr:byte
extrn fn:word ; files have been processed
extrn fulstr:byte
extrn configbuf:byte
suc db 'total %d blocks in %s loaded successful!','$'
fai db 'failed!','$'
notregu db '%s is not an regular file','$'
kbseg db 'kernel base segment : %d',13,10,'$'
koffset db 'kernel base offset : %d',13,10,'$'
lodkbyte db 'kilo bytes loaded : %d',13,10,'$'
; debug
debugstr db '%d# logic zone want to be converted','$'
newline db 0dh,0ah,'$'
phyzone db 'convert to physical zone %d','$'
dseg ends
cseg segment para public 'code'
assume cs:cseg,ds:dseg,es:dseg,ss:sseg
public wrtfile,bmap,clrmem
extrn printf:near
extrn getinode:near
extrn getzone:near
extrn panic:near
;/============================================================================
;
; clrmem
;
;============================================================================/
clrmem proc near
push ds
push es
mov ax,es_sym
mov es,ax
mov di,di_sym
xor ax,ax
mov cx,0ffffh
cld
repnz stosb ; clean 64k core
mov ax,es_sym
add ax,1000h
mov es,ax
mov di,di_sym
xor ax,ax
mov cx,0ffffh
cld
repnz stosb ; another 64k please
pop es
pop ds
ret
clrmem endp
;/============================================================================
;
; wrtfile
;
;============================================================================/
wrtfile proc near
push ds
push es
push bp
mov bp,sp
sub sp,12
; the local variable arranged as followed
; [bp-2] : maximum file logic blk #
; [bp-4] : current logic blk #
; [bp-6] : current file handler
; [bp-8] : es_count for kernel segment
; [bp-10] : di_count for kernel offset
; [bp-12] : kernel kilo bytes counter
; initialize es_count & di_count
mov word ptr [bp-8],0
mov word ptr [bp-10],0
mov word ptr [bp-12],0
push ds
mov ax,overlap
mov ds,ax
assume ds:overlap
mov ax,[inodeinfo.i_mode]
pop ds
assume ds:dseg
and ax,I_TYPE
cmp ax,I_REGULAR
je wnext1
mov ax,offset fai
push ax
call printf
pop cx
mov ax,offset newline
push ax
call printf
pop cx
mov ax,offset fulstr
push ax
mov ax,offset notregu
push ax
call printf
pop cx
pop cx
mov ax,offset newline
push ax
call printf
pop cx
mov sp,bp
pop bp
pop es
pop ds
ret ; this convertion failed
wnext1:
; we will determine how many block this file taken!
push es
mov ax,overlap
mov es,ax
assume es:overlap
mov ax,es:[inodeinfo.i_size] ; low 16 bit
mov dx,es:[inodeinfo.i_size2] ; high 16 bit
pop es
assume es:dseg
; bmap will change es definition again to access the
; physical zone #
mov cl,10
shr ax,cl
and dx,3ffh
mov cl,6
shl dx,cl
or ax,dx
; this is not precise, if the file size is not the
; multiple of blk size, it is one blk bigger, so
; it is the responsibility of bmap to assume this
; block won't move to kernel space
mov [bp-2],ax ; max file logic blk #
mov word ptr [bp-4],0 ; first logic blk #
wnext4:
mov [bp-6],ax ; save file handler
wnext2:
mov ax,[bp-2] ; load up limit
cmp ax,[bp-4]
jb scale1
jmp goahead
scale1:
jmp wnext3
goahead:
mov ax,[bp-4]
inc word ptr [bp-4] ; stepping logic zone
push ax
call bmap
pop cx
push ax
call getzone
pop cx
cmp word ptr [fn],1 ; the sequence of kernel path
je kernelpath
cmp word ptr [fn],0 ; the sequence of config path
je configpath
; if fn > 1, we will obsolete the last path
; component the user just input
mov sp,bp
pop bp
pop es
pop ds
ret
configpath:
push es
mov ax,dseg
mov es,ax
mov di,offset configbuf
mov si,offset zonespace
mov cx,1024
cld
repnz movsb
jmp movnext1
; move the zone just read to kernel
; preload address at 0400:0000h
kernelpath:
; save cursor position
mov ah,3
mov bh,0
int 10h
push dx
push es
mov ax,es_sym
add ax,[bp-8]
mov es,ax
mov di,di_sym
add di,[bp-10]
mov si,offset zonespace
mov cx,1024
cld
repnz movsb
; now updata [bp-8], [bp-10], every time a zone
; is transfered, [bp-10] will inc 400h, if we
; detected it was wraparound, the [bp-8] will
; increase by 1000h
inc word ptr [bp-12]
add word ptr [bp-10],400h
cmp word ptr [bp-10],0
jne movnext1
add word ptr [bp-8],1000h
; we don't check the up limit of es
; we believe our kernel won't take
; up to 640k, [bp-2] only need to
; increase 2-3 times is sufficient
movnext1:
pop es
cmp word ptr [fn],0 ; only for kernel
je wnext5
mov ax,[bp-8]
add ax,es_sym
push ax
mov ax,offset kbseg
push ax
call printf
pop cx
pop cx
mov ax,[bp-10]
add ax,di_sym
push ax
mov ax,offset koffset
push ax
call printf
pop cx
pop cx
mov ax,[bp-12]
push ax
mov ax,offset lodkbyte
push ax
call printf
pop cx
pop cx
pop dx ; restore cursor position
mov bh,0
mov ah,2
int 10h
wnext5:
jmp wnext2
wnext3:
cmp word ptr [fn],0 ; only for kernel
je wnext6
; move cursor to the proper line
mov ax,offset newline
push ax
call printf
pop cx
mov ax,offset newline
push ax
call printf
pop cx
wnext6:
; time for return
; debug
mov ax,offset fulstr
push ax
mov ax,[bp-2]
inc ax
push ax
mov ax,offset suc
push ax
call printf
pop cx
pop cx
pop cx
mov ax,offset newline
push ax
call printf
pop cx
inc word ptr [fn]
mov sp,bp
pop bp
pop es
pop ds
ret
wrtfile endp
;/============================================================================
;
; bmap
;
;============================================================================/
bmap proc near
push ds
push es
push bp
mov bp,sp
sub sp,6
; the stack arranges as follows
; [bp-2] : logic zone # (base 0)
; [bp-4] : physical zone # (base 0)
; [bp-6] : last zone # (base 0)
mov ax,8[bp] ; logic zone #
mov [bp-2],ax
; we use two register combination
; we can also use the shift instruction
; to divide the 32 bit value
push es
mov ax,overlap
mov es,ax
assume es:overlap
mov ax,es:[inodeinfo.i_size] ; low 16 bit
mov dx,es:[inodeinfo.i_size2] ; high 16 bit
; isize / zonesize +1 = total logic zone #
mov cl,10
shr ax,cl
; the low 10 bit of dx must be shift
; into the high 10 bit of ax which
; was shift out
and dx,3ffh
; we can process maximum 64M file
; that's enough for not only ASCII file
mov cl,6
shl dx,cl
or ax,dx
mov [bp-6],ax ; save last zone #
; inc ax ; add tail
; ax now contain the total zone #
jmp bnext13
bnext1:
jmp bnext12
bnext13:
mov ax,[bp-2] ; used to determine the algorithm for address zone
inc ax ; adjust base # from 0 to 1
cmp ax,7 ; direct zone
ja bnext1
mov ax,[bp-2]
mov bx,4
mul bx ; i_zone is only the low 16 bit of Minix zone
mov si,offset inodeinfo.i_zone
add si,ax
mov ax,es:[si]
mov [bp-4],ax ; save return value
pop es
assume es:dseg
; debug
mov ax,8[bp]
push ax
mov ax,offset debugstr
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
; debug
mov ax,[bp-4]
push ax
mov ax,offset phyzone
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
mov ax,[bp-4] ; restore return value
; now ax contain the phsical LBA block #
mov sp,bp
pop bp
pop es
pop ds
ret
; we will implement large file algorithm, including
; indirect and double indirect fetch. it is so important
; for file larger than 7k
bnext12:
; the following code maps the logic file block one per
; time, so we share the zonespace and getzone subroutine
; for storing the indirect / double indirect block
jmp bnext23
bnext2:
jmp bnext22
bnext23:
cmp ax,263 ; 7 + 256 , ax base # is 1 not 0
jbe bnext2
mov si,offset inodeinfo.i_zone
add si,32 ; get double indirect zone #, not 8
mov ax,es:[si] ; get the zone
pop es
assume es:dseg
mov [bp-4],ax
push ax
call getzone
pop cx
mov ax,[bp-2]
sub ax,263 ; get offset
mov cl,8
shr ax,cl
xor dx,dx
mov bx,4
mul bx
mov si,ax
add si,offset zonespace
mov ax,[si]
mov [bp-4],ax ; save physical zone
push ax
call getzone
pop cx
; evaluate remain using masking
mov ax,[bp-2]
sub ax,263
and ax,0ffh ; ax is offset now
xor dx,dx
mov bx,4
mul bx
mov si,ax
add si,offset zonespace
mov ax,[si]
mov [bp-4],ax
; debug
mov ax,8[bp]
push ax
mov ax,offset debugstr
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
; debug
mov ax,[bp-4]
push ax
mov ax,offset phyzone
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
mov ax,[bp-4]
; now ax contain the physical
; zone # we want
mov sp,bp
pop bp
pop es
pop ds
ret
bnext22:
mov si,offset inodeinfo.i_zone
add si,28 ; be more careful, this is not 7 but 7*4
mov ax,es:[si]
pop es
assume es:dseg
push ax
call getzone
pop cx
mov ax,[bp-2]
sub ax,7
xor dx,dx
mov bx,4
mul bx
mov si,ax
add si,offset zonespace
mov ax,[si]
mov [bp-4],ax
; debug
mov ax,8[bp]
push ax
mov ax,offset debugstr
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
; debug
mov ax,[bp-4]
push ax
mov ax,offset phyzone
push ax
; call printf
pop cx
pop cx
mov ax,offset newline
push ax
; call printf
pop cx
mov ax,[bp-4]
mov sp,bp
pop bp
pop es
pop ds
ret
bmap endp
cseg ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -