XENIX 86 (360K Floppdisk) Boot Sector ; Erdošan Tan 20-6-2012 ; Memory Location: 0:7C00h ; Disk Address: Sector 0 ; ; -=========================================================================¬ ; ¦ This file is generated by The Interactive Disassembler (IDA) ¦ ; ¦ Copyright (c) 2010 by Hex-Rays SA, ¦ ; ¦ Licensed to: Freeware version ¦ ; L=========================================================================- ; ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; File Name : C:\xenix86\n1.img ; Format : Binary file ; Base Address: 0000h Range: 7C00h - 61C00h Loaded length: 5A000h ; .8086 .model flat ; =========================================================================== ; Segment type: Pure code seg000 segment byte public 'CODE' assume cs:seg000 ;org 7C00h assume es:nothing, ss:nothing, ds:nothing jmp far ptr 7C0h:5 loc_7C05: ; 7C0h:5h mov ax, cs mov ds, ax mov ss, ax mov sp, 5000h sti xor ax, ax mov es, ax mov bx, 7E00h mov ax, 201h mov dx, 0 mov cx, 2 int 13h ; DISK - READ SECTORS INTO MEMORY ; AL = number of sectors to read, CH = track, CL = sector ; DH = head, DL = drive, ES:BX -> buffer to fill ; Return: CF set on error, AH = status, AL = number of sectors read mov word ptr ds:216h, 0 mov word ptr ds:218h, 3000h lds si, es:78h ; INT 1Eh, Diskette parameter table pointer xor di, di mov ax, 4200h mov es:78h, di mov es:7Ah, ax ; 4200h:0h mov es, ax assume es:nothing mov cx, 6 ; 12 byte parameter table copy to the new address cld rep movsw mov di, 4 ; Last sector on a track mov byte ptr es:[di], 0Fh ; Last sector is 15 mov ax, cs mov ds, ax mov ax, 2 push ax ; inode number = 2 (root directory) call sub_7D07 ; iget, get inode pop ax loc_7C5B: ; CODE XREF: seg000:7C8Bj call sub_7D34 ; rmblock, read mapped block ; root directory is loaded at 4000h:0h mov dx, 40h ; 64 directory entry in the block push cs pop ds mov ax, 4000h mov es, ax assume es:nothing mov bx, 0 loc_7C6B: ; CODE XREF: seg000:7C89j mov ax, es:[bx+0] ; inode number add bx, 2 test ax, ax jz short loc_7C84 mov si, 200h ; file name, "boot" mov di, bx mov cx, 0Eh ; comparise "boot" file name cld repe cmpsb jcxz short loc_7C8D ; loc_7C84: ; CODE XREF: seg000:7C75j add bx, 0Eh ; file name length = 14 bytes dec dx ; dec entry counter jnz short loc_7C6B jmp short loc_7C5B ; infinitive loop ? ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; load file ; "/boot" file is in 26th sector of N1 (360K) floppy ; n1.img byte byte offset is 3400h (62h, 2Ch, 0, 7Fh, 3Dh, 0, 0) loc_7C8D: ; CODE XREF: seg000:7C82j push ax call sub_7D07 ; iget, get inode pop ax mov word ptr ds:21Ah, 0 ; reset file pointer call sub_7D34 mov ax, 4000h mov es, ax mov si, 34h ; mov ax, es:[si] mov si, ax ; mov ax, es:[si+0Ch] ; ("boot") file size (18293) mov cx, ax ; mov ax, es:[si+8] ; Boot file header size (80) mov si, ax ; beginning of boot file code mov di, 0 mov ax, 3000h mov es, ax assume es:nothing mov ax, 4000h mov ds, ax assume ds:nothing cld loc_7CC2: ; CODE XREF: seg000:loc_7CD6j movsb cmp si, 400h ; 1024 byte jb short loc_7CD6 push cs pop ds assume ds:nothing call sub_7D34 ; read mapped block mov ax, 4000h mov ds, ax assume ds:nothing mov si, 0 loc_7CD6: ; CODE XREF: seg000:7CC7j loop loc_7CC2 ; cx=0 -> End of file push cs pop ds assume ds:nothing ; waiting loop ? mov ax, 5 loc_7CDD: ; CODE XREF: seg000:7CE6j mov cx, 0FFFFh loc_7CE0: ; CODE XREF: seg000:loc_7CE0j loop loc_7CE0 dec ax cmp ax, 0 jnz short loc_7CDD ; end of waiting loop cli mov si, 20Eh ; address of "fd(4,0)" mov ax, 3000h mov es, ax mov di, 10h loc_7CF4: ; CODE XREF: seg000:7CF8j lodsb ; copy "fd(4,0)" to 3000h:10h stosb or al, al jnz short loc_7CF4 push ds pop es assume es:nothing mov ax, 3000h mov ds, ax assume ds:nothing jmp dword ptr es:216h ; 3000h:0h ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ db 0C3h ; + ; --------------- S U B R O U T I N E --------------------------------------- ; Attributes: bp-based frame ; iget, get the inode for specificied inode number sub_7D07 proc near ; CODE XREF: seg000:7C57p ; seg000:7C8Ep arg_0 = word ptr 2 mov bp, sp mov si, [bp+arg_0] ; Inode number (ax) dec si mov ax, si mov cl, 4 shr ax, cl ; 64 inode in 1 block add ax, 2 ; Block 2 is the inode list offset call sub_7D7C ; Read disk block and si, 0Fh ; 16 inode per block (inode offset) mov cl, 6 shl si, cl ; inode (byte) offset in block mov cx, 20h ; 32 word (64 byte) mov di, 220h ; inode location push ds pop es assume es:nothing mov ax, 4000h ; Block (2 sectors) Buffer mov ds, ax assume ds:nothing cld rep movsw ; move 32 words (inode structure) push cs pop ds assume ds:nothing retn sub_7D07 endp ; --------------- S U B R O U T I N E --------------------------------------- ;read mapped block ;rmblock ;read file sub_7D34 proc near ; CODE XREF: seg000:loc_7C5Bp ; seg000:7C98p ... push cx push es mov ax, ds:21Ah ; file offset mov cl, 0Ah ; 1 block has 1024 bytes (2^10) shr ax, cl ; convert file offset to block cmp ax, 0Ah ; < block 10 (direct block) jl short loc_7D61 mov bx, 24Ah ; single indirect block pointer push ax mov ax, [bx+0] ; indirect block address call sub_7D7C ; read block pop ax sub ax, 0Ah ; single indirect block list ; begins with address of 10th data ; block at offset 0 mov cl, 2 ; 2 bytes per pointer shl ax, cl mov bx, ax ; byte offset in the list mov ax, 4000h ; Buffer segment mov es, ax assume es:nothing mov ax, es:[bx+0] ; put the data block address in ax jmp short loc_7D6D ; read/load data block ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; get data block address (by using data block pointer) loc_7D61: ; CODE XREF: sub_7D34+Cj mov bx, 22Ch ; beginning of data block pointers ; in inode add bx, ax ; every pointer has 3 bytes (length) add ax, ax add bx, ax mov ax, [bx+0] ; address in the calculated pointer ; read data block & update file pointer loc_7D6D: ; CODE XREF: sub_7D34+2Bj call sub_7D7C ; read disk block mov ax, ds:21Ah ; file offset/pointer add ax, 400h ; add 1024 bytes to the count mov ds:21Ah, ax ; update file offset/pointer pop es assume es:nothing pop cx retn sub_7D34 endp ; --------------- S U B R O U T I N E --------------------------------------- ; read disk block sub_7D7C proc near ; CODE XREF: sub_7D07+Fp ; sub_7D34+15p ... push dx push es mov byte ptr ds:21Ch, 2 ; 2 sectors mov cl, 1 shl ax, cl ; 1 block = 2 sectors mov bx, 12h ; 18 sectors per cylinder sub dx, dx ; 0 div bx ; Cyl number is in DX:AX mov ds:21Eh, al ; Cyl number (max:40) mov byte ptr ds:21Fh, 0 ; Head = 0 inc dl ; sector in track cmp dl, 9 jg short loc_7DA7 ; Head is 1 if sector no > 9 jl short loc_7DAF mov byte ptr ds:21Ch, 1 ; Only 1 sector if sector is 9 (the last) jmp loc_7DAF ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ loc_7DA7: ; CODE XREF: sub_7D7C+1Fj mov byte ptr ds:21Fh, 1 ; Head = 1 sub dl, 9 ; Sector is in head 1 loc_7DAF: ; CODE XREF: sub_7D7C+21j ; sub_7D7C+28j mov ds:21Dh, dl ; sector in track (2 tracks per cylinder) mov ax, 4000h mov es, ax ; (Read) Buffer is at 4000h:0000h assume es:nothing mov bx, 0 loc_7DBB: ; CODE XREF: sub_7D7C+71j mov ah, 2 mov al, ds:21Ch mov ch, ds:21Eh mov cl, ds:21Dh mov dh, ds:21Fh mov dl, 0 int 13h ; DISK - READ SECTORS INTO MEMORY ; AL = number of sectors to read, CH = track, CL = sector ; DH = head, DL = drive, ES:BX -> buffer to fill ; Return: CF set on error, AH = status, AL = number of sectors read jb short loc_7DF0 cmp byte ptr ds:21Ch, 2 jz short loc_7DFD cmp byte ptr ds:21Dh, 1 ; head 1, sector 1 jz short loc_7DFD mov byte ptr ds:21Dh, 1 mov bx, 200h ; Buffer offset = old offset + 200h mov byte ptr ds:21Fh, 1 ; read head 1 & sector 1 jmp loc_7DBB ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ;; Print error "E" loc_7DF0: ; CODE XREF: sub_7D7C+54j mov ax, 500h int 10h ; - VIDEO - SELECT DISPLAY PAGE ; AL = display page, 0-7 for modes 0 & 1, 0-3 for modes 2 & 3 mov ax, 0E45h mov bx, 7 int 10h ; - VIDEO - WRITE CHARACTER AND ADVANCE CURSOR (TTY WRITE) ; AL = character, BH = display page (alpha modes) ; BL = foreground color (graphics modes) loc_7DFD: ; CODE XREF: sub_7D7C+5Bj ; sub_7D7C+62j pop es assume es:nothing pop dx retn sub_7D7C endp ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ org 200h db 62h ; b db 6Fh ; o db 6Fh ; o db 74h ; t db 0 db 0 db 0 db 0 db 0 db 0 db 0 db 0 db 0 db 0 byte_20E: db 66h ; f db 64h ; d db 28h ; ( db 34h ; 4 db 2Ch ; , db 30h ; 0 db 29h ; ) db 0 dword_216 dd 0 ; DATA XREF: seg000:0021w ; seg000:0101r ... word_21A dw 0 ; DATA XREF: seg000:0092w ; sub_134+2r ... sectorcount: byte_21C db 0 ; DATA XREF: sub_17C+2w ; sub_17C+23w ... sector: byte_21D db 0 ; DATA XREF: sub_17C:loc_1AFw ; sub_17C+48r ... track: byte_21E db 0 ; DATA XREF: sub_17C+12w ; sub_17C+44r head: byte_21F db 0 ; DATA XREF: sub_17C+15w byte_220: ; sub_17C:loc_1A7w ... i_node: ; 64 byte inode, db 64 dup(0) db 69h ; i db 63 dup(0F6h)