📄 first-dos.s
字号:
mov bx,cs ; return address of BOOTP record mov dx,CON(btpnew) SEGCS mov cx,LOC(btplen) ; return BOOTP length iretintF82: cmp al,CON(0x03) jne intF83 mov bx,cs ; return address of old interrupt mov dx,CON(oldints) ; vector table SEGCS mov cl,LOC(drvid) ; return drive id SEGCS mov ax,LOC(xmshdl) ; return XMS handle iretintF83: cmp al,CON(0x04) jne intF88 call rmrd ; remove ramdisk iretintF88: or al,al jnz intF89 xchg al,ah ; return installation check codeintF89: iret;====================================================================;; New interrupt 13h routine to handle disk accesses. It is different; for simulating either a floppy drive or a hard disk. DOS provides; a way for restoring this interrupt to its original value when we; want to remove the ramdisk lateron.; Input: AH - function code; DL - driver number; Output: carry flag set if error; Registers changed: depends on functionint13: sti ; we dont need interrupts disabled push ax SEGCS mov ax,LOC(xmsadr+0) SEGCS or ax,LOC(xmsadr+2) ; check if XMS already initialized jnz int13s mov ax,CON(0x4300) ; check if XMS available int 0x2f cmp al,CON(0x80) ; XMS not available jne int13s push bx push es mov ax,CON(0x4310) ; get XMS driver address int 0x2f SEGCS mov LOC(xmsadr+0),bx ; save driver address SEGCS mov LOC(xmsadr+2),es pop es call inixms ; initialize XMS pop bxint13s: pop ax SEGCS cmp dl,LOC(drvid) ; check if its for us je int132 SEGCS cmp BLOC(drvid),CON(0x80) ; check if we are to simulate a hard jae int13h ; disk drive; First comes the floppy drive redirector cmp dl,CON(0x80) ; check if its for a hard disk jb int133 SEGCS test BLOC(nohd),CON(0xff) ; check if hard disk accesses allowed jz int131 cmp ah,CON(0x08) ; function 0x08 should not return error mov ah,CON(0x80) ; return with error jne int135 xor dl,dl ; indicate no hard disk present JMP(int13f) ; return without error; Handle function 0x08 for disk drives other than the ramdisk.int133: cmp ah,CON(0x08) jne int131 pushf SEGCS ; function 0x08 has to return the call far [old13h] ; correct number of disk drives SEGCS mov dl,LOC(drvnum)int13f: xor ah,ah ; never return an error JMP(int136); Jump directly to the BIOSint131: SEGCS jmp far [old13h] ; call the old interrupt routine; Now handle all ramdisk functions. First check if the function number; is correct.int132: cmp ah,CON(0x18) jbe int134 mov ah,CON(0x01) ; unknown commandint135: stcint136: push ds JMP(int13e); Determine the handlers address according to the function number in AH; and jump to it.int134: push ds push cs pop ds ; set data segment push bx mov bl,ah xor bh,bh shl bx,CON(1) ; compute pointer into routine table jmp [bx+fntab]; Now comes the hard disk drive redirectorint13h: cmp dl,CON(0x80) ; check if its for a floppy drive jb int131; Handle function 0x08 for hard disk drives other than the ramdisk. cmp ah,CON(0x08) jne int137 dec dl pushf SEGCS ; function 0x08 has to return the call far [old13h] ; correct number of disk drives SEGCS mov dl,LOC(drvnum) JMP(int13f) ; always return without error; Handle function 0x15 for disk drives other than the ramdisk. This is; the only function besides 0x08 which returns a value in DX and therefore; has to have special handling.int137: push dx dec dl cmp ah,CON(0x15) jne int138 pushf SEGCS call far [old13h] ; call the BIOS for handling jc int139 cmp ah,CON(0x03) ; DX is only used if AH = 0x03 jne int139 add sp,BCON(0x0002) ; remove DX from stack if the BIOS JMP(int136) ; returned a value in it; Handle all other functions for drives other than the ramdisk. This will; just call the original BIOS handler.int138: pushf SEGCS call far [old13h] ; simply call the old int 13h routineint139: pop dx JMP(int136); Save the return status into the BIOS data area and return to the caller; while preserving the carry flag.int13e: push es ; return from function handler push bx ; this code is not allowed to change call getsts ; any register or flag SEGES mov [bx],ah ; set disk operation status pop bx pop esintend: pop ds push ax ; general exit point for interrupts pushf pop ax push bp mov bp,sp mov [bp+8],al ; put the flags onto the stack pop bp pop ax iret; Function tablefntab: dw f1300 ; function 00: reset disk system dw f1301 ; function 01: return last error dw f1302 ; function 02: read disk dw f1303 ; function 03: write disk dw f1304 ; function 04: verify disk dw f1305 ; function 05: format disk dw f1306 ; function 06: format track dw f1307 ; function 07: format disk dw f1308 ; function 08: get drive parameters dw f1309 ; function 09: intialize controller dw f130A ; function 0A: read long sectors dw f130B ; function 0B: write long sectors dw f130C ; function 0C: seek for cylinder dw f130D ; function 0D: disk reset dw f130E ; function 0E: read sector buffer dw f130F ; function 0F: write sector buffer dw f1310 ; function 10: check if drive ready dw f1311 ; function 11: recalibrate drive dw f1312 ; function 12: controller ram diagnostic dw f1313 ; function 13: drive diagnostic dw f1314 ; function 14: controller int diagnostic dw f1315 ; function 15: get disk type dw f1316 ; function 16: detect disk change dw f1317 ; function 17: set media type for format dw f1318 ; function 18: set media type for formatf13end: JMP(int13e);====================================================================;; Function 00 - reset disk system;f1300: test WLOC(syscnf),CON(0x0001) ; check if we have physical floppy jz f13001 ; drives at all push dx xor dl,dl ; always reset the floppy system pushf call far [old13h] ; call old disk interrupt pop dx jc f13002f13001: xor ah,ah ; no errorf13002: pop bx JMP(f13end);====================================================================;; Function 01 - return last error status;f1301: push es call getsts ; get offset to status byte SEGES mov ah,[bx] ; get disk operation status pop es pop bx clc JMP(intend);====================================================================;; Function 02/03 - read from/write to diskf1302:f1303: pop bx ; get old BX from stack push dx push cx push bx push ax xchg cx,ax sub ch,2 ; ch=0 for reads, ch=1 for writes call cvtsec ; get linear sector number jnc f13026 pop ax mov ah,CON(0x04) ; error: sector not foundf13021: pop bx pop cx pop dx stc JMP(f13end) ; terminatef13022: cmp dx,LOC(secnumhi) ; check if sector is still correct jb f13024 cmp ax,LOC(secnumlo) jbe f13024 mov ah,CON(0x04) ; error: sector not foundf13023: pop bx mov al,bl sub al,cl ; compute number of sectors processed JMP(f13021)f13024: call rwsect ; actually handle request jnc f13025 mov ah,CON(0x20) ; error: disk controller error JMP(f13023)f13025: inc ax ; proceed with next linear sector adc dx,CON(0) add bx,CON(SECT_SIZE) ; increment src/dst address dec cl ; decrement sector countf13026: or cl,cl jnz f13022f13027: pop ax pop bx pop cx pop dx xor ah,ah ; no errorf13e1: JMP(f13end);====================================================================;; Function 08 - get disk drive parametersf1308: pop bx ; get old BX from stack mov dl,LOC(drvnum) ; get number of disk drives mov cl,LOC(secptk) ; get sectors per track mov ch,LOC(cylnum) ; number of cylinders mov dh,LOC(heads) ; number of heads - 1 dec dh xor bx,bx ; ramdisk drive type xor ax,ax dec ch JMP(f13e1);====================================================================;; Function 04, 05, 06, 07, 09, 0D, 10, 11, 12, 13, 14, 16 - no operationf1304:f1305:f1306:f1307:f1309:f130D:f1310:f1311:f1312:f1313:f1314:f1316: pop bx ; get old BX from stack xor ah,ah ; no error JMP(f13e1);====================================================================;; Function 0A, 0B, 0E, 0F, 17, 18 - not implementedf130A:f130B:f130E:f130F:f1317:f1318: pop bx ; get old BX from stack mov ah,CON(0x01) ; invalid opcode stc JMP(f13e1);====================================================================;; Function 0C - seek for cylinderf130C: pop bx ; get old BX from stack push dx push cx push ax xchg ax,cx call cvtsec ; get linear sector number pop ax mov ah,CON(0x00) ; no error jnc f130C1 mov ah,CON(0x04) ; error: sector not foundf130C1: pop cx pop dx JMP(f13e1) ; terminate;====================================================================;; Function 15 - get disk typef1315: pop bx ; get old BX from stack mov ah,CON(0x02) ; indicate floppy disk cmp dl,CON(0x80) ; check if floppy disk type requested jb f13159 inc ah ; indicate hard disk mov dx,LOC(secnumlo) ; get number of sectors on disk mov cx,LOC(secnumhi)f13159: clc JMP(f13e1);====================================================================;; Convert Cyl/Sec/Head notation into a linear sector number; Input: AH - cylinder number; AL - sector number; DH - head number; Output: DX:AX - 32-bit linear sector number; carry flag set if invalid sector number; Registers changed: AX,DXcvtsec: push bx push cx mov bl,al ; move sector number into BL mov bh,dh ; move head number into BH xchg ah,al ; compute track number into AX, the mov cl,CON(6) ; upper two bits of CL are the high shr ah,cl ; bits of the 10 bit cylinder number xor dx,dx xor cx,cx mov cl,LOC(heads) mul cx ; compute track number from cylinders mov cl,bh add ax,cx adc dx,CON(0) mov cl,LOC(secptk) push bx xor bx,bx or dx,dx ; is 32-bit value > 16-bits yet? jz cvts6 push ax push dx mov ax,dx ; multiply upper 16-bits first mul cx mov bx,ax ; save result in bx pop dx pop axcvts6: mul cx ; compute number of track starting add dx,bx ; fixup upper 16-bits pop bx mov cl,bl and cl,CON(0x3F) ; move sector number into AX cmp cl,LOC(secptk) ; check if sector number is correct ja cvts8 dec cx ; sector numbers start with 1 js cvts8 ; therefore sector 0 does not exist add ax,cx ; compute final sector number adc dx,CON(0) cmp dx,LOC(secnumhi) ; check if the sector is valid jb cvts8 ja cvts7 cmp ax,LOC(secnumlo) jb cvts8cvts7: stc JMP(cvts9)cvts8: clc ; return with errorcvts9: pop cx pop bx ret;====================================================================;; Read/write a sector from the ram disk. This routine requires a; sector to be 512 bytes long.; Input: CH - non-zero if write to ram disk; DX:AX - logical sector number; ES:BX - pointer to destination buffer; Output: carry flag set if error; Registers changed: AXrwsect: push si push di push cx push dx push ax mov si,rd_srcb mov di,rd_dstb or ch,ch ; check direction of transfer jz rwsec1 mov si,rd_dstb mov di,rd_srcbrwsec1: mov cx,CON(SECT_SIZE) ; compute linear ramdisk address mul cx ; from sector number add ax,LOC(rdaddr+0) adc dx,LOC(rdaddr+2) mov [si],ax ; set src for read, dst for write mov [si+2],dl mov [si+5],dh mov ax,es
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -