Skip to content

Instantly share code, notes, and snippets.

@Trinitek
Created June 16, 2015 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Trinitek/7d305d66b15ba90d427e to your computer and use it in GitHub Desktop.
Save Trinitek/7d305d66b15ba90d427e to your computer and use it in GitHub Desktop.
;
; FILE: myos.asm
; AUTHOR: nkeck72 (board.flatassembler.net)
; EDITOR: Trinitek (board.flatassembler.net)
; DATE: 15 June 2015
;
; COMMENTS FROM EDITOR:
;
; I made a lot of changes to this file in my effort to get this thing to work in DOSbox. The
; original code and final build process did not like DOSbox at all. I found out that the boot
; media has to have a filesize of any common floppy disk image. Instead of concatenating the
; int21.bin file to the end of myos.bin and booting that, I needed to fill up the trailing
; space with 0's to expand the image size to 1474560 bytes, the same size as that of a 1.44 MB
; floppy. I modified the build process as follows:
;
; > fasm myos.asm
; > fasm int21.asm
; > fasm floppy.asm floppy.ima
; > dosbox -c "boot floppy.ima"
;
; The file contents of floppy.asm is as follows:
;
; file 'myos.bin'
; file 'int21.bin'
; times 1474560-($-$$) db 0
;
use16
org 7C00h
; Setup stack, segment regs
mov ax, 9ch
mov ss, ax
mov sp, 4096d
; There's some data at the bottom of the file that is modified/read from.
; Since we're loaded at 0000:7C00, we want our data segment to be the same as our code segment.
mov ax, cs ;mov ax, 7c0h
mov ds, ax
; Save the boot drive number
mov byte [bootDrive], dl ; The boot drive is not guaranteed to be 0 !!
;mov ah, 02h
;mov dx, 0000h
;int 10h
;
; Eh, why not just re-set the video mode?
mov ax, 0x0003
int 0x10
;----------------------------------------
loadup:
; Reset the floppy drive
mov ah, 00h
mov dl, byte [bootDrive] ;mov dl, 00h
int 13h
;mov ah, 01h
;mov dl, 00h ; Remember! Boot drive isn't guaranteed to be 0 !
;int 13h
;cmp al, 00h ; What!? You didn't change it to AH like I said!
;jne stop
;
; Check for a successful reset
;
; No need to use INT 0x13 function AH=0x01 because AH already
; contains the status of the operation (if you want to use that),
; and the carry flag is always set if there is an error (AH != 0),
; which is what I changed it to check here.
mov al, 'A'
jc stop
;; Load the int 21h code (For later implementation)
; Load at 0000:1400
mov ah, 02h ; Read sectors into memory
mov al, 01h ; Sectors to read = 0
mov ch, 00h ; low 8 bits of cylinder number = 0
mov dh, 00h ; head number = 0
mov cl, 01h ; high 2 bits of cylinder number = 0
; starting sector number (bits 0-5) = 1
mov dl, byte [bootDrive] ; drive number = byte [bootDrive]
mov bx, 1400h ; destination segment = 0x1400
mov es, bx
mov bx, 0000h ; destination offset = 0x0000
int 13h
;mov ah, 01h
;mov dl, 00h
;int 13h
;cmp al, 00h ; Again, errorcode is in AH, not AL! Read your documentation!
;jne stop
;
; Check for a successful read
mov al, 'B'
jc stop
;; Set up the IVT to recognize my int 21h
cli
mov ax, 0000h
mov es, ax
; You could just hardcode the offset to the IVT, like...
; mov bx, 0x21*4
; ...instead of making the processor calculate it at runtime.
mov al, 21h
mov bl, 04h
mul bl
add ax, 02h
mov bx, ax
; Program the 0x21 offset
mov dx, 1400h
mov [es:bx], dx
; Program the 0x21 segment
;mov al, 21h
;mov bl, 04h
;mul bl
;mov bx, ax
sub bx, 2 ; Why recalc the IVT offset? Just offset back 2 bytes.
mov dx, 0000h
mov [es:bx], dx
sti
;; Clear the screen
;mov ah, 02h
;mov dh, 00h
;mov dl, 00h
;int 10h
;mov ah, 07h
;mov al, 00h
;mov ch, 00h
;mov cl, 00h
;mov dh, 80d
;mov dl, 25d
;int 10h
;mov cx, 01h
; Just re-set the video mode if you want to clear the screen.
mov ax, 0x0003
int 0x10
;; Display 'NOS 1.0' message
;mov ah, 09h
;mov al, 4Eh
;int 10h
;mov ah, 02h
;inc dl
;int 10h
;mov ah, 09h
;mov al, 4Fh
;int 10h
;mov ah, 02h
;inc dl
;int 10h
;mov ah, 09h
;mov ah, 53h
;int 10h
;mov ah, 02h
;inc dl
;mov ah, 09h
;mov al, 20h
;int 10h
;mov ah, 02h
;inc dl
;int 10h
;mov ah, 09h
;mov al, 31h
;int 10h
;mov ah, 02h
;inc dl
;int 10h
;mov ah, 09h
;mov al, 2Eh
;int 10h
;mov ah, 02h
;inc dl
;mov ah, 09h
;mov al, 30h
;int 10h
;mov ah, 02h
;mov dl, 00h
;add dh, 01h
;int 10h
;
; Uh. Ever heard of AH=0x0E ? Teletype output. It increments the cursor
; on each character write, and even accounts for page scrolling and newlines.
;
; Also, I noticed in that block of code above that you took the time to translate
; the ASCII characters for "NOS 1.0" into hexadecimal. Why? Did you not know that you
; can deliberately specify ASCII characters like
; mov al, 'N'
; ?? If that is the case, then why are you trying to write an operating system when
; you're not even fully acquainted with the assembler you're using? That's nuts!
mov si, hello
call printString
;; Begin setting up the environment in which the user will type
; I'm not going to look at this very closely, but you can probably reimplement this
; using AH=0x0E. It'll save you a lot of bytes on the output binary, which is a blessing
; since you're trying to fit this thing inside a single 512-byte sector.
typer:
mov ah, 00h
int 16h
cmp al, 0Dh
je print_enter
cmp al, 08h
je print_back
mov ah, 09h
int 10h
push ax
cmp dl, 80d
je mcdn
pop ax
mov ah, 09h
int 10h
mov ah, 02h
inc dl
int 10h
jmp typer
print_enter:
cmp dh, 25d
je scr_dn
mov ah, 02h
add dh, 01h
mov dl, 00h
int 10h
jmp typer
print_back:
mov ah, 02h
dec dl
int 10h
mov ah, 09h
mov al, 20h
int 10h
jmp typer
scr_dn:
mov ah, 07h
mov al, 01h
int 10h
ret
mcdn:
cmp dh, 25d
je scr_dn
mov ah, 02h
add dh, 01h
mov dl, 00h
int 10h
ret
; SI = pointer to string, null terminated
printString:
push ax ; preserve registers
push si
pushf ; preserve direction flag
cld ; LODSB increments SI
mov ah, 0x0E ; INT 0x10 function 0x0E (teletype)
.nextChar:
lodsb ; load byte from SI, increment SI
cmp al, 0 ; if byte is 0, return
jz .end
int 0x10 ; put character
jmp .nextChar ; get the next character
.end:
popf ; restore direction flag
pop si ; restore registers
pop ax
ret
stop:
; Show error symbol on screen.
; AL is set to the character that is to be displayed before the
; jump here. This allows you to determine where the problem is
; occuring in the code, but it does not communicate the actual
; errorcode.
mov ah, 0x0E
int 0x10
; Halting without disabling interrupts will continue execution
; whenever an interrupt is received from hardware.
; If you want to stop the processor indefinitely, clear interrupts,
; halt, and then, in the event that a non-maskable interrupt (which
; can't be disabled in software) is triggered, jump back to the stop
; label. The only downside to doing this is that you lose the ability
; to use CTRL-ALT-DEL to reboot.
.loopForever:
cli
hlt
jmp .loopForever
;----------------------------------------
hello db "NOS 1.0", 0
bootDrive db ?
times 510-($-$$) db 0
dw 0xAA55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment