--- /dev/null
+#+SETUPFILE: ~/.emacs.d/org-styles/html/darksun.theme
+#+TITLE: Fifth - virtual machine opcodes 0 -- 9
+#+AUTHOR: Svjatoslav Agejenko
+#+LANGUAGE: en
+
+#+OPTIONS: H:20 num:20
+#+OPTIONS: author:nil
+
+#+begin_export html
+<style>
+ .flex-center {
+ display: flex; /* activate flexbox */
+ justify-content: center; /* horizontally center anything inside */
+ }
+
+ .flex-center video {
+ width: min(90%, 1000px); /* whichever is smaller wins */
+ height: auto; /* preserve aspect ratio */
+ }
+
+ .responsive-img {
+ width: min(100%, 1000px);
+ height: auto;
+ }
+</style>
+#+end_export
+
+
+* 0: nop
+:PROPERTIES:
+:ID: 4f0dee8a-647e-4d91-a252-aaf4782b5edc
+:END:
+
+- *Stack Effect:* =--=
+- *Description:* No operation. The VM simply proceeds to the next
+ instruction without modifying any state. This is a placeholder
+ instruction that has no effect on registers or stacks.
+- *Notes:* Implemented by jumping back to the main instruction fetch
+ loop (=emu= label), effectively doing nothing.
+
+* 1: halt
+:PROPERTIES:
+:ID: 7c8841d3-2335-4ee9-b6b9-518d05354841
+:END:
+- *Stack Effect:* =--=
+- *Description:* Terminates the emulator process. Restores the original
+ text mode, closes the virtual disk file, restores the keyboard driver,
+ and exits to DOS.
+- *Notes:* This is the only way to cleanly exit the emulator. No stack
+ items are consumed.
+
+* 2: kbd@
+:PROPERTIES:
+:ID: 820b1b90-4f4c-4ab1-b49f-9b4a52ea2528
+:END:
+- *Stack Effect:* =-- scancode=
+- *Description:* Reads the next keyboard scan code from the keyboard
+ buffer. Returns 0 if no keys are pressed. Non-blocking operation.
+
+* 3: num
+:PROPERTIES:
+:ID: 8721dc8c-b237-4e9a-a509-0ded1c02329b
+:END:
+- *Stack Effect:* =-- n=
+- *Description:* Pushes a 32-bit immediate value onto the data stack.
+ The value is encoded in the instruction stream immediately after the
+ opcode.
+- *Notes:* The value is loaded from =[es:esi]=, then =esi= is
+ incremented by 4 to skip over the immediate data.
+- *Example:*
+ #+begin_example
+ 42 ; Push 42 onto stack
+ num
+ #+end_example
+
+* 4: jmp
+:PROPERTIES:
+:ID: a5c53b60-ffe9-4ba4-ab87-30c2ccc51a45
+:END:
+- *Stack Effect:* =--=
+- *Description:* Unconditionally jumps to the absolute address specified
+ by the next 32-bit value in the instruction stream.
+- *Notes:* The target address is added to =xms_addr= to convert from
+ virtual to physical memory address before jumping.
+- *Example:*
+ #+begin_example
+ 0x1000 ; Jump target address
+ jmp
+ #+end_example
+
+* 5: call
+:PROPERTIES:
+:ID: 66efbd35-c2b6-4657-ba0f-ff00a3a2c312
+:END:
+- *Stack Effect:* =--=
+- *Description:* Calls a subroutine at the specified address. Saves the
+ return address (current instruction pointer + 4) onto the return stack
+ before jumping.
+- *Notes:* The return address is pushed to the return stack before the
+ jump occurs.
+- *Example:*
+ #+begin_example
+ 0x2000 ; Subroutine address
+ call
+ #+end_example
+
+* 6: 1+
+:PROPERTIES:
+:ID: 76fe1c8f-756d-406e-9e8a-4ecc8f1d7369
+:END:
+- *Stack Effect:* =n -- n+1=
+- *Description:* Increments the top value on the data stack by 1.
+- *Notes:* Directly increments the dword at the data stack pointer.
+- *Example:*
+ #+begin_example
+ 5
+ 1+
+ #+end_example
+ After execution, stack contains 6.
+
+* 7: 1-
+:PROPERTIES:
+:ID: 523f93a3-359e-4a6d-b296-df25008db403
+:END:
+- *Stack Effect:* =n -- n-1=
+- *Description:* Decrements the top value on the data stack by 1.
+- *Notes:* Directly decrements the dword at the data stack pointer.
+- *Example:*
+ #+begin_example
+ 10
+ 1-
+ #+end_example
+ After execution, stack contains 9.
+
+* 8: dup
+:PROPERTIES:
+:ID: 2a6a449a-fc76-421c-a81c-c2024a15fc78
+:END:
+- *Stack Effect:* =n -- n n=
+- *Description:* Duplicates the top value on the data stack.
+- *Notes:* Creates a copy of the top item and pushes it onto the stack.
+- *Example:*
+ #+begin_example
+ 42
+ dup
+ #+end_example
+ After execution, stack contains 42 42.
+
+* 9: drop
+:PROPERTIES:
+:ID: 4600dbeb-1833-4e7d-af7e-f6cc6c98d022
+:END:
+- *Stack Effect:* =n --=
+- *Description:* Removes the top value from the data stack.
+- *Notes:* Simply increments the data stack pointer by 4 bytes.
+- *Example:*
+ #+begin_example
+ 42
+ drop
+ #+end_example
+ After execution, stack is empty.
:PROPERTIES:
:ID: 9b251eb9-aff6-4025-94bf-25e89e26d54a
:END:
-
+#+SETUPFILE: ~/.emacs.d/org-styles/html/darksun.theme
#+TITLE: Fifth - virtual machine
#+AUTHOR: Svjatoslav Agejenko
#+LANGUAGE: en
+#+OPTIONS: H:20 num:20
+#+OPTIONS: author:nil
+
+#+begin_export html
+<style>
+ .flex-center {
+ display: flex; /* activate flexbox */
+ justify-content: center; /* horizontally center anything inside */
+ }
+
+ .flex-center video {
+ width: min(90%, 1000px); /* whichever is smaller wins */
+ height: auto; /* preserve aspect ratio */
+ }
+
+ .responsive-img {
+ width: min(100%, 1000px);
+ height: auto;
+ }
+</style>
+#+end_export
+
+
* Overview
Fifth is a hobby operating system built around a custom stack-based
Graphics operations are performed through dedicated VM instructions.
-* Boot Process**
+* Boot Process
1. DOS loads emulator.com as a COM executable
2. system_init() allocates XMS memory and sets up A20 gate
are now loaded from filesystem files.
10. Enters interactive REPL
-
* Implemented instructions
Virtual CPU opcodes (most of them are available as directly executable commands
| # | Name | Stack effect | Description | Notes |
|----+----------+-----------------------+----------------------------------------------------------+---------------------------------------------------------------------|
| 0 | [[id:4f0dee8a-647e-4d91-a252-aaf4782b5edc][nop]] | -- | No operation | |
-| 1 | [[#halt][halt]] | -- | Halt CPU (exit emulator) | |
+| 1 | [[id:7c8841d3-2335-4ee9-b6b9-518d05354841][halt]] | -- | Halt CPU (exit emulator) | |
| 2 | [[id:820b1b90-4f4c-4ab1-b49f-9b4a52ea2528][kbd@]] | -- scancode | Read scancode of pressed or released key | |
| 3 | [[id:8721dc8c-b237-4e9a-a509-0ded1c02329b][num]] | -- n | Push immediate 32-bit number onto data stack | |
-| 4 | [[#jmp][jmp]] | -- | Unconditional jump to specified address | |
-| 5 | [[#call][call]] | | Call subroutine (save return address on return stack) | |
-| 6 | [[#section][1+]] | n -- n+1 | Increment top of data stack by 1 | |
-| 7 | [[#section-1][1-]] | n -- n-1 | Decrement top of data stack by 1 | |
-| 8 | [[#dup][dup]] | n -- n n | Duplicate top of data stack | |
-| 9 | [[#drop][drop]] | n -- | Drop top of data stack | |
+| 4 | [[id:a5c53b60-ffe9-4ba4-ab87-30c2ccc51a45][jmp]] | -- | Unconditional jump to specified address | |
+| 5 | [[id:66efbd35-c2b6-4657-ba0f-ff00a3a2c312][call]] | | Call subroutine (save return address on return stack) | |
+| 6 | [[id:76fe1c8f-756d-406e-9e8a-4ecc8f1d7369][1+]] | n -- n+1 | Increment top of data stack by 1 | |
+| 7 | [[id:523f93a3-359e-4a6d-b296-df25008db403][1-]] | n -- n-1 | Decrement top of data stack by 1 | |
+| 8 | [[id:2a6a449a-fc76-421c-a81c-c2024a15fc78][dup]] | n -- n n | Duplicate top of data stack | |
+| 9 | [[id:4600dbeb-1833-4e7d-af7e-f6cc6c98d022][drop]] | n -- | Drop top of data stack | |
| 10 | [[#if][if]] | n -- | Jump to address if top of stack is zero | |
| 11 | [[#ret][ret]] | | Return from subroutine (pop return address) | |
| 12 | [[#c][c@]] | addr -- byte | Read byte from memory at specified address | |
| 46 | [[id:77fa76d3-9cd0-49c1-882c-f30383347352][depth]] | -- depth | Push current data stack depth | |
| 47 | [[id:4bb479cf-aae0-4128-9868-f016c286a162][charput]] | fg bg src dest x y -- | Draw character from source buffer to destination buffer | |
-** nop
-:PROPERTIES:
-:ID: 4f0dee8a-647e-4d91-a252-aaf4782b5edc
-:END:
-
-- *Stack Effect:* =--=
-- *Description:* No operation. The VM simply proceeds to the next
- instruction without modifying any state. This is a placeholder
- instruction that has no effect on registers or stacks.
-- *Notes:* Implemented by jumping back to the main instruction fetch
- loop (=emu= label), effectively doing nothing.
-
-** halt
-:PROPERTIES:
-:CUSTOM_ID: halt
-:ID: 7c8841d3-2335-4ee9-b6b9-518d05354841
-:END:
-- *Stack Effect:* =--=
-- *Description:* Terminates the emulator process. Restores the original
- text mode, closes the virtual disk file, restores the keyboard driver,
- and exits to DOS.
-- *Notes:* This is the only way to cleanly exit the emulator. No stack
- items are consumed.
-
-** kbd@ - read scancode of pressed or released key
-:PROPERTIES:
-:ID: 820b1b90-4f4c-4ab1-b49f-9b4a52ea2528
-:END:
-- *Stack Effect:* =-- scancode=
-- *Description:* Reads the next keyboard scan code from the keyboard
- buffer. Returns 0 if no keys are pressed. Non-blocking operation.
-
-** num
-:PROPERTIES:
-:ID: 8721dc8c-b237-4e9a-a509-0ded1c02329b
-:END:
-- *Stack Effect:* =-- n=
-- *Description:* Pushes a 32-bit immediate value onto the data stack.
- The value is encoded in the instruction stream immediately after the
- opcode.
-- *Notes:* The value is loaded from =[es:esi]=, then =esi= is
- incremented by 4 to skip over the immediate data.
-- *Example:*
- #+begin_example
- 42 ; Push 42 onto stack
- num
- #+end_example
-
-** jmp
-:PROPERTIES:
-:CUSTOM_ID: jmp
-:ID: a5c53b60-ffe9-4ba4-ab87-30c2ccc51a45
-:END:
-- *Stack Effect:* =--=
-- *Description:* Unconditionally jumps to the absolute address specified
- by the next 32-bit value in the instruction stream.
-- *Notes:* The target address is added to =xms_addr= to convert from
- virtual to physical memory address before jumping.
-- *Example:*
- #+begin_example
- 0x1000 ; Jump target address
- jmp
- #+end_example
-
-** call
-:PROPERTIES:
-:CUSTOM_ID: call
-:ID: 66efbd35-c2b6-4657-ba0f-ff00a3a2c312
-:END:
-- *Stack Effect:* =--=
-- *Description:* Calls a subroutine at the specified address. Saves the
- return address (current instruction pointer + 4) onto the return stack
- before jumping.
-- *Notes:* The return address is pushed to the return stack before the
- jump occurs.
-- *Example:*
- #+begin_example
- 0x2000 ; Subroutine address
- call
- #+end_example
-
-** 1+
-:PROPERTIES:
-:CUSTOM_ID: section
-:ID: 76fe1c8f-756d-406e-9e8a-4ecc8f1d7369
-:END:
-- *Stack Effect:* =n -- n+1=
-- *Description:* Increments the top value on the data stack by 1.
-- *Notes:* Directly increments the dword at the data stack pointer.
-- *Example:*
- #+begin_example
- 5
- 1+
- #+end_example
- After execution, stack contains 6.
-
-** 1-
-:PROPERTIES:
-:CUSTOM_ID: section-1
-:ID: 523f93a3-359e-4a6d-b296-df25008db403
-:END:
-- *Stack Effect:* =n -- n-1=
-- *Description:* Decrements the top value on the data stack by 1.
-- *Notes:* Directly decrements the dword at the data stack pointer.
-- *Example:*
- #+begin_example
- 10
- 1-
- #+end_example
- After execution, stack contains 9.
-
-** dup
-:PROPERTIES:
-:CUSTOM_ID: dup
-:ID: 2a6a449a-fc76-421c-a81c-c2024a15fc78
-:END:
-- *Stack Effect:* =n -- n n=
-- *Description:* Duplicates the top value on the data stack.
-- *Notes:* Creates a copy of the top item and pushes it onto the stack.
-- *Example:*
- #+begin_example
- 42
- dup
- #+end_example
- After execution, stack contains 42 42.
-
-** drop
-:PROPERTIES:
-:CUSTOM_ID: drop
-:ID: 4600dbeb-1833-4e7d-af7e-f6cc6c98d022
-:END:
-- *Stack Effect:* =n --=
-- *Description:* Removes the top value from the data stack.
-- *Notes:* Simply increments the data stack pointer by 4 bytes.
-- *Example:*
- #+begin_example
- 42
- drop
- #+end_example
- After execution, stack is empty.
-
** if
:PROPERTIES:
:CUSTOM_ID: if