Exec86.def 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. DEFINITION MODULE Exec86 ;
  2. (* Exec86 -- an in-process 8086 interpreter.
  3. This is what the shell's `R` key runs: the compiled image is copied into
  4. the interpreter's own 64 KB and executed here, with no DOS, no loader and
  5. no emulator outside this program. TP3's `R` does the same thing - it runs
  6. the generated code in place in the same 64 KB - so this is also the shape
  7. the original had.
  8. The reason to want one at all is documented in SUMMARY.md: qemu-system-i386
  9. cannot be an 8086 oracle, because its lowest CPU model is a 486, where the
  10. opcodes that were the `0F 8x' bug are ordinary instructions. An
  11. interpreter written against the 8086's own reference and then required to
  12. agree with qemu byte-for-byte on the same images is a second, independent
  13. execution oracle - and the one that can actually see an 8086-only fault.
  14. The interface is deliberately three calls: zero the machine, poke the
  15. image in, run it. Everything the guest can do outside its own code - the
  16. INT 21h services, where its input comes from, where its output goes - is
  17. inside, because those are part of "running it", not part of setting it up.
  18. The names carry an 86 suffix, which reads as redundant inside Exec86 and
  19. is not. ISO Modula-2 has no import renaming - gm2 -fiso rejects
  20. `FROM M IMPORT x AS y' outright - and an import cannot be scoped to a
  21. procedure either, so every module that imports Exec86 shares one flat
  22. namespace with everything else it imports. Shell needs TextBuf.Clear,
  23. Editor.Run, Exec86.Clear and Exec86.Run at the same time, and the first
  24. two were spoken for by modules that predate this one. This is the module
  25. that moved: Clear86, Poke86, Run86.
  26. NOTE, because Runtime.def records the same trap: this .def is
  27. HAND-MAINTAINED. gm2 resolves `FROM Exec86 IMPORT ...' against it and
  28. checks the implementation against it, but never rewrites it. An interface
  29. change means editing this file by hand in the same commit. Keep changes
  30. ADDITIVE where possible. *)
  31. PROCEDURE Clear86 ;
  32. (* Reset the machine to the state a DOS .COM starts in: all of memory zeroed,
  33. CS = DS = ES = SS = 0, IP = 0100H (where DOS puts a .COM), SP = 0FFFEH
  34. (the top of the segment, where DOS puts the stack), every general register
  35. zero, DF clear, every other flag clear.
  36. Zeroing the general registers is a CHOICE, not a fact about DOS: bootcom.s
  37. leaves them as the BIOS found them. All 31 fixtures are deterministic
  38. under qemu, so no guest of ours reads an undefined initial register - and
  39. this is the first place that would show up if one ever did. Memory below
  40. 0100H is left zero rather than holding bootcom's interrupt vector, because
  41. the interpreter services INT 21h itself and never looks at the vector. *)
  42. PROCEDURE Poke86 (addr, value : CARDINAL) ;
  43. (* Store one byte at flat address `addr' (value is taken modulo 256).
  44. Poking also records how far up memory has been written, and execution
  45. outside that region is a fault: a guest that jumps out of its own loaded
  46. image has gone somewhere it cannot come back from, and running on into
  47. whatever happens to be there is how a wild jump turns into a wild hang. *)
  48. PROCEDURE Run86 (VAR exitCode : CARDINAL; VAR steps : LONGCARD) : CARDINAL ;
  49. (* Execute until something stops it. Returns
  50. 0 the program terminated with INT 21h AH=4Ch, and exitCode is its AL
  51. 1 the interpreter faulted - a diagnostic is already on stderr
  52. 2 the step limit was reached; steps says how many
  53. `steps' is always the number of instructions actually executed.
  54. The step limit is a runaway guard, and it is a limit rather than a
  55. solution: a program that idles in a tight loop will reach it. It exists
  56. so that a broken image fails instead of never returning. *)
  57. END Exec86.