AgonConsole8 / agon-mos

Official AGON QUARK Firmware for Console8: eZ80 MOS
MIT License
25 stars 10 forks source link

Small binaries can be run without any header #67

Open triplefox opened 4 months ago

triplefox commented 4 months ago

While learning my way around ez80asm I started building simple assembly binaries without any header attached, and they worked, but I didn't notice that this wasn't supposed to work. Eventually I made a binary over 64 bytes and then it suddenly failed, and after some diagnosis, reduction to the simplest possible case(a "ret" and 64 null db bytes) and examining other code, I discovered that I needed the header.

My hypothesis for why this works is because the area at &40000 isn't cleared, so anything that ran previously there(like ez80asm) will still have its data. I don't have any specific suggestions for resolution - it might be sufficient to allow the small-binary case to slip through and adjust the "Invalid binary" error message to indicate more details, like a hexdump of the header area.

stevesims commented 4 months ago

yeah - the memory area isn't cleared, and so a previous binary loaded at &40000 which has a correct header will mean that the header check on attempting to execute the binary at that memory address will pass

this is actually a trickier thing to resolve than it might first seem

until very recently MOS didn't actually have the ability to directly run a binary file. the only mechanism was to use load <filename> [address] and then run [address|.] [args]. (alternatively instead of using run you can jmp <address>).

the new facility to run a binary directly essentially just does an automatic load and run

run checks for a suitable header, but as it's essentially a separate command it can't know how large the binary was that was loaded

as I see it there are two potential solutions here

  1. change the functionality in MOS for where automatic "load and run" happens, and have that check for a minimum file size
  2. do nothing - just better document the existing behaviour
triplefox commented 4 months ago

I slept on it overnight and I think the actual behavior doesn't need to be prevented, but the source of surprise - "it worked before, why doesn't it work now" - is worth addressing. It is not about single-command run: separate load and run was what I was using and it surprised me anyway, because it's the header check itself that is the invisible step, and by the time it occurs the context is gone.

Here is a proposal: load becomes two commands: load and require (following a conventional term that often appears in programming languages that can import code at runtime), single-command run now automatically uses require, and then the documentation would be "use run or require/run to load programs, use load for raw binary data". That creates the context needed to generate all kinds of warnings and errors, without hiding anything about what's going on or making load do more.

Edit: "Invalid binary" can become "Invalid binary, for details use REQUIRE" to guide me, a simple-minded load user, towards the correct process.