📄 load.asm
字号:
CODE SEGMENT PARA USE16 ;can't run alone
ASSUME CS:CODE
ORG 800H
START:
.386P
;MOV AX,0600H ;clear screen
;MOV BH,07H
;MOV CX,0
;MOV DX,184FH
;INT 10H
MOV AX,1301H ;M1
MOV DX,0A00H
MOV BX,7H
MOV BP,OFFSET M1
MOV SI,BP
MOV CL,[SI]
XOR CH,CH
INC BP
INT 10H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAAAAAAA
;load the file "GFAT16.EXE" to 1000:0
MOV SI,7C00H ;COS_BOOT sector moved to 70:0
MOV DI,700H
MOV CX,03EH
REPZ MOVSB
MOV SI,700H
XOR AX,AX
CMP [SI+13H],AX
JZ L1
MOV CX,[SI+13H]
MOV [SI+20H],CX
L1: MOV AL,[SI+10H]
MUL WORD PTR [SI+16H]
ADD AX,[SI+0EH]
ADC DX,+0
MOV WORD PTR DIR_FS+7,AX ;7C50 save root dir 1st sector_no
MOV WORD PTR DIR_FS+9,DX ;7C52
MOV WORD PTR DIR_FS,AX ;7C49
MOV WORD PTR DIR_FS+2,DX ;7C4B
MOV AX,20H
MUL WORD PTR [SI+11H] ;dx:ax bytes of root_dir
MOV BX,[SI+0BH] ;bx=bytes per sector
ADD AX,BX
DEC AX
DIV BX
ADD WORD PTR DIR_FS,AX ;save file area 1st sector_no
ADC WORD PTR DIR_FS+2,+0
MOV DX,WORD PTR DIR_FS+9 ;7c52h
MOV AX,WORD PTR DIR_FS+7 ;7c50h dx:ax root dir 1st sector_no
CALL SECTOR_ADDR
JB ERROR_IN
MOV AL,1
MOV BX,0500H ;input buf----root 1st sector
CALL READ_SECTOR ;gfat16.exe should be in 1st sector
JB ERROR_IN
MOV BL,16
cld
MOV WORD PTR DIR_FS+13,SI
MOV DI,0500H
L2: MOV CX,000BH
MOV WORD PTR DIR_FS+15,DI
MOV SI,OFFSET FNAME0
REPZ CMPSB
JZ READ_OK
DEC BL
JZ ERROR_IN
MOV DI,WORD PTR DIR_FS+15
ADD DI,32
JMP L2
READ_OK: ;found GFAT16.EXE di point just after file_name
MOV SI,WORD PTR DIR_FS+13
MOV AX,DI
ADD AX,15
MOV DI,AX
MOV AX,[DI] ;begin cluster_no
MOV WORD PTR DIR_FS+17,AX ;cluster_no
MOV BX,0H
MOV WORD PTR DIR_FS+19,BX ;offset of Input buf
; read GFAT16.EXE--->1000H:0
; in:DIR_FS+17=1st cluster_no
; & DIR_FS+19=offset of Input buf
;from cluster -->logical sector_no
CLUSTER_L: MOV SI,700h
MOV AX,WORD PTR DIR_FS+17
CMP AX,0FFF8H
JAE READ_FILE_END
XOR DX,DX
SUB AX,2
MOV BL,BYTE PTR [SI+0DH]
XOR BH,BH
MUL BX
ADD AX,WORD PTR DIR_FS
ADC DX,+0 ;dx:ax logical sector_no
; Read gfat16.exe
READ_FILE:
;MOV WORD PTR DIR_FS,AX
;MOV WORD PTR DIR_FS+2,DX
CALL SECTOR_ADDR
JB ERROR_IN
MOV AL,BYTE PTR [SI+0DH]
PUSH ES
MOV BX,1000H
MOV ES,BX
MOV BX,WORD PTR DIR_FS+19
CALL READ_SECTOR ;cos.exe should be in 1st sector
JB ERROR_IN0
JMP READ_FILE_NEXT
ERROR_IN0: POP ES
JMP ERROR_IN
READ_FILE_NEXT:
POP ES
;************find next cluster_start
PUSH EBX
PUSH ECX
PUSH EDX
MOV CX,WORD PTR DS:[SI+0BH] ;bytes per setctor
MOVZX ECX,CX
MOV AX,WORD PTR DIR_FS+17 ;current cluster
MOVZX EAX,AX
MOV EBX,EAX
ADD EAX,EBX ;eax=offset of the cluster_no
XOR EDX,EDX
DIV ECX ;eax=sectors before the cluster_no
INC EAX ;ADD boot now eax=logical sector_no
NEXT_CLUSTER1: ;EAX=sector_no of the cluster
;;;;;;;
PUSH DX ;remains = offset of cluster_no
;read one_sector eax=logical sector_no
MOV EDX,EAX
SHR EDX,16
CALL SECTOR_ADDR
JB ERROR_IN
MOV AL,1
MOV BX,OFFSET TTSECTOR
CALL READ_SECTOR ;read fat
JB ERROR_IN1
JMP READ_FILE_NEXT1
ERROR_IN1:
JMP ERROR_IN
READ_FILE_NEXT1:
;read one_sector eax=logical sector_no
MOV BX,OFFSET TTSECTOR
POP DX ;remains
ADD BX,DX
MOV AX,[BX] ;next cluster
CLD
MOV WORD PTR DIR_FS+17,AX
POP EDX
POP ECX
POP EBX
;************find next cluster_end
MOV AL,[SI+0DH]
MOV AH,0
MUL WORD PTR [SI+0BH]
CLD
ADD WORD PTR DIR_FS+19,AX
JMP CLUSTER_L
READ_FILE_END:
MOV AX,1000H
MOV GS,AX
CALL G_EXEC_LOAD
CMP AX,1
JE ERROR_IN
;
CLI
MOV AX,GS:0EH
MOV SS,AX
MOV AX,GS:11H
MOV SP,AX
STI
;MOV BX,GS:16H
;ADD BX,1000H
;MOV SI,GS:14H
DB 0EAH
DW 0,1CDFH ;for ok 1000+20+CBF=cos.exe
jmp ttt
ERROR_IN: MOV BP,OFFSET ERROR1
CALL DO_ERROR
;tt: jmp tt ;cut off comment
TTT: ;cut off after test
MOV ax,4c00h ;for test
int 21h
T1: JMP T1 ; ok
mov ax,word ptr dir_fs+17
CALL DISP_EXT_AX_dos
mov ax,word ptr dir_fs+19
CALL DISP_EXT_AX_dos
READ_SECTOR PROC NEAR
;in:es:bx input buf
;ds:dir_fs ds=0
MOV AH,2
MOV DX,WORD PTR DIR_FS+4 ;cylinder=7C4D
MOV CL,6
SHL DH,CL
OR DH,DIR_FS+6 ;sector=7C4F
MOV CX,DX
XCHG CH,CL
MOV DL,[SI+24H]
MOV DH,[SI+25H] ;head
INT 13H
RET
READ_SECTOR ENDP
SECTOR_ADDR PROC NEAR
;in : dx:ax= logical sector_no
ADD AX,1
ADC DX,+0
ADD AX,[SI+1CH]
ADC DX,[SI+1EH] ;DX:AX =A
PUSH AX
PUSH DX
MOV AX,[SI+1AH]
MUL WORD PTR [SI+18H]
MOV WORD PTR DIR_FS+11,AX
POP DX
POP AX
DIV WORD PTR DIR_FS+11
MOV WORD PTR DIR_FS+4,AX ;Cylinder_no
XCHG AX,DX
XOR DX,DX
DIV WORD PTR [SI+18H]
MOV [SI+25H],AL ;head_no
MOV DIR_FS+6,DL ;Sector_no 7C4f
CLC
RET
EEE: STC
RET
SECTOR_ADDR ENDP
DO_ERROR PROC NEAR
MOV AX,1301H ;display M1
MOV DX,0A00H
MOV BX,7H
;MOV BP,OFFSET ERROR1
MOV SI,BP
MOV CL,[SI]
XOR CH,CH
INC BP
INT 10H
;DO_ERROR0: JMP DO_ERROR0 ;OK after test
RET
DO_ERROR ENDP
;;;;;;;;;;;AAAAAAAAA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
G_EXEC_LOAD PROC FAR
;in---- (ds)=system data segment
; (gs)=head+program(cos.exe)=1000H
; DS:G_WORK 100 DB PARA AREA
PUSH ES
MOV BX,GS:00H
CMP BX,5A4DH
JZ G_EXEC0
MOV AX,1 ;Not DOS .exe first 2 bytes is 4D5AH
JMP G_EXEC_END
;*********************get program_size
G_EXEC0:
; set ldt_desc for CS OF USER PROCESS -->START
MOV AX,GS:08H ;SIZE_HEAD PARA
SHL AX,4 ;SIZE_HEAD BYTE
PUSH AX ;SS:1=SIZE_HEAD BYTE INTO STACK
;;;;;;;;; ;GET FILE_SIZE
MOV BX,GS:02H ;mod512
MOV AX,GS:04H ;file_sectors
CMP BX,0
JZ g_exec1
DEC AX
g_exec1: XOR DX,DX
MOV CX,512
MUL CX
ADD AX,BX
ADC DX,0 ;DX:AX file_size
MOV DS:G_WORK,AL
MOV DS:G_WORK[1],AH
MOV DS:G_WORK[2],DL
MOV DS:G_WORK[3],DH ;0-3=FILE SIZE
POP BX ;GET SIZE_HEAD
;PUSH BX
MOVZX EBX,BX
MOV DWORD PTR DS:G_WORK[4],EBX ;4-7=SIZE_HEAD
MOV CX,WORD PTR GS:6H ;reposit_count LOOP
MOV BX,WORD PTR GS:18H ;position for re_position item
g_exec_1:
MOV AX,WORD PTR GS:[BX]
ADD AX,WORD PTR DS:G_WORK[4] ;OFFFSET
MOV DI,AX
MOV AX,WORD PTR GS:[BX+2]
ADD AX,1000H
MOV ES,AX
MOV AX,ES:[DI]
ADD AX,1000H
ADD AX,GS:08H
MOV ES:[DI],AX
ADD BX,4
LOOP g_exec_1
G_EXEC_END1:
; LOOP OTHER SEGMENT-----END
;POP DX
;*********************A -->end deal with loading .exe
G_EXEC_END:
POP ES
RET
G_EXEC_LOAD ENDP
;call DISP_EXT_AX_dos
;jmp G_EXEC_END1
M1 DB 17,'Start NUAA 3G-COS'
FNAME0 DB 'COS EXE'
ERROR1 DB 15H,'Non-System disk error'
ERROR2 DB 10H,'Error loading OS'
DIR_FS DB 21 DUP(0)
G_WORK DB 100 DUP(0)
TTSECTOR DB 512 DUP(?)
t_string DB 100 DUP(0)
G_END:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;xxxxxxxxxxxxxx next for test
DISP2_16_dos PROC FAR
;in al code 2 using ah
;out ah:al:code 16
mov ah,al
MOV CL,4
shr ah,CL
cmp ah,9
jle disp2_16_1_dos
add ah,7
disp2_16_1_dos: add ah,30h
and al,0fh
cmp al,9
jle disp2_16_2_dos
add al,7
disp2_16_2_dos: add al,30h
RET
DISP2_16_dos ENDP
DISP_EXT_AX_dos PROC FAR
;in cx:position
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV BX,AX
mov al,BH
CALL DISP2_16_dos
mov DS:t_string,ah
mov DS:t_string[1],al
MOV AL,BL
CALL DISP2_16_dos
mov DS:t_string[2],ah
mov DS:t_string[3],al
mov DS:t_string[4],' '
mov DS:t_string[5],'$'
MOV AH,9
MOV DX,OFFSET t_string
;add dx,16
INT 21H
POP DX
POP CX
POP BX
POP AX
RET
DISP_EXT_AX_dos ENDP
;;xxxxxxxxxxxxxx next for test
START_TEST:
CLI
MOV AX,SEG CODE
MOV SS,AX
MOV AX,OFFSET STACK0
ADD AX,1024
MOV SP,AX
MOV AX,SEG CODE
MOV ES,AX
MOV DS,AX
CLD
;;;;;;;;;;;;;;;;;;;;; save to C:\TC\G\LOAD.3G
MOV DX,OFFSET FNAME
MOV CX,0
MOV AH,3CH ;CREAT FILE
INT 21H
MOV AL,01H ;FOR WRITE
MOV AH,3DH ;OPEN FILE
INT 21H
MOV BX,AX ;BX=FILE HANDLE
MOV DX,OFFSET START
MOV CX,start_test ; OFFSET G_END ;for test 1/1
SUB CX,DX
MOV AH,40H ;WRITE FILE
INT 21H
MOV AH,3EH ;CLOSE FILE
INT 21H
MOV AX,4C00H
INT 21H
FNAME DB 'C:\TC\G\LOAD.3G',0
STACK0 DB 1024 DUP(?)
CODE ENDS
END START_TEST
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -