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 3.9KB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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 `usr` 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 `usr`). 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. > m=0xa000
  17. > while m<0xa008 getc:poke m a:m=m+1
  18. (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 0a000
  28. > puth a
  29. 3A
  30. > peek 0a007
  31. > puth a
  32. C9
  33. Good! Now, we can try to run it. Before we run it, let's peek at the value at
  34. `0xa100` (being RAM, it's random):
  35. > peek 0xa100
  36. > puth a
  37. 61
  38. So, we'll expect this to become `62` after we run the code. Let's go:
  39. > usr 0xa100
  40. > peek 0xa100
  41. > puth a
  42. 62
  43. Success!
  44. ## The upload 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 manually can be a hassle.
  49. To this end, there is a `upload` file in `tools/` (run `make` to build it) that
  50. takes care of loading the file and verify the contents. So, instead of doing
  51. `getc` followed by `poke` followed by your `cat` above, you would have done:
  52. ./upload /dev/ttyUSB0 a000 tosend.bin
  53. This clears your basic listing and then types in a basic algorithm to receive
  54. and echo and pre-defined number of bytes. The `upload` tool then sends and read
  55. each byte, verifying that they're the same. Very handy.
  56. ## Labels in RAM code
  57. If your code contains any label, make sure that you add a `.org` directive at
  58. the beginning of your code with the address you're planning on uploading your
  59. code to. Otherwise, those labels are going to point to wrong addresses.
  60. ## Calling ROM code
  61. The ROM you run Collapse OS on already has quite a bit of code in it, some of
  62. it could be useful to programs you run from RAM.
  63. If you know exactly where a routine lives in the ROM, you can `call` the address
  64. directly, no problem. However, getting this information is tedious work and is
  65. likely to change whenever you change the kernel code.
  66. A good approach is to define yourself a jump table that you put in your glue
  67. code. A good place for this is in the `0x03` to `0x37` range, which is empty
  68. anyways (unless you set yourself up with some `rst` jumps) and is needed to
  69. have a proper interrupt hook at `0x38`. For example, your glue code could look
  70. like (important fact: `jp <addr>` uses 3 bytes):
  71. jp init
  72. ; JUMP TABLE
  73. jp printstr
  74. jp aciaPutC
  75. .fill 0x38-$
  76. jp aciaInt
  77. init:
  78. [...]
  79. It then becomes easy to build yourself a predictable and stable jump header,
  80. something you could call `jumptable.inc`:
  81. .equ JUMP_PRINTSTR 0x03
  82. .equ JUMP_ACIAPUTC 0x06
  83. You can then include that file in your "user" code, like this:
  84. #include "jumptable.inc"
  85. .org 0xa000
  86. ld hl, label
  87. call JUMP_PRINTSTR
  88. ret
  89. label: .db "Hello World!", 0
  90. If you load that code at `0xa000` and call it, it will print "Hello World!" by
  91. using the `printstr` routine from `core.asm`.