A simple exploratory interpreter with REPL experience. (Beginning learning purpose only)
- For windows users, you can download and run the
.exe
file from releases page. - Clone and run this repository,
git clone https://github.com/hemanta212/8085-simulator
python -m pip install loguru rich pyreadline
cd 8085-simulator
python main.py
Type help
and run the commands listed.
For detailed examples on available commands, see file usage_examples.org.
- Features
- REPL Mode
- Command line arguments
- Example Repl Workflow
- Example Command line Workflow
- Using From Terminal, Vim and Emacs
- Extensive Usage Examples
- [x] - Implement Registers and Memory
- [x] - Implement Basic commands (ADD, ADI, SUB, SUI, MOV, MVI, STA, LDA)
- [x] - Implement Xtended Register Pairs (LXI, M, LDAX)
- [x] - Write a ob-8085 for emacs org-mode (babel)
- [x] - Implement Flags (CY, Z, S)
- [x] - Implement labels and jumps (Loops) [Commands: JC, JNC, JZ, JNZ)
- [x] - Implement increment/decrements [INR, DCR]
- [x] - Implement Xtended increment/decrements [INX, DCX]
- [x] - Implement basic commands (CMP/CPI, OUT)
- [x] - Implement comments, empty lines, HLT(no-effect)
- [x] - Release a pyinstaller executable
- [ ] - Implement commands (ANI, ORI, RRC, STAX)
- [ ] - … ( a lot of commands)
- [ ] - Implement proper 8-bit 16-bit type system and validation
- [ ] - Implement a stacktrace in case of errors
- [x] - Implement integration test and actions CI
- [ ] - A pypi package
- [-] - Write a major mode for emacs.
python main.py
Welcome to the 8085 emulator. Type 'help' for a list of commands. >>>
>>> help
MOV - Move data from one register to another MVI - Move to immediate INR - Increment Register DCR - Decrement Register LXI - Load register pair immediate LDA - Load accumulator STA - Store accumulator HLT - Halt ADD - Add SUB - Subtract ADI - Add Immediate SUI - Subtract Immediate CMP - Compare CPI - Compare Immediate ANI - And Immediate with Accumulator ORI - OR Immediate with Accumulator RRC - Rotate Right Accumulator LDAX - Load accumulator from register pair STAX - Store accumulator to register pair INX - Incremented xtended register pairs DCX - Decrement xtended register pairs JZ - Jump If Zero JNZ - Jump If Not Zero JC - Jump If Carry JNC - Jump If Not Carry OUT - Out
Beside repl, the interpreter can be entirely run from command line.
python main.py --help
:8085 Interpreter: help | --help | -h: Display this message -i : Run in indirect mode, dont display welcome msg and >>> prompt -v <d/i/w/e> : Verbosity option use (d,i,w,e) for (DEBUG, INFO, WARNING, ERROR) resp. -db <FILENAME> : Run in file db mode save and restore after each cmd from file -f <FILENAME> : Read command/commands from file -c "cmd1;cmd2" : Run cmd directly, separate with ";" for more than one commands NOTE: In case of using multiple options, they need to be specified in order listed above.
The interpreter provides:
- An option to run in raw plain mode without any welcome message or
>>>
prompt through-i
option. - An option to pass a file (containing commands line by line) to the interpreter to evaluate through
-f
option. - An option to save state after each command to a json file through
-db
option. - An option to run commands in place through
-c
option. - An option to customize the verbosity of logging messages through
-v
option.
NOTE: In case of using multiple options, they need to be specified in order,
-i
,-v
,-db
,-f
,-c
Providing options otherwise will result in an error.
NOTE Fore more extensive examples for each commands, see file usage_examples.org.
>>> inspect
Registers: A: 0x00 B: 0x00 C: 0x00 D: 0x00 E: 0x00 H: 0x00 L: 0x00 M: 0x00 Memory: 0x1000: 0x2b 0x1001: 0x34 0x0000: 0x00 Flags: carry: 0 auxillary_carry: 0 zero: 0 sign: 0
>>> MVI B 05H
B -> 05H
>>> MVI C 05H
C -> 05H
>>> ADD B
A -> 00H + 05H -> 05H
>>> ADD C
A -> 05H + 05H -> 0AH
>>> STA 3322H
3322H -> 0AH
>>> inspect
Registers: A: 0x0a B: 0x05 C: 0x05 D: 0x00 E: 0x00 H: 0x00 L: 0x00 M: 0x00 Memory: 0x1000: 0x2b 0x1001: 0x34 0x0000: 0x00 0x3322: 0x0a Flags: carry: 0 auxillary_carry: 0 zero: 0 sign: 0
echo "MVI B 05H" > test.txt
echo "MVI A 00H" >> test.txt
python main.py -f test.txt
B -> 05H A -> 00H
python main.py -c "MVI B 05H"
B -> 05H
python main.py -c "MVI A 00H; MVI B 05H; ADD B"
A -> 00H B -> 05H A -> 00H + 05H -> 05H
Specifying the file db option saves the state of interpreter to a json file and restores from it every time a 8085 command is executed.
This is useful when trying to run multiple -c
commans as a session.
python main.py -db /tmp/pyassm-readme-02 -c "MVI B 05H"
B -> 05H
python main.py -db /tmp/pyassm-readme-02 -c "MVI A 00H; ADD B"
A -> 00H A -> 00H + 05H -> 05H
python main.py -db /tmp/pyassm-readme-02 -c "STA 5555H; inspect"
5555H -> 05H Registers: A: 0x05 B: 0x05 C: 0x00 D: 0x00 E: 0x00 H: 0x00 L: 0x00 M: 0x00 Memory: 0x1000: 0x2b 0x1001: 0x34 0x0000: 0x00 0x5555: 0x05 Flags: carry: 0 auxillary_carry: 0 zero: 0 sign: 0
This is very useful for piping interactions to and from other applications.
It is also recommended to run in -db
file mode for continuous session-like interaction.
echo "MVI B 05H" | python main.py -i
B -> 05H
echo "MVI B 05H\nADD B" | python main.py -i
B -> 05H A -> 00H + 05H -> 05H
You can customize the verbosity of logging messages by providing,
d
: ForDEBUG
levele
: ForERROR
levelw
: ForWARNING
leveli
: ForINFO
level
echo "MVI B 05H" | python main.py -i -v d
The command line options provided by interpreter allows it to be used through editors like Vim and Emacs. Either you can:
- Use the
-f
option and write and execute using a temp buffer/file. - Use combination of
-c
and-db
option to emulate a repl session. - Use combnation of
-i
and-db
option to emulate a repl session.
With some configuration, the interpreter can be made to work with Emacs’ Org Mode using the org-babel-eval
function.
This uses -i
command option to write to the interpreter.
Put this in your init.el
file,
(defcustom path-to-8085 "~/dev/8085-interpreter/"
"Path to folder where 8085-interpreter was cloned")
(defcustom org-babel-8085-command
(concat
"python"
(concat path-to-8085 "/main.py"))
"Name of the command for executing 8085 interpreter.")
(defun org-babel-execute:8085 (body params)
(let ((args (cdr (assoc :args params))))
(org-babel-eval
(concat
org-babel-8085-command
(if args (concat " -i " args) " -i " ))
body)))
;; Placeholder major mode, look below for more featured major mode
(define-derived-mode 8085-mode prog-mode "8085"
"Major mode for 8085."
(setq-local comment-start ";")
(setq-local comment-start-skip ";+[\t ]*"))
- The
path-to-8085
should be folder where you cloned this project. - The
org-babel-8085-command
should be the command to run the interpreter (eg python main.py),- You could use
(concat path-to-8085 "/.venv/bin/python")
in place of ”python
” if you use in-project virtual environments.
- You could use
(require 'rx)
(defvar 8085-mode-map
(let ((map (make-sparse-keymap)))
map))
(defconst 8085--font-lock-defaults
(let (
(instructions '("MVI" "MOV" "ADD" "SUB" "ADI"
"SUI" "JNZ" "JNC" "JZ" "JC" "LXI"
"LXAD" "INR" "DCR" "INX" "DCX" "OUT"
"HLT" "CPI" "CMP" "STA" "LDA")))
`(((,(rx-to-string `(: (or ,@instructions))) 0 font-lock-keyword-face)
("\\([[:word:]]+\\):" 1 font-lock-function-name-face)))))
(defvar 8085-mode-syntax-table
(let ((st (make-syntax-table)))
;; - and _ are word constituents
(modify-syntax-entry ?_ "w" st)
(modify-syntax-entry ?- "w" st)
;; add comments. lua-mode does something similar, so it shouldn't
;; bee *too* wrong.
(modify-syntax-entry ?\; "<" st)
(modify-syntax-entry ?\n ">" st)
st))
(define-derived-mode 8085-mode prog-mode "8085"
"Major mode for 8085."
(setq font-lock-defaults 8085--font-lock-defaults)
(setq-local comment-start ";")
(setq-local comment-start-skip ";+[\t ]*")
(setq-local case-fold-search nil))
Save and restart your emacs (or execute each block with C-x C-e
).
Then you can use org mode to write block like:
- Use
C-c C-c
to execute a given block.
#+begin_src 8085 :args -v d -db /tmp/8085-session1 MVI B 80H #+end_src
- For session-like use,
#+begin_src 8085 :args -v d -db /tmp/8085-session1 MVI B 80H #+end_src
- For verbose logging,
#+begin_src 8085 :args -v d -db /tmp/8085-session1 MVI B 80H #+end_src