The code that accompanies the LessCursedVM blog post.
import signal
import sys
import threading
from cursed_vm import Asm, CursedVm
def main():
# Build the guest program
asm = Asm()
asm.push_string("Hello, World!\n")
asm.mov_rsi_rsp()
asm.print_loop(port=0x10)
# Handle Ctrl+C
stop = threading.Event()
signal.signal(signal.SIGINT, lambda *_: stop.set())
# Run the VM on a background thread
def vm_thread():
with CursedVm() as vm:
vm.load(asm.code())
vm.run(lambda port, data: (
sys.stdout.write(chr(data[0])) or sys.stdout.flush()
if port == 0x10 and len(data) == 1
else None
))
t = threading.Thread(target=vm_thread, daemon=True)
t.start()
stop.wait()
print("\nBye.")
if __name__ == "__main__":
main()