⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrtio.asm

📁 一个朋友写的操作系统源码
💻 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 + -