From adefdf3e4c42f007d75662d504617f7542590464 Mon Sep 17 00:00:00 2001 From: CrazyEttin <> Date: Sun, 30 May 2021 19:12:19 +0300 Subject: [PATCH] Reorganise and comment the code and rewrite readstr. --- make.sh | 5 ++ src/EttinOS.img | 0 src/boot.asm | 26 +++--- src/byte2hexstr.inc | 32 ++++++++ src/calls.inc | 193 -------------------------------------------- src/cmpstr.inc | 32 ++++++++ src/echo.inc | 19 +++++ src/hello.inc | 11 +++ src/help.inc | 11 +++ src/keycode.inc | 44 ++++++++++ src/os.asm | 108 ++++++++++++++++--------- src/println.inc | 14 ++++ src/printstr.inc | 20 +++++ src/readstr.inc | 177 ++++++++++++++++++++++++++++++++++++++++ 14 files changed, 453 insertions(+), 239 deletions(-) create mode 100644 src/EttinOS.img create mode 100644 src/byte2hexstr.inc delete mode 100644 src/calls.inc create mode 100644 src/cmpstr.inc create mode 100644 src/echo.inc create mode 100644 src/hello.inc create mode 100644 src/help.inc create mode 100644 src/keycode.inc create mode 100644 src/println.inc create mode 100644 src/printstr.inc create mode 100644 src/readstr.inc diff --git a/make.sh b/make.sh index 2a147e4..c2a8c12 100755 --- a/make.sh +++ b/make.sh @@ -1,5 +1,10 @@ #!/bin/bash +if [ ! -d "build" ]; +then + mkdir build +fi + cd src/ nasm boot.asm -f bin -o ../build/boot.bin nasm os.asm -f bin -o ../build/os.bin diff --git a/src/EttinOS.img b/src/EttinOS.img new file mode 100644 index 0000000..e69de29 diff --git a/src/boot.asm b/src/boot.asm index d1d2efe..55e574f 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -1,23 +1,31 @@ [ORG 0x7c00] -mov ax, 0 -mov ds, ax jmp 0:start + start: +;Initialise ds +mov ax, 0x0 +mov ds, ax + +;Set the source +mov dh, 0x0 +mov ch, 0x0 +mov cl, 0x2 +;Set the destination mov ax, 0x1000 mov es, ax mov bx, 0 - +;Set the size mov al, 0x20 -mov dh, 0 -mov ch, 0 -mov cl, 0x2 - +;Load mov ah, 0x2 int 0x13 +;Boot jmp 0x1000:0 +;Padding times 0x1fe-($-$$) db 0 -db 0x55 -db 0xaa + +;Boot signature +dw 0xaa55 diff --git a/src/byte2hexstr.inc b/src/byte2hexstr.inc new file mode 100644 index 0000000..df43b88 --- /dev/null +++ b/src/byte2hexstr.inc @@ -0,0 +1,32 @@ +;Converts a byte in ah to a hex string at di. + +byte2hexstr: + +;Set a key for the hex digits +mov si, .key + +;Set a counter for the two characters of the hex string +mov cx, 0x2 + +.loop: + +;Read the byte +rol ax, 0x4 +mov bx, ax + +;Convert the byte to a hex digit +and bx, 0xf +mov bl, [si + bx] + +;Store the hex digit +mov [di], bl + +;Repeat +inc di +dec cx +jnz .loop + +ret + +.key: +db "0123456789abcdef" diff --git a/src/calls.inc b/src/calls.inc deleted file mode 100644 index 14d4c9e..0000000 --- a/src/calls.inc +++ /dev/null @@ -1,193 +0,0 @@ -printstr: -lodsb -cmp al, 0 -je .done -mov ah, 0xe -int 0x10 -jmp printstr -.done: -ret - -readstr: -mov di, readstr.out -mov cx, 0x80 -mov al, 0 -rep stosb -mov bl, 0 -mov ah, 0x3 -int 0x10 -mov byte [.lastln], dh -mov di, readstr.out -.loop: -mov ah, 0 -int 0x16 -cmp al, 0 -je .loop -cmp al, 0xd -je .return -cmp al, 0x8 -je .backspace -cmp bl, 0x80 -je .loop -cmp al, 0x9 -je .erase -cmp al, 0x20 -je .space -.char: -mov byte [di], 0 -mov ah, 0xe -int 0x10 -stosb -inc bl -jmp .checkln -.erase: -mov al, 0x20 -jmp .char -.space: -cmp byte [di], 0 -je .char -mov al, byte [di] -mov ah, 0xe -int 0x10 -inc di -inc bl -.checkln: -mov ah, 0x3 -int 0x10 -cmp dh, [.lastln] -jle .loop -mov byte [.lastln], dh -jmp .loop -.backspace: -cmp bl, 0 -je .loop -mov ah, 0x3 -int 0x10 -cmp dl, 1 -je .prevln -mov ah, 0xe -int 0x10 -dec di -dec bl -jmp .loop -.prevln: -mov ah, 0x2 -dec dh -mov dl, [cpl] -int 0x10 -dec di -dec bl -jmp .loop -.return: -mov di, readstr.end -.findtrailing: -dec di -cmp byte [di], 0 -je .findtrailing -cmp byte [di], 0x20 -je .deltrailing -jmp .done -.deltrailing: -mov al, 0 -stosb -dec di -jmp .findtrailing -.done: -mov ah, 0x2 -mov dh, [.lastln] -int 0x10 -mov si, newline -call printstr -ret -.lastln: -db 0 -.out: -times 0x80 db 0 -.end: -db 0 - -cmpstr: -mov al, [si] -mov bl, [di] -cmp al, bl -jne .neq -cmp al, 0 -je .eq -inc si -inc di -jmp cmpstr -.neq: -clc -ret -.eq: -stc -ret - -byte2hexstr: -mov di, .out -mov si, .key -mov cx, 0x2 -.loop: -rol ax, 0x4 -mov bx, ax -and bx, 0xf -mov bl, [si + bx] -mov [di], bl -inc di -dec cx -jnz .loop -ret -.key: -db "0123456789abcdef" -.out: -times 3 db 0 - -help: -mov si, .out -call printstr -ret -.out: -db "Input:", 0xd, 0xa, "* Typing a character overwrites the cursor location.", 0xd, 0xa, "* The tab key erases the cursor location.", 0xd, 0xa, "* The space and backspace keys move the cursor.", 0xd, 0xa, "Commands:", 0xd, 0xa, "* help: you are reading it.", 0xd, 0xa, "* hello: a hello world program.", 0xd, 0xa, "* echo: echoes its input.", 0xd, 0xa, "* keycode: echoes the BIOS code of a key.", 0xd, 0xa, 0 - -hello: -mov si, .out -call printstr -ret -.out: -db "Hello world!", 0xd, 0xa, 0 - -echo: -call readstr -cmp byte [readstr.out], 0 -je .done -mov si, readstr.out -call printstr -mov si, newline -call printstr -.done: -ret - -keycode: -mov ah, 0 -int 0x16 -mov byte [.scan], ah -mov byte [.ascii], al -mov si, .prefix -call printstr -mov ah, [.scan] -call byte2hexstr -mov si, byte2hexstr.out -call printstr -mov ah, [.ascii] -call byte2hexstr -mov si, byte2hexstr.out -call printstr -mov si, newline -call printstr -ret -.prefix: -db "0x", 0 -.scan: -db 0 -.ascii: -db 0 diff --git a/src/cmpstr.inc b/src/cmpstr.inc new file mode 100644 index 0000000..10597b0 --- /dev/null +++ b/src/cmpstr.inc @@ -0,0 +1,32 @@ +;Compares strings from si and di and sets the carry flag if they are equal and clears it if not. + +cmpstr: + +;Load characters +mov al, [si] +mov bl, [di] + +;Compare the characters +cmp al, bl + +;Check for difference +jne .neq + +;Check for the string end +cmp al, 0x0 +je .eq + +;Repeat +inc si +inc di +jmp cmpstr + +.neq: +;Clear the carry flag +clc +ret + +.eq: +;Set the carry flag +stc +ret \ No newline at end of file diff --git a/src/echo.inc b/src/echo.inc new file mode 100644 index 0000000..ed855aa --- /dev/null +++ b/src/echo.inc @@ -0,0 +1,19 @@ +;Reads a string to the buffer and prints it. + +echo: + +;Read a string +mov di, buffer +mov al, 0xff +call readstr + +;Check for an empty string +cmp byte [buffer], 0x0 +je .done + +;Print the string +mov si, buffer +call println + +.done: +ret \ No newline at end of file diff --git a/src/hello.inc b/src/hello.inc new file mode 100644 index 0000000..1dc1afc --- /dev/null +++ b/src/hello.inc @@ -0,0 +1,11 @@ +;Prints a hello world. + +hello: + +mov si, .hello +call println + +ret + +.hello: +db "Hello world!", 0x0 \ No newline at end of file diff --git a/src/help.inc b/src/help.inc new file mode 100644 index 0000000..de4a565 --- /dev/null +++ b/src/help.inc @@ -0,0 +1,11 @@ +;Prints help. + +help: + +mov si, .help +call println + +ret + +.help: +db "Input:", 0xd, 0xa, "* Typing a character overwrites the cursor location.", 0xd, 0xa, "* The erase (=tab) key erases the cursor location.", 0xd, 0xa, "* The space and backspace keys move the cursor.", 0xd, 0xa, "Commands:", 0xd, 0xa, "* echo: echoes its input.", 0xd, 0xa, "* hello: a hello world program.", 0xd, 0xa, "* help: you are reading it.", 0xd, 0xa, "* keycode: echoes the BIOS code of a key.", 0x0 \ No newline at end of file diff --git a/src/keycode.inc b/src/keycode.inc new file mode 100644 index 0000000..e73fa81 --- /dev/null +++ b/src/keycode.inc @@ -0,0 +1,44 @@ +;Reads a keypress and prints its keycode. + +keycode: + +;Read a keypress +mov ah, 0x0 +int 0x16 + +;Store the keycode +mov [.scan], ah +mov [.ascii], al + +;Print the prefix +mov si, .prefix +call printstr + +;Convert the scancode to a hex string +mov ah, [.scan] +mov di, .keycode +call byte2hexstr + +;Convert the ascii value to a hex string +mov ah, [.ascii] +mov di, .keycode +add di, 0x2 +call byte2hexstr + +;Print the keycode +mov si, .keycode +call println + +ret + +.prefix: +db "0x", 0x0 + +.scan: +db 0x0 + +.ascii: +db 0x0 + +.keycode: +times 0x5 db 0x0 diff --git a/src/os.asm b/src/os.asm index c42cf16..32ceb13 100644 --- a/src/os.asm +++ b/src/os.asm @@ -1,79 +1,113 @@ jmp start -%include "calls.inc" +;Calls +%include "printstr.inc" +%include "println.inc" +%include "readstr.inc" ;Under construction +%include "cmpstr.inc" +%include "byte2hexstr.inc" + +;Commands +%include "echo.inc" +%include "hello.inc" +%include "help.inc" +%include "keycode.inc" start: +;Initialise ds mov ax, 0x1000 mov ds, ax +;Get the terminal width mov ah, 0xf int 0x10 -mov byte [cpl], ah +mov [cpl], ah +;Print a welcome message mov si, welcome -call printstr +call println loop: + +;Print a prompt mov si, prompt call printstr + +;Read a command +mov di, buffer +mov al, 0xff call readstr -cmp byte [readstr.out], 0 -je loop + exec: -.help: -mov si, readstr.out -mov di, cmd.help -call cmpstr -jnc .hello -call help -jmp loop -.hello: -mov si, readstr.out -mov di, cmd.hello -call cmpstr -jnc .echo -call hello -jmp loop +;No command +cmp byte [buffer], 0x0 +je loop .echo: -mov si, readstr.out +;Check for the command +mov si, buffer mov di, cmd.echo call cmpstr -jnc .keycode +jnc .hello +;Execute the command call echo jmp loop +.hello: +;Check for the command +mov si, buffer +mov di, cmd.hello +call cmpstr +jnc .help +;Execute the command +call hello +jmp loop +.help: +;Check for the command +mov si, buffer +mov di, cmd.help +call cmpstr +jnc .keycode +;Execute the command +call help +jmp loop .keycode: -mov si, readstr.out +;Check for the command +mov si, buffer mov di, cmd.keycode call cmpstr jnc .error +;Execute the command call keycode jmp loop .error: -mov si, cmd.error -call printstr +mov si, error +call println jmp loop cpl: -db 0 +db 0x0 welcome: -db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0xd, 0xa, 0 +db 0xd, 0xa, "Welcome to EttinOS!", 0xd, 0xa, 0x0 prompt: -db "> ", 0 +db "> ", 0x0 cmd: -.help: -db "help", 0 -.hello: -db "hello", 0 .echo: -db "echo", 0 +db "echo", 0x0 +.hello: +db "hello", 0x0 +.help: +db "help", 0x0 .keycode: -db "keycode", 0 -.error: -db "Unknown command", 0xd, 0xa, 0 +db "keycode", 0x0 -newline: -db 0xd, 0xa, 0 +error: +db "Unknown command", 0x0 + +;buffer: +;times 0x100 db 0 + +buffer: +times 0x100 db 0 diff --git a/src/println.inc b/src/println.inc new file mode 100644 index 0000000..54e296f --- /dev/null +++ b/src/println.inc @@ -0,0 +1,14 @@ +;Prints a line from si until a null. +println: + +;Print a string +call printstr + +;Print a newline +mov si, .newline +call printstr + +ret + +.newline: +db 0xd, 0xa, 0x0 diff --git a/src/printstr.inc b/src/printstr.inc new file mode 100644 index 0000000..71be922 --- /dev/null +++ b/src/printstr.inc @@ -0,0 +1,20 @@ +;Prints a string from si until a null. + +printstr: + +;Load a character +lodsb + +;Check for the string end +cmp al, 0x0 +je .done + +;Print the character +mov ah, 0xe +int 0x10 + +;Repeat +jmp printstr + +.done: +ret diff --git a/src/readstr.inc b/src/readstr.inc new file mode 100644 index 0000000..61ee4d2 --- /dev/null +++ b/src/readstr.inc @@ -0,0 +1,177 @@ +;Reads a string of at most al characters to di. + +readstr: + +;Store the length +mov [.length], al + +;Initialise the destination with spaces +mov cx, [.length] +mov al, 0x20 +rep stosb +sub di, [.length] + +;Initialise the cursor pointer +mov bl, 0x0 + +;Initialise the last input line pointer +mov ah, 0x3 +int 0x10 +mov byte [.lastln], dh + +.loop: + +;Read a keypress +mov ah, 0x0 +int 0x16 + +;Check for null +cmp al, 0x0 +je .loop + +;Check for return +cmp al, 0xd +je .return + +;Check for backspace +cmp al, 0x8 +je .backspace + +;Check for input end +cmp bl, [.length] +je .loop + +;Check for space +cmp al, 0x20 +je .space + +;Check for erase +cmp al, 0x9 +je .erase + +;Check for non-printing characters +cmp al, 0x1f +jle .loop +cmp al, 0x7f +je .loop + +.char: +;Store the character +stosb +;Print the character +mov ah, 0xe +int 0x10 +;Move the cursor pointer +inc bl + +.checkln: +;Get the cursor position +mov ah, 0x3 +int 0x10 +;Check if the current line is the last one of the input +cmp dh, [.lastln] +jle .loop +;If it is mark it as so +mov byte [.lastln], dh +jmp .loop + +.erase: +;Replace the cursor position with a space +mov al, 0x20 +jmp .char + +.space: +;Get the cursor position +mov ah, 0x3 +int 0x10 +;More from the end of a line to the beginning of the next one +cmp dl, [cpl] +je .nextln +;Move forward within a line +inc dl +mov ah, 0x2 +int 0x10 +inc di +inc bl +jmp .loop + +.nextln: +mov ah, 0x2 +inc dh +mov dl, 0x1 +int 0x10 +inc di +inc bl +;Go to the last input line check +jmp .checkln + +.backspace: +;Check for the input beginning +cmp bl, 0x0 +je .loop +;Get the cursor position +mov ah, 0x3 +int 0x10 +;More from the beginning of a line to the end of the previous one +cmp dl, 0x1 +je .prevln +;Move backward within a line +dec dl +mov ah, 0x2 +int 0x10 +dec di +dec bl +jmp .loop + +.prevln: +mov ah, 0x2 +dec dh +mov dl, [cpl] +int 0x10 +dec di +dec bl +jmp .loop + +.return: + +;Go to the end of the input +mov bh, 0 +sub di, bx +add di, [.length] + +.findtrailing: +;Check for a trailing space +dec di +cmp byte [di], 0x20 +je .deltrailing +jmp .done + +.deltrailing: +;Delete a trailing space +mov al, 0x0 +stosb +dec di +jmp .findtrailing + +.done: +;Move the cursor to the last line of input +mov ah, 0x2 +mov dh, [.lastln] +int 0x10 +;Print a newline +mov si, .newline +call printstr + +ret + +.length: +db 0x0 + +.cursor: +db 0x0 + +.lastln: +db 0x0 + +.newline: +db 0xd, 0xa, 0x0