XENIX 86 (360K Floppdisk) Boot Sector
; Erdoan 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, <support@hex-rays.com>           
;                       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:7C8Bj
                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:7C89j
                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:7C75j
                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:7C82j
                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_7CD6j
                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:7CC7j
                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:7CE6j
                mov     cx, 0FFFFh
loc_7CE0:                               ; CODE XREF: seg000:loc_7CE0j
                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:7CF8j
                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:7C57p
                                        ; seg000:7C8Ep
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_7C5Bp
                                        ; seg000:7C98p ...
                 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+Cj
                 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+2Bj
                 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+Fp
                                         ; sub_7D34+15p ...
                 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+1Fj
                 mov     byte ptr ds:21Fh, 1	; Head = 1
                 sub     dl, 9		; Sector is in head 1

loc_7DAF:                               ; CODE XREF: sub_7D7C+21j
                                        ; sub_7D7C+28j
                 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+71j
                 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+54j
                 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+5Bj
                                         ; sub_7D7C+62j
                 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:0021w
                                        ; seg000:0101r ...
word_21A        dw 0                    ; DATA XREF: seg000:0092w
                                        ; sub_134+2r ...
sectorcount:
byte_21C        db 0                    ; DATA XREF: sub_17C+2w
                                        ; sub_17C+23w ...
sector:
byte_21D        db 0                    ; DATA XREF: sub_17C:loc_1AFw
                                        ; sub_17C+48r ...
track:
byte_21E        db 0                    ; DATA XREF: sub_17C+12w
                                        ; sub_17C+44r
head:
byte_21F        db 0                    ; DATA XREF: sub_17C+15w

byte_220:				; sub_17C:loc_1A7w ...
i_node:                             	
; 64 byte inode, db 64 dup(0)
db  69h ; i
db 63 dup(0F6h)