https://github.com/YJDoc2/8086-Emulator/blob/master/src/lib/...
https://github.com/YJDoc2/8086-Emulator/blob/master/src/lib/...
edit
Here's how to define a 'procedure', which is different from a 'label' and can be called:
def count_up {
INC AX
CALL count_up
}
start:
XOR AX,AX
CALL count_up
Now the 'C'ultists are polluting assembly language with their curly braces! Notice that SP doesn't change while it counts up, the call stack exists only inside the interpreter.I actually had a calculator as a kid that could be programmed in both BASIC and a similar pretend-assembler.
The decision to differentiate procedures from labels was intentional, and taken due to some restrictions of our IR (which is not the best, issue is open to change that).
Also, the way to define procedure is this way (separate form labels), as I felt that might be a bit more familiar to newcomers to assembly, who are coming from other languages.
Call stack exists inside assembler due to the same reason, as in case someone accidentally bashes their stack , it would still not corrupt the whole code. Maybe we should do a better job at reporting this so users can know they have corrupted the stack, instead of silently ignoring.
The SP should be changing, it is probably a bug. Thanks for reporting, I'll try to take a look at it.
Since the code doesn't have an address inside the emulated memory space, it kind of makes sense for there to be a separate return stack. Problem is that you're trying to emulate 8086 and not a Forth machine :)
One solution might be to have 'CALL' decrement SP (perhaps writing some dummy value like 0000 or FFFF to memory), and also remember where SS:SP points now. The interpreter's return stack could store that address, along with the reference to the line of code it should return to.
When executing 'RET', check if the stack pointer is at the same location as it was after the last 'CALL', and halt with an error message if it is different. I suggest you also allow 'JMP' to procedures, or just get rid of the separation entirely and make everything a label. The procedure syntax could still be allowed as an alternative but just declare a normal label.
Another small but impactful bug: REP seems to always perform one more iteration when CX is zero!
Wow. Reading the authors other comments, it sounds like they couldn't find an assembler they liked for their operating system, and instead decided to spend their course building their own instead, as they imagined it would work. Stay away from this tool if your goal is to learn about 8086. This project is an 8086-inspired programming language.
It is clearly a student project, intended to run very simple code and show how the registers and memory are affected. They did read the Intel manual, and most of the instructions seem to be implemented correctly including flag behaviour; for example the SBB AL,0x69 + DAS trick works.
Generating and running actual machine code might well be "out of scope" for something like this.
(segment-register) [bs/bp/si/di , signed word number]; The offset is taken from the registers, and the number is added to it
(segment-register) [bs/bp , si/di , (signed word number) ];It's in the "Memory" part of the instructions page.