Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

load-run-code.md 4.0KB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. # Load code in RAM and run it
  2. Collapse OS likely runs from ROM code. If you need to fiddle with your machine
  3. more deeply, you will want to send arbitrary code to it and run it. You can do
  4. so with the shell's `poke` and `call` commands.
  5. For example, let's say that you want to run this simple code that you have
  6. sitting on your "modern" machine and want to execute on your running Collapse OS
  7. machine:
  8. ld a, (0xa100)
  9. inc a
  10. ld (0xa100), a
  11. ret
  12. (we must always return at the end of code that we call with `call`). This will
  13. increase a number at memory address `0xa100`. First, compile it:
  14. zasm < tosend.asm > tosend.bin
  15. Now, we'll send that code to address `0xa000`:
  16. > mptr a000
  17. A000
  18. > poke 8 (resulting binary is 8 bytes long)
  19. Now, at this point, it's a bit delicate. To pipe your binary to your serial
  20. connection, you have to close `screen` with CTRL+A then `:quit` to free your
  21. tty device. Then, you can run:
  22. cat tosend.bin > /dev/ttyUSB0 (or whatever is your device)
  23. You can then re-open your connection with screen. You'll have a blank screen,
  24. but if the number of characters sent corresponds to what you gave `poke`, then
  25. Collapse OS will be waiting for a new command. Go ahead, verify that the
  26. transfer was successful with:
  27. peek 8
  28. 3A00A13C3200A1C9
  29. Good! Now, we can try to run it. Before we run it, let's peek at the value at
  30. `0xa100` (being RAM, it's random):
  31. > mptr a100
  32. A100
  33. > peek
  34. 61
  35. So, we'll expect this to become `62` after we run the code. Let's go:
  36. > mptr a000
  37. A000
  38. > call 00 0000
  39. > mptr a100
  40. A100
  41. > peek
  42. 62
  43. Success!
  44. ## The upload.py tool
  45. The serial connection is not always 100% reliable and a bad byte can slip in
  46. when you push your code and that's not fun when you try to debug your code (is
  47. this bad behavior caused by my logic or by a bad serial upload?). Moreover,
  48. sending contents bigger than `0xff` bytes can be a hassle.
  49. To this end, there is a `upload.py` file in `tools/` that takes care of loading
  50. the file and verify the contents. So, instead of doing `mptr a000` followed by
  51. `poke 8` followed by your `cat` above, you would have done:
  52. ./upload.py /dev/ttyUSB0 a000 tosend.bin
  53. This emits `mptr`, `poke` and `peek` commands and fail appropriately if the
  54. `peek` doesn't match sent contents. If the file is larger than `0xff` bytes,
  55. repeat the process until the whole file was sent (file must fit in memory space
  56. though, of course). Very handy.
  57. ## Labels in RAM code
  58. If your code contains any label, make sure that you add a `.org` directive at
  59. the beginning of your code with the address you're planning on uploading your
  60. code to. Otherwise, those labels are going to point to wrong addresses.
  61. ## Calling ROM code
  62. The ROM you run Collapse OS on already has quite a bit of code in it, some of
  63. it could be useful to programs you run from RAM.
  64. If you know exactly where a routine lives in the ROM, you can `call` the address
  65. directly, no problem. However, getting this information is tedious work and is
  66. likely to change whenever you change the kernel code.
  67. A good approach is to define yourself a jump table that you put in your glue
  68. code. A good place for this is in the `0x03` to `0x37` range, which is empty
  69. anyways (unless you set yourself up with some `rst` jumps) and is needed to
  70. have a proper interrupt hook at `0x38`. For example, your glue code could look
  71. like (important fact: `jp <addr>` uses 3 bytes):
  72. jp init
  73. ; JUMP TABLE
  74. jp printstr
  75. jp aciaPutC
  76. .fill 0x38-$
  77. jp aciaInt
  78. init:
  79. [...]
  80. It then becomes easy to build yourself a predictable and stable jump header,
  81. something you could call `jumptable.inc`:
  82. .equ JUMP_PRINTSTR 0x03
  83. .equ JUMP_ACIAPUTC 0x06
  84. You can then include that file in your "user" code, like this:
  85. #include "jumptable.inc"
  86. .org 0xa000
  87. ld hl, label
  88. call JUMP_PRINTSTR
  89. ret
  90. label: .db "Hello World!", 0
  91. If you load that code at `0xa000` and call it, it will print "Hello World!" by
  92. using the `printstr` routine from `core.asm`.