📄 romos.asm
字号:
MOV DH,DL
CALL @WHB1 ;write lower digit / vytiskni dolni cislici
POPF
POP DX
POP AX
RET
@WHB1: CMP DH,0Ah ;compare if the digit is lower than 10 / porovnej, je-li cislo mensi nez 10 (0Ah)
JC @WHB2 ;if not then skip / neni-li preskoc dal
ADD DH,7 ;if yes then add 7 to get proper ASCII code / je-li, pricti 7 (rozdil ASCII kodu 'A' a '9'+1)
@WHB2: ADD DH,'0' ;add ASCII code of '0' / pricti ASCII kod '0'
MOV AH,0Eh ;write char / vypis znak
MOV AL,DH ;from AL / z AL
INT 10h ;via BIOS / pres BIOS
RET ;return / navrat
;*****************************************************************************
WREGS: PUSHA ;write register dump line and CRLF / vypis na radku registry a odradkuj
PUSH DS ;prepare all regs to stack / priprav vsechny registry do zasobniku
PUSH ES ;AX,CX,DX,BX,SP,BP,SI,DI, DS,ES,SS,CS, F
PUSH SS
PUSH CS
PUSHF
MOV CX,9 ;loop counter-9x repeat / pocitadlo smycky-9x oparuj
MOV SI,REGSTR ;prepare reg name / priprav jmeno registru
MOV BP,SP ;set BP=SP for indexing stored regs / priprav BP=SP pro indexaci ulozenych registru
@WREGS1:MOV BX,0107h ;seda barva, opakovani 1x
CALL WRITE ;write reg name / vypis jmeno registru
MOV AX,0E3Dh ;write char function, char '=' / funkce vypisu znaku, znak '='
XOR BL,BL ;paper color=0 / barva papiru=0
INT 10h ;write '=' via BIOS / vypis '=' pres BIOS
MOV DX,[SS:BP] ;load reg from stack to DX / nacti registr ze zasobniku do DX
CALL WHEXW ;write DX hexa value / vypis hexa hodnotu DX
MOV AL,' ' ;write char ' ' / vypis znak ' '
INT 10h ;via BIOS / pres BIOS
INC BP ;go up through the stack data / jdi v zasobniku na dalsi registr
INC BP
INC SI ;reg name pointer+=3 / nastav pointer na dalsi jmeno registru (+3)
INC SI
INC SI
LOOP @WREGS1 ;repeat until CX is nonzero / opakuj dokud je CX nenulove
CALL WCRLF ;newline / odradkuj
POPF ;restore regs and flag / obnov registry a flag
POP DS ;POP DS instead CS because it crashed under BOCHS
POP SS ;anyway CS was not changed during this routine
POP ES
POP DS
POPA
RET ;return / navrat
REGSTR DB 'F',0,0 ;strings with regs names / retezce s nazvy registru
DB 'CS',0
DB 'SS',0
DB 'ES',0
DB 'DS',0
DB 'DI',0
DB 'SI',0
DB 'BP',0
DB 'SP',0
;************** New INT 13h handler emulating virtual ROM disk, now supports functions 2,3,8
;************** Nova obsluha INT 13h emulujici virtualni ROM disk, nyni podporuje sluzby 2,3,8
NEW_INT13H: ;INT XX do CLI, PUSH F,CS,IP (6B) / INT XX provadi CLI, PUSH F,CS,IP (6B)
PUSHF ;store flags (2B) / uloz flagy (2B)
CMP DL,ROMDISK_DRIVE;related to our disk ? / tyka se to naseho disku?
JE @NEW_INT13H_HUB ;if yes continue below else / pokud ano, pokracuj nize, jinak
POPF ;restore flags (2B) and / obnov flagy (2B) a
JMP 0:OLD_INT13H-1 ;jump to old INT 13h handler using FAR JMP / skoc na puvodni preruseni INT 13h pomoci FAR JMP
@NEW_INT13H_HUB: ;subfunction hub / rozcestnik podfunkci
PUSHA ;store regs AX,CX,DX,BX,SP,BP,SI,DI (16B) / uloz registry...
PUSH DS ;store DS (2B) / uloz DS (2B)
CMP AH,02h ;function ?= 2h - read sectors / sluzba ?= 2h - cti sektory
JE @NEW_INT13H_02H
CMP AH,03h ;function ?= 3h - write sectors / sluzba ?= 3h - pis sektory
JE @NEW_INT13H_03H
CMP AH,08h ;function ?= 8h - get drive params / sluzba ?= 8h - vrat parametry disku
JE @NEW_INT13H_08H
CMP AH,15h ;function ?= 15h - get disk type / sluzba ?= 15h - vrat typ disku
JE @NEW_INT13H_15H
ADD AH,'A' ;infoflag of unhandled function (cislo 0=A, 1=B,...) / priznak neobslouzeni funkce
JMP @NEW_INT13HEND1 ;other? jump to end and let me know / jina? preskoc na konec a dej o tom vedet
@NEW_INT13H_02H: ;INT 13h: AH=func, DL=drive, DH=H, CH=C, CL=S,
PUSH AX ; AL=S-CNT, ES:BX=buffer of calling program
MOV DI,BX ;prepare destination address ES:BX->ES:DI / priprav cilovou adresu...
XOR SI,SI ;we prepare linear address to SI step by step / do SI si postupne pripravime linearni adresu
AND CL,03Fh ;number of sector is only 6-bit / cislo sektoru je jen 6-bitove (cyl<=80 u FD)
DEC CL ;BIOS numbers the sectors from starting 1, we need from 0 / BIOS cisluje sektory o 1, my potebujem od 0
MOV AX,ROMDISK_SECPT;SI=LINSEC=NH*NS*C + NS*H + (S-1)
MUL DH ;AX*DH->AX (NS*H)
ADD SI,AX ;add to SI (SI=NS*H) / pricti do SI
MOV AX,ROMDISK_HEADS;there's no check of CHS validity / neprovadi se zadna kontrola parametru CHS
MOV BL,ROMDISK_SECPT;so when CHS overflow it returns invalid data from memory / takze pri prekroceni adr. rozs. vraci nesmyslna data
MUL BL ;AX*BL->AX (NH*NS)
MUL CH ;AX*CH->AX (NH*NS*C)
ADD SI,AX ;add to SI (SI=NS*H + NH*NS*C) / pricti do SI
XOR CH,CH ;prepare S to CX / priprav S v CX
ADD SI,CX ;add to SI (SI=NH*NS*C + NS*H + (S-1)) / pricti do SI
SHL SI,9 ;recalc from sectors to Bytes (SI*512) / prepocti SI ze sektoru na Byty
ADD SI,IMG_BEGIN ;prepare source offset (and add offset to image) / priprav zdrojovy offset (jeste pricti offset na image)
PUSH CS ;prepare source segment / priprav zdrojovy segment
POP DS ;set DS=CS (ROM segment with disk image / segment ROM s image disku)
POP CX ;restore number of required sectors to CX / vyber pocet ctenych sektoru do CX
SHL CX,9 ;recalc number of sectors to number of Bytes (S-CNT*512) / prepocitej pocet sektoru na Byty
REP MOVSB ;copy until CX is nonzero / kopiruj dokud CX neni nulove
JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h
@NEW_INT13H_03H: ;ROM disk is read-only so return errorcode AH=3 / ROM disk je read-only, takze vrat chybu AH=3
MOV BP,SP ;set BP=SP / nastav BP=SP
MOV AX,[SS:BP+24] ;precti ze zasobniku FLAG (adr=2+16+2+2+2 objem dat v zasob. nad F)
OR AX,1 ;nahod bit CARRY (SP->DS,ALL,F,IP,CS ^)
MOV [SS:BP+24],AX ;zapis ho zpet
MOV [SS:BP+17],BYTE 3 ;nastav AH v zasobniku na kod chyby 3 (adr=16+2-1=DS+ALL)
JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h
@NEW_INT13H_08H: ;return CHS info about ROM disk geometry / vrat informace CHS o geometrii ROM disku
MOV BP,SP ;set BP=SP / nastav BP=SP
MOV CH,ROMDISK_CYLS ;set CH to number of cylinders / nastav CH na pocet cylindru
MOV CL,ROMDISK_SECPT;set CL to number of sectors per track / nastav CL na pocet sektoru/stopu
MOV [SS:BP+13],BYTE ROMDISK_HEADS ;nastav DH v zasob. - hlavy (adr=2+16-2-2-1=DS+ALL-AX-CX-DL)
MOV [SS:BP+14],CX ;nastav CX v zasobniku (adr=2+16-2-2=DS+ALL-AX-CX)
JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h
@NEW_INT13H_15H: ;ROM disk is like nonchangeable diskette drive / ROM disk je jako nevymenna disketova jednotka
MOV BP,SP ;set BP=SP / nastav BP=SP
MOV [SS:BP+17],BYTE 1 ;nastav AH v zasobniku na kod chyby 0 (adr=16+2-1=DS+ALL)
MOV [SS:BP+14],WORD 0 ;set CX=0 (total drive sectors high word to 0) / nastav vyssi slovo poctu sektoru na 0
MOV [SS:BP+12],WORD ROMDISK_CYLS*ROMDISK_HEADS*ROMDISK_SECPT ;set DX=total drive sectors / nastav DX=celkovy pocet sektoru
JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h
@NEW_INT13HEND: ;INT 13h watcher (work in textmode only / funguje jen v textovem modu)
MOV AH,'*' ;flag of hanled function / priznak obslouzeni funkce
@NEW_INT13HEND1:
PUSH WORD 0B800h
POP DS ;set DS=B800h (segment of textmode VRAM on VGA / segment textove VRAM u VGA)
MOV [DS:79*2],AH ;write flag character to top-right corner from AH / do praveho horniho rohu obrazovky vykresli znak z AH
POP DS ;restore DS (2B) / obnov DS (2B)
POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) / obnov registry...
POPF ;restore flags (2B) / obnov flagy (2B)
IRET ;return from an interrupt do POP IP,CS,F (6B) / navrat z preruseni provadi...
;*****************************************************************************
INSTALL_NEW_INT13H: ;install new INT 13h handler / nainstaluj novou obsluhu INT 13h
PUSHA ;and write message about vector change + CRLF / a vypise hlaseni o zmene vektoru a odradkuje
PUSH ES ;store ES / uloz ES
PUSH BYTE 0 ;push 00
POP ES ;pop 0000 (ES=0) / vynuluj ES
MOV SI,13h*4 ;set SI at INT 13h IVT position / nastav SI na pozici vektoru INT 13h v IVT
MOV DI,OLD_INT13H ;set DI at free INT 85h IVT position / nastav DI na volnou pozici vektoru INT 85h v IVT
MOV CX,[ES:SI] ;load original offset of INT 13h handler from IVT to CX / nacti do CX offset puvodni obsluhy INT 13h z IVT
MOV [ES:DI],CX ;store it to other safe place in IVT / uloz ho na jine bezpecne misto v IVT
MOV DX,[ES:SI+2] ;load original segment of INT 13h handler from IVT to DX / nacti do DX segment puvodni obsluhy INT 13h z IVT
MOV [ES:DI+2],DX ;store it to other safe place in IVT / uloz ho na jine bezpecne misto v IVT
MOV [ES:DI-1],BYTE 0EAh ;opcode FAR JMP (dynamically modified instruction / dynamicky menena instrukce)
MOV [ES:SI],WORD NEW_INT13H ;set offset of new INT 13h handler / nastav offset nove obsluhy INT 13h
MOV [ES:SI+2],CS ;set segment of new INT 13h handler (current-ROM) / nastav segment nove obsluhy INT 13h (aktualni-ROM)
MOV SI,IINTSTR ;write hook INT 13h vector message / vypis zpravu o zmene vektoru INT 13h
MOV BX,0107h ;grey color, 1-times / seda barva, opakovani 1x
CALL WRITE
CALL WHEXPTR ;write original vector DX:CX / vypis puvodni vektor DX:CX
MOV SI,AROWSTR
CALL WRITE ;write / vypis ' -> '
MOV DX,CS
MOV CX,WORD NEW_INT13H
CALL WHEXPTR ;write new vector DX:CX (CS:NEW_INT13H) / vypis novy vektor DX:CX
CALL WCRLF ;newline / odradkuj
POP ES
POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) / obnov registry...
RET ;return / navrat
IINTSTR DB 'INT13h vector has been hooked ',0
AROWSTR DB ' -> ',0
;************** Initial code - modify carefully! / Pocatecni kod, upravujte s max. opatrnosti!
BEGIN: PUSHF ;store flags (2B) / uloz flagy (2B)
PUSHA ;store regs AX,CX,DX,BX,SP,BP,SI,DI (16B) / uloz registry...
MOV AX,SS ;set AX=original SS / nastav AX=puvodni SS
PUSH NEW_SS ;set new bigger stack (BIOS use default SS=0 SP=0Dxx - small) / nastav novy vetsi zasobnik...
POP SS ;segment
MOV BX,NEW_SP ;offset
XCHG BX,SP ;set BX=original SP / nastav BX=puvodni SP
PUSH AX ;store configuration of original stack - SS / uloz konfiguraci stareho zasobniku - SS
PUSH BX ;store configuration of original stack - SP / uloz konfiguraci stareho zasobniku - SP
PUSH ES ;store ES / uloz ES
PUSH DS ;store DS / uloz DS
;TEST FOR 1ST RUN-ROMSCAN/2ND RUN-INT19H CALL
%ifdef HOOK_INT19H ;only if we want to hook INT 19h otherwise skip this / jen pokud chceme hooknout INT 19h
PUSH BYTE 0 ;push 00
POP ES ;pop 0000 (ES=0, segment of IVT) / nastav ES=0, segment IVT
CMP [ES:INT19H],WORD BEGIN ;compare if offset match the BEGIN label / porovnej, shoduje-li se offset s labelem BEGIN
JNE RUN1ST ;if not it means that's 1st run-ROMSCAN / pokud ne, znamena to, ze bezime poprve-ROMSCAN
MOV AX,CS ;set AX=CS (cannot compare CS directly / CS nelze primo porovnavat)
CMP [ES:INT19H+2],AX;compare if segment match the current CS segment / porovnej, shoduje-li se segment s aktualnim CS
JNE RUN1ST ;if not it means that's 1st run-ROMSCAN / pokud ne, znamena to, ze bezime poprve-ROMSCAN
JMP BOOT ;else continue next phase at BOOT label / jinak pokracuj v dalsi fazi na labelu BOOT
%endif
;ASK FOR BOOT ROMOS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -