0% found this document useful (0 votes)
114 views

Operating Systems

This document provides information about creating a simple operating system using assembly language and the emu8086 emulator. It discusses loading code into memory locations using a boot loader program and then transferring control to a kernel module that can perform basic functions like printing text. Code examples are provided for a boot loader that loads from a floppy disk and a very basic kernel that initializes registers and includes macros for printing characters.

Uploaded by

Tahsin Preacher
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
114 views

Operating Systems

This document provides information about creating a simple operating system using assembly language and the emu8086 emulator. It discusses loading code into memory locations using a boot loader program and then transferring control to a kernel module that can perform basic functions like printing text. Code examples are provided for a boot loader that loads from a floppy disk and a very basic kernel that initializes registers and includes macros for printing characters.

Uploaded by

Tahsin Preacher
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 38

Operating System with Assembly language

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.

MOV MOV MOV JMP

AX, 0040h DS, AX w.[0072h], 0000h ; cold boot. 0FFFFh:0000h ; reboot!

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

Boot Sector Location:

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

cmd_size command_buffer clean_str prompt ; commands: chelp

db cmd_size dup("b") db cmd_size dup(" "), 0 db ">", 0

db "help", 0

chelp_tail: ccls db "cls", 0

ccls_tail: cquit db "quit", 0

cquit_tail: cexit db "exit", 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

db "more to come!", 0Dh,0Ah, 0 unknown db "unknown command: " , 0

;====================================== start: ; set data segment: push pop cs ds

; 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

ah, 0eh 10h

; wait for any key mov int ax, 0 16h

; reboot mov mov mov jmp ax, 0040h ds, ax w.[0072h], 0000h 0ffffh:0000h

integrity_check_ok: nop ; *** ok ***

; clear screen: call clear_screen

; print out the message: lea call si, msg print_string

eternal_loop: call call get_command process_cmd

; make eternal loop: jmp eternal_loop ;=========================================== get_command proc near ; set cursor position to bottom ; of the screen: mov ax, 40h

mov mov gotoxy

es, ax al, es:[84h] 0, al

; clear command line: lea call gotoxy si, clean_str print_string 0, al

; show prompt: lea call si, prompt print_string

; wait for a command: mov lea call ret get_command endp ;=========================================== process_cmd proc near dx, cmd_size ; buffer size.

di, command_buffer get_string

;//// 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

['help',0] string. lea repe je di, chelp cmpsb help_command

; 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]

['quit',0] string. lea repe je di, cquit cmpsb reboot_command

; compare command buffer with exit lea mov si, command_buffer cx, cexit_tail offset cexit ; size of

['exit',0] string. lea repe je di, cexit cmpsb reboot_command

; compare command buffer with reboot lea mov si, command_buffer cx, creboot_tail offset creboot ; size of

['reboot',0] string. lea repe je di, creboot cmpsb reboot_command

; ignore empty lines cmp jz command_buffer, 0 processed

;//////////////////////////// ; 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

lea call mov call jmp

si, help_msg print_string al, 1 scroll_t_area processed

; +++++ cls command ++++++ cls_command: call jmp clear_screen processed

; +++ quit, exit, reboot +++ reboot_command: call clear_screen

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 dx, 40h mov es, dx ; for getting screen parameters.

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.

add_to_buffer: cmp jae cx, dx wait_for_key ; buffer is full? ; if so wait for

backspace or return mov inc inc [di], al di cx

; print the key: mov int jmp ah, 0eh 10h

wait_for_key

;============================ exit:

; terminate by null: mov [di], 0

empty_buffer: pop pop pop pop ret get_string endp dx di cx ax

; 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

ax ds bx cx di ax, 40h ds, ax

; store registers ; ; ; ;

; for getting screen parameters.

ah, 06h ; scroll up function id. al, 0 ; scroll all lines! ; attribute for new

bh, 1001_1111b

ch, 0 cl, 0

; 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 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:

; ; ;

cylinder: 0 sector: 2 head: 0

; 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 data segment: xor mov ax, ax ds, ax

; set default video mode 8025: mov mov int ah, 00h al, 03h 10h

; print welcome message: lea call si, msg print_string

;=================================== ; 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.

; dl not changed! drive number.

; es:bx points to receiving ; mov mov mov ; read! int 13h data buffer: bx, 0800h es, bx bx, 0

;=================================== ; integrity check: cmp es:[0000],0E9h ; first byte of kernel must be

0E9 (jmp). je integrity_check_ok

; integrity check error lea call si, err print_string

; wait for any key mov int ah, 0 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!

;=================================== integrity_check_ok: ; pass control to kernel: jmp 0800h:0000h

;===========================================

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 si ax ; re-store registers ; al, [si] al, 0 printed si ah, 0eh ; teletype function. 10h next_char

;==== data section ===================== msg db "Loading",0Dh,0Ah, 0

err

db "invalid data at sector: 2, cylinder: 0, head: 0

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.

; writebin [filename] [/k ]

; 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

valuable data. org 100h

jmp st

filename

db 128 dup(0)

; full path up to 128

chars can be specified. buffer db 512 dup (0) $ offset buffer

buffer_size = handle

dw 0 ; if there is /k

kernel_flag db 0 parameter, kernel_flag=1. counter dw 0 sect cyld head

db 1 ; sector number (1..18). db 0 ; cylinder number (0..79). db 0 ; head number (0..1).

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]

mov di, offset filename mov al, / repne scasb jz fs

jmp boot fs: cmp [di-2], jne nsp mov [di-2], 0 nsp:mov [di-1], 0 or [di], 0010_0000b ; to lower case.

cmp [di], k jne wp or kernel_flag, 1 mov sect, 2 ; start write at sector 2.

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 al, 0 mov dx, offset filename int 21h jc co

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)

mov dl, drive ; always 0 (A:)

mov bx, offset buffer int 13h jc er

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 ; ^ ; ^

mov cyld, 0 inc head cmp head, 1 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]

"when /k parameter is specified file is

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,$

use 8.3 short file names only." ,0Dh,0Ah,$ e3e:

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

; flag to prevent printing zeros before number: mov cx, 1

; (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

; avoid printing zeros before number: cmp je cx, 0 calc

; 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

ds bx cx di ax, 40h ds, ax

; ; ; ;

; for getting screen parameters.

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).

; ; ; INT 13h / AH = 03h write disk sectors. input:

AL = number of sectors to read/write (must be

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/

You might also like