Operating Systems
Operating Systems
This is a little old but a good place to start learning the essentials about operating systems. First you would need to have the emu8086 assembler and emulator or something alike.
8086 Microprocessor Emulator Emu8086 is the emulator of 8086 (Intel and AMD compatible) microprocessor with integrated 8086 assembler and tutorials for beginners. The emulator runs programs like the real microprocessor in step-by-step mode. It shows registers, memory, stack, variables and flags. All memory values can be investigated and edited by a double click. The instructions can be executed in a regular forward direction and also in reverse direction. emu8086 can create a tiny operating system and write its binary code to a bootable floppy disk. This software package includes several virtual external devices: robot, stepper motor, led display, and traffic lights intersection. Virtually anyone with any programming experience can design animated virtual devices in assembly language or in any other programming language. All devices are open for modifications and cloning (source code is available). All communications between the microprocessor and devices is coming through this file: c:\emu8086.io, to emulate in/out instructions its just required to change corresponding bytes in this binary file. Tutorials, examples and 8086 microprocessor references are inside. Click here to download free evaluation version or click here to purchase. Creating the bootable floppy Usually, when a computer starts it will try to load the first 512-byte sector (thats Cylinder 0, Head 0, Sector 1) from any diskette in your A: drive to memory location 0000h:7C00h and give it control. If this fails, the BIOS tries to use the MBR of the first hard drive instead.
This tutorial covers booting up from a floppy drive, the same principles are used to boot from a hard drive. But using a floppy drive has several advantages: * you can keep your existing operating system intact (windows, dos, linux, unix, beos). * it is easy and safe to modify the boot record of a floppy disk. example of a simple floppy disk boot program:
; directive to create BOOT file: #make_boot# ; Boot record is loaded at 0000:7C00, ; so inform compiler to make required ; corrections: ORG 7C00h PUSH POP CS DS ; make sure DS=CS
; load message address into SI register: LEA SI, msg ; teletype function id: MOV AH, 0Eh print: MOV AL, [SI] CMP AL, 0 JZ done INT 10h INC SI JMP print ; wait for any key: done: MOV AH, 0 INT 16h ; store magic value at 0040h:0072h: ; ; 0000h cold boot. 1234h warm boot. ; print using teletype.
new_line EQU 13, 10 msg DB DB Hello This is My First Boot Program! new_line, Press any key to reboot , 0
copy the above example to the source editor and press emulate. the emulator automatically loads .bin file to 0000h:7C00h (it uses supplementary .binf file to know where to load). you can run it just like a regular program, or you can use the virtual drive menu to write 512 bytes at 7c00h to boot sector of a virtual floppy drive (its FLOPPY_0 file in Emulators folder). after your program is written to the virtual floppy drive, you can select boot from floppy from virtual drive menu. .bin files for boot records are limited to 512 bytes (sector size). if your new operating system is going to grow over this size, you will need to use a boot program to load data from other sectors (just like micro-os_loader.asm does). an example of a tiny operating system can be found in c:\emu8086\examples: micro-os_loader.asm micro-os_kernel.asm To create extensions for your operating system (over 512 bytes), you can use additional sectors of a floppy disk. Its recommended to use .bin files for this purpose (to create .bin file select BIN Template from File -> New menu). To write .bin file to virtual floppy, select Write .bin file to floppy from Virtual drive menu of emulator, you should write it anywhere but the boot sector (which is Cylinder: 0, Head: 0, Sector: 1).
you can use this utility to write .bin files to virtual floppy disk (FLOPPY_0 file), instead of write 512 bytes at 7c00h to boot sector menu. however, you should remember that .bin file that is designed to be a boot record should always be written to cylinder: 0, head: 0, sector: 1
to write .bin files to real floppy disk use writebin.asm, just compile it to com file and run it from command prompt. to write a boot record type: writebin loader.bin ; to write kernel module type: writebin kernel.bin /k /k parameter tells the program to write the file at sector 2 instead of sector 1. it does not matter in what order you write the files onto floppy drive, but it does matter where you write them. note: the latest version of emu8086 allows to open command prompt directly in build folder, just click external -> command prompt menu. Note: this boot record is not MS-DOS/Windows compatible boot sector, its not even Linux or Unix compatible, operating system may not allow you to read or write files
on this diskette until you re-format it, therefore make sure the diskette you use doesnt contain any important information. however you can write and read anything to and from this disk using low level disk access interrupts, its even possible to protect valuable information from the others this way; even if someone gets the disk he will probably think that its empty and will reformat it because its the default option in windows operating system such a good type of self destructing data carrier Idealized floppy drive and diskette structure:
for a 1440 kb diskette: * floppy disk has 2 sides, and there are 2 heads; one for each side (0..1), the drive heads move above the surface of the disk on each side. * each side has 80 cylinders (numbered 0..79). * each cylinder has 18 sectors (1..18). * each sector has 512 bytes. * total size of floppy disk is: 2 x 80 x 18 x 512 = 1,474,560 bytes. note: the MS-DOS (windows) formatted floppy disk has slightly less free space on it (by about 16,896 bytes) because the operating system needs place to store file names
and directory structure (often called FAT or file system allocation table). more file names less disk space. the most efficient way to store files is to write them directly to sectors instead of using file system, and in some cases it is also the most reliable way, if you know how to use it. to read sectors from floppy drive use INT 13h / AH = 02h.
Definition of procedure A procedure is a collection of instructions to which we can direct the flow of our program, and once the execution of these instructions is over control is given back to the next line to process of the code which called on the procedure. Procedures help us to create legible and easy to modify programs. At the time of invoking a procedure the address of the next instruction of the program is kept on the stack so that, once the flow of the program has been transferred and the procedure is done, one can return to the next line of the original program, the one which called the procedure. First you have to use DEFINE_ macro somewhere in your program if you want to use these functions:
; ; ; ; ; ; ; CALL CALL CALL CALL CALL CALL CALL SCAN_NUM PRINT_STRING PTHIS GET_STRING CLEAR_SCREEN PRINT_NUM PRINT_NUM_UNS
You can define all these procedures in your source code, but compilation time may slow down sufficiently because of that, only declare functions that you plan to use:
DEFINE_SCAN_NUM DEFINE_PRINT_STRING DEFINE_PTHIS DEFINE_GET_STRING DEFINE_CLEAR_SCREEN DEFINE_PRINT_NUM DEFINE_PRINT_NUM_UNS
The above declarations should be made in your code once only! Better somewhere in the end of your file, but before END directive. You can also declare them in the beginning of the file, but it should be after ORG 100h directive for COM files, or inside the code segment for EXE files.
This is a very basic example of a tiny operating system. This is the kernel module! it is assumed that this machine code is loaded by microos_loader.asm from floppy drive from: cylinder: 0, sector: 2, head: 0
; ; ; ; ; ; ; ; ; ; ; name "kernel" this is a very basic example of a tiny operating system. this is kernel module! it is assumed that this machine code is loaded by micro-os_loader.asm from floppy drive from: cylinder: 0 sector: 2 head: 0
;================================================= ; how to test micro-operating system: ; ; ; ; ; ; ; 1. compile micro-os_loader.asm 2. compile micro-os_kernel.asm 3. compile writebin.asm 4. insert empty floppy disk to drive a: 5. from command prompt type: writebin loader.bin writebin kernel.bin /k
;================================================= ; directive to create bin file: #make_bin# ; where to load? (for emulator. all these values are saved into .binf file)
#load_segment=0800# #load_offset=0000# ; these values are set to registers on load, actually only ds, es, cs, ip, ss, sp are ; important. these values are used for the emulator to emulate real microprocessor state ; after micro-os_loader transfers control to this kernel (as expected). #al=0b# #ah=00# #bh=00# #bl=00# #ch=00# #cl=02# #dh=00# #dl=00# #ds=0800# #es=0800# #si=7c02# #di=0000# #bp=0000# #cs=0800# #ip=0000# #ss=07c0# #sp=03fe# ; this macro prints a char in al and advances ; the current cursor position: putc macro push mov mov int char ax al, char ah, 0eh 10h
pop endm
ax
; sets current cursor position: gotoxy macro push push push mov mov mov mov int pop pop pop endm print macro x, y, attrib, sdat LOCAL s_dcl, skip_dcl, s_dcl_end col, row ax bx dx ah, 02h dh, row dl, col bh, 0 10h dx bx ax
pusha mov dx, cs mov es, dx mov ah, 13h mov al, 1 mov bh, 0 mov bl, attrib mov cx, offset s_dcl_end offset s_dcl mov dl, x mov dh, y mov bp, offset s_dcl int 10h popa jmp skip_dcl s_dcl DB sdat
s_dcl_end DB 0 skip_dcl: endm ; kernel is loaded at 0800:0000 by micro -os_loader org 0000h ; skip the data and function delaration section: jmp start ; The first byte of this jump instruction is 0E9h ; It is used by to determine if we had a sucessful launch or not. ; The loader prints out an error message if kernel not found. ; The kernel prints out "F" if it is written to sector 1 instead of sector 2.
;==== data section ===================== ; welcome message: msg db "Welcome to micro-os!", 0 equ 10 ; size of command_buffer
db "help", 0
cexit_tail:
creboot
db "reboot", 0
creboot_tail: help_msg db "Thank you for choosing micro -os!", 0Dh,0Ah db "The short list of su pported commands:", 0Dh,0Ah db "help db "cls print out this list." , 0Dh,0Ah - clear the screen.", 0Dh,0Ah
db "reboot reboot the machine.", 0Dh,0Ah db "quit db "exit same as reboot.", 0Dh,0Ah same as quit.", 0Dh,0Ah
; set default video mode 8025: mov mov int ah, 00h al, 03h 10h
; blinking disabled for compatibility with dos/bios, ; emulator and windows prompt never blink. mov mov int ax, 1003h bx, 0 10h *** ; disable blinking.
; *** the integrity check cmp [0000], 0E9h jz integrity_check_ok integrity_failed: mov al, F
mov int
; reboot mov mov mov jmp ax, 0040h ds, ax w.[0072h], 0000h 0ffffh:0000h
; make eternal loop: jmp eternal_loop ;=========================================== get_command proc near ; set cursor position to bottom ; of the screen: mov ax, 40h
; wait for a command: mov lea call ret get_command endp ;=========================================== process_cmd proc near dx, cmd_size ; buffer size.
;//// check commands here /// ; set es to ds push pop cld ds es ; forward compare.
; compare command buffer with help lea mov si, command_buffer cx, chelp_tail offset chelp ; size of
; compare command buffer with cls lea mov string. lea repe jne jmp not_cls: ; compare command buffer with qu it lea mov si, command_buffer cx, cquit_tail offset cquit ; size of di, ccls cmpsb not_cls cls_command si, command_buffer cx, ccls_tail offset ccls ; size of ['cls',0]
; compare command buffer with exit lea mov si, command_buffer cx, cexit_tail offset cexit ; size of
; compare command buffer with reboot lea mov si, command_buffer cx, creboot_tail offset creboot ; size of
;//////////////////////////// ; if gets here, then command is ; unknown mov call al, 1 scroll_t_area
; set cursor position just ; above prompt line: mov mov mov dec gotoxy lea call lea call mov call jmp ax, 40h es, ax al, es:[84h] al 0, al si, unknown print_string si, command_buffer print_string al, 1 scroll_t_area processed
; +++++ help command ++++++ help_command: ; scroll text area 9 lines up: mov call al, 9 scroll_t_area
; set cursor position 9 lines ; above prompt line: mov mov mov sub gotoxy ax, 40h es, ax al, es:[84h] al, 9 0, al
print 5,2,0011_1111b," please eject any floppy disks " print 5,3,0011_1111b," and press any key to reboot " mov ax, 0 int 16h ; store magic value at 0040h:0072h: ; ; mov mov mov jmp 0000h cold boot. 1234h warm boot. ax, 0040h ds, ax w.[0072h], 0000h ; cold boot. 0ffffh:0000h ; reboot! ; wait for any key.
; ++++++++++++++++++++++++++ processed: ret process_cmd endp ;=========================================== ; scroll all screen except last row ; up by value specified in al scroll_t_area proc near
mov ah, 06h ; scroll up function id. mov bh, 07 mov ch, 0 mov cl, 0 ; attribute for new lines. ; upper row. ; upper col.
mov di, 84h ; rows on screen -1, mov dh, es:[di] ; lower row (byte). dec dh ; dont scroll bottom line.
mov di, 4ah ; columns on screen, mov dl, es:[di] dec dl int 10h ret scroll_t_area endp ; lower col.
;=========================================== ; get characters from keyboard and write a null terminated string ; to buffer at DS:DI, maximum buffer size is in DX. ; enter stops the input. get_string push push push push mov cmp jbe dec zero. ax cx di dx cx, 0 dx, 1 empty_buffer dx ; char counter. ; buffer too small? ; ; reserve space for last proc near
;============================ ; eternal loop to get ; and processes key presses: wait_for_key: mov int cmp jz cmp jne jcxz dec dec putc putc putc jmp ah, 0 16h al, 0Dh exit al, 8 add_to_buffer wait_for_key cx di 8 8 wait_for_key ; backspace. ; clear position. ; backspace again. ; nothing to remove! ; backspace pressed? ; return pressed? ; get pressed key.
wait_for_key
;============================ exit:
; print a null terminated string at current cursor position, ; string address: ds:si print_string proc near push push ax si ; store registers ;
next_char: mov cmp jz inc mov int jmp printed: pop pop ret print_string endp ; clear the screen by scrolling ent ire screen window, ; and set cursor position on top. ; default attribute is set to white on blue. clear_screen proc near si ax ; re-store registers ; al, [si] al, 0 printed si ah, 0eh ; teletype function. 10h next_char
push push push push push mov mov mov mov mov lines. mov mov mov mov mov mov dec int
; store registers ; ; ; ;
ah, 06h ; scroll up function id. al, 0 ; scroll all lines! ; attribute for new
bh, 1001_1111b
ch, 0 cl, 0
di, 84h ; rows on screen -1, dh, [di] ; lower row (byte). di, 4ah ; columns on screen, dl, [di] dl 10h ; lower col.
; set cursor position to top ; of the screen: mov mov mov mov int pop pop pop pop pop ret clear_screen endp bh, 0 dl, 0 dh, 0 ah, 02 10h di cx bx ds ax ; re-store registers ; ; ; ; ; current page. ; col. ; row.
The code in this file is supposed to load the kernel (micro-os_kernel.asm) and to pass control over it. The kernel code should be on floppy at: cylinder: 0, sector: 2, head: 0
name "loader" ; this is a very basic example of a tiny operating system. ; directive to create boot file: #make_boot# ; this is an os loader only! ; ; it can be loaded at the first sector of a floppy disk: ; ; ; cylinder: 0 sector: 1 head: 0
;================================================= ; how to test micro-operating system: ; ; ; ; ; ; ; 1. compile micro-os_loader.asm 2. compile micro-os_kernel.asm 3. compile writebin.asm 4. insert empty floppy disk to drive a: 5. from command prompt type: writebin loader.bin writebin kernel.bin /k
;================================================= ; ; The code in this file is supposed to load ; the kernel (micro-os_kernel.asm) and to pass control over it. ; The kernel code should be on floppy at:
; ; ;
; memory table (hex): ; ; 07c0:0000 | ; 07c0:01ff | ; ; 07c0:0200 | ; 07c0:03ff | ; ; 0800:0000 | ; 0800:1400 | ; ; ; ; | | | | (currently 5 kb, 10 sectors are loaded from floppy) kernel stack (255 words) boot sector (512 bytes)
; ; To test this program in real envirinment write it to floppy ; disk using compiled writebin.asm ; After sucessfully compilation of both files, ; type this from command prompt: writebin loader.bin
; Note: floppy disk boot record will be overwritten. ; until ; ; you reformat it, data on floppy disk may be lost. use empty floppy disks only. the floppy will not be useable under windows/dos
; micro-os_loader.asm file produced by this code should be less or ; equal to 512 bytes, since this is the size of the boot sector.
; boot record is loaded at 0000:7c00 org 7c00h ; initialize the stack: mov mov mov ax, 07c0h ss, ax sp, 03feh ; top of the stack.
; set default video mode 8025: mov mov int ah, 00h al, 03h 10h
;=================================== ; load the kernel at 0800h:0000h ; 10 sectors starting at: ; ; ; cylinder: 0 sector: 2 head: 0
; BIOS passes drive number in dl, ; so its not changed: mov mov mov mov mov ah, 02h ; read function. al, 10 ch, 0 cl, 2 dh, 0 ; sectors to read. ; cylinder. ; sector. ; head.
; es:bx points to receiving ; mov mov mov ; read! int 13h data buffer: bx, 0800h es, bx bx, 0
; store magic value at 0040h:0072h: ; ; mov mov mov jmp 0000h cold boot. 1234h warm boot. ax, 0040h ds, ax w.[0072h], 0000h ; cold boot. 0ffffh:0000h ; reboot!
;===========================================
next_char: mov cmp jz inc mov int jmp printed: pop pop ret print_string endp si ax ; re-store registers ; al, [si] al, 0 printed si ah, 0eh ; teletype function. 10h next_char
err
integrity check failed." , 0Dh,0Ah db "refer to tutorial 11 making your own operating system.", 0Dh,0Ah db "System will reboot now. Press any key" , 0
;======================================
This utility is to be used from the command prompt, it reads a specified file and writes it to floppy drive at cylinder: 0, head: 0, sector: 1 (boot sector).
name "writebin"
; version 0.02 ; assembled by emu8086 must be compatible with major assemblers. ; writebin.com a tiny operating system loader.
; this utility is be used from command prompt, ; it reads a specified file and writes it to floppy drive at ; cylinder: 0, head: 0, sector: 1 (boot sector).
; if there is /k parameter after the file name, then the ; file is written at cylinder: 0, head: 0, sector: 2. ; first sector of a floppy drive is reserved for boot sector. ; second and other sectors can be used to store any kind of data ; and code. kernel module of tiny operating system should be ; written to sector 2. ; this program works with drive A: only. ; for emulator drive A: is c: \emu8086\FLOPPY_0 ; filename must he in 8.3 format, ; maximum 8 chars for the name and 3 chars after the dot. ; warning! if you run this program outside of the emulator ; caution. ; do not play with floppies that contain it may corrupt existing data. use with
jmp st
filename
db 128 dup(0)
buffer_size = handle
dw 0 ; if there is /k
drive db 0 ; drive number (0..3) ; A: =0, B:=1 ; init st: mov ax, cs mov ds, ax mov es, ax call clear_screen ; read cmd parameters cp: xor cx, cx mov cl, [80h] jcxz np ; this instruction is
assembled into OR CX, CX and two JMPs, tutorial 7 tells why. mov si, 82h mov di, offset filename cld rep movsb mov [di-1], 0 ; check for /k parameter: cld xor cx, cx mov cl, [80h]
jmp boot fs: cmp [di-2], jne nsp mov [di-2], 0 nsp:mov [di-1], 0 or [di], 0010_0000b ; to lower case.
lea dx, s0 mov ah, 9 int 21h jmp s0s s0 db 0Dh,0Ah,"[/k] start from sector: 2 " , 0Dh,0Ah, $ s0s: jmp of
boot: lea dx, s3 mov ah, 9 int 21h jmp s3s s3 db 0Dh,0Ah," boot record ", 1 , 0Dh,0Ah, $ s3s: ; open file of: mov ah, 3dh
mov handle, ax
lea dx, m0 mov ah, 9 int 21h jmp m0m m0 db "opened: $" m0m: mov si, offset filename call print_string
; read bytes from file rd: mov ah, 3fh mov bx, handle mov cx, buffer_size mov dx, offset buffer int 21h jc er cmp ax, 0 jz cf ; no bytes left?
; write bytes to disk wr: mov ah, 03h mov al, 1 ; write 1 sector (512 bytes). mov cl, sect mov ch, cyld mov dh, head ; sector (1..18) ; cylinder (0..79) ; head (0..1)
inc counter
; set cursor at 2,5 mov ah, 2 mov dh, 5 mov bh, 0 int 10h
; show current progress: lea dx, s1 mov ah, 9 int 21h jmp s1s s1 db 1Dh,0Ah,"writing: $" s1s: mov ax, counter call print_num_uns
; sectors cylinders heads cmp kernel_flag, 1 jne cf inc sect cmp sect, 18 jbe rd mov sect, 1 inc cyld cmp cyld, 79 jbe rd ; ^ ; ^
; close file cf: mov bx, handle mov ah, 3eh int 21h jc er jmp ex
co: lea dx, e0 mov ah, 9 int 21h jmp e0e e0 db " e0e: jmp ex np: lea dx, e1 mov ah, 9 int 21h jmp e1e e1 db " db "======================================================= =======================" ,0Dh,0Ah db "this program was designed especially to test micro-operating system",0Dh,0Ah db "if you are emulating in emu8086, click file >set command line parameters." ,0Dh,0Ah db "from command prompt type:" , 0Dh,0Ah no parameters",0Dh,0Ah cannot open the file",0Dh,0Ah,$
db " [/k]",0Dh,0Ah, db
writebin [filename]
written to second sector (kernel area)." ,0Dh,0Ah, db "======================================================= =======================" ,0Dh,0Ah,$ e1e: jmp ex
er: lea dx, e2 mov ah, 9 int 21h jmp e2e e2 db " e2e: jmp ex wp: lea dx, e3 mov ah, 9 int 21h jmp e3e e3 db " wrong parameter. only [/k] is supported. i/o error",0Dh,0Ah,$
ex: lea dx, m1 mov ah, 9 int 21h jmp m1m m1 db 0Dh,0Ah," m1m: mov ax, counter call print_num_uns total sectors: $"
lea dx, m2 mov ah, 9 int 21h jmp m2m m2 db 0Dh,0Ah, "thank your for using writebin! emu8086.com 2005 (c) freeware",0Dh,0Ah db " press any key",0Dh,0Ah, $ m2m: ; wait for any key mov ah, 0 int 16h
ret
; exit.
; this macro prints a char in AL and advances ; the current cursor position: PUTC MACRO PUSH MOV MOV INT POP PUTC ENDM char AX AL, char AH, 0Eh 10h AX
; prints out an unsigned value of AX register. ; allowed values from 0 to 65535 print_num_uns push push push push proc ax bx cx dx near
; (result of "/ 10000" is always less or equal to 9). mov bx, 10000 ; 2710h divider.
; ax is zero? cmp jz begin_print: ; check divider (if zero go to end_print): cmp jz bx,0 end_print ax, 0 print_zero
; if ax<bx then result of div will be zero: cmp jb calc: mov mov div (dx=remainder). ; print last digit ; ah is always zero, so its ignored add putc mov skip: ; calculate bx=bx/10 push mov mov div ax dx, 0 ax, bx cs:ten ; ax = dx:ax / 10 al, 30h al ax, dx ; get remainder from last div. ; convert to ascii code. cx, 0 dx, 0 bx ; ax = dx:ax / bx ; set flag. ax, bx skip
(dx=remainder). mov pop jmp print_zero: putc end_print: pop pop pop pop ret ten print_num_uns dw endp 10 ; used as divider. dx cx bx ax 0 bx, ax ax begin_print
; print null terminated string at ds:si print_string proc near push push nxtch: ax si mov cmp jz inc mov int jmp printed: pop pop ret print_string endp clear_screen proc near push ax ; store registers si ax ; re-store registers ; ; store registers ; al, [si] al, 0 printed si ah, 0eh ; teletype function. 10h nxtch
push push push push mov mov mov mov mov mov mov mov mov mov mov dec int
; ; ; ;
ah, 06h ; scroll up function id. al, 0 bh, 07 ch, 0 cl, 0 ; scroll all lines! ; attribute for new lines. ; upper row. ; upper col.
di, 84h ; rows on screen -1, dh, [di] ; lower row (byte). di, 4ah ; columns on screen, dl, [di] dl 10h ; lower col.
; set cursor position to top ; of the screen: mov mov mov mov int pop pop pop pop pop ret clear_screen endp ; some interrupt info: bh, 0 dl, 0 dh, 0 ah, 02 10h di cx bx ds ax ; re-store registers ; ; ; ; ; current page. ; col. ; row.
; ; ; ; INT 21h / AH= 3Dh open existing file. entry: ; AL = access and sharing modes (if unsure set to
zero). ; ; ; ; ; DS:DX -> ASCIZ filename. return: CF clear if successful, AX = file handle. CF set on error AX = error code. Note: file pointer is set to start of file.
; ; ; ; ; ; ; ; INT 21h / AH= 3Fh read from file. entry: BX = file handle. CX = number of bytes to read. DS:DX -> buffer for data. return: CF is clear if successful AX = number of bytes
actually read; 0 if at EOF (end of file) before call. ; ; CF is set on error AX = error code. note: data is read beginning at current file
position, and the file position is updated after ; a successful read the returned AX may be
smaller than the request in CX if a partial read occurred. ; ; ; ; ; ; INT 21h / AH= 3Eh close file. entry: BX = file handle return: CF clear if successful, AX destro yed. CF set on error, AX = error code (06h).
nonzero) ; ; ; ; CL = sector number (1..18). CH = cylinder number (0..79). DH = head number (0..1). DL = drive number (0..3 , for the emulator it depends
on quantity of FLOPPY_ files). ; ; ; ; ; ; ; ES:BX points to data buffer. return: CF set on error. CF clear if successful. AH = status (0 if successful). AL = number of sectors transferred. Note: each sector has 512 bytes.
; ; INT 10h / AH = 02h set cursor position. ; ; ; ; input: DH = row. DL = column. BH = page number (0..7).
; ; ; INT 21h / AH=09h output of a string at DS:DX. string must be terminated by $ character.
Reference : http://wiicode.com/make-your-own-operating-system-with-x86-assemblypart-1/