-
-
Save Trinitek/7d305d66b15ba90d427e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; | |
; 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