02/03/10: Dangerous loading by remz, | Tags: | Category: General, Programming | 5 comments - (Comments are closed)

Dangerous loading

Hello guys
I had a dangerous bug yesterday while coding my music synth. I would like to know what is a safe way to load a program without risking this:
I have set my code and data to start at org $4000, and reaching up to address $8000.
The problem I encountered seems to be related to the fact that the CoCo BASIC stack pointer starts at $8000 so it hangs in the range of $7FD0 or something like that when a program is loaded from LOADM”HELLO. What happens is that before your program can even start (and thus set the stack to somewhere safe like $F000 and put to Coco in all-RAM mode), a little bit of data will get corrupted near the initial stack pointer. Maybe its the disk loading routine itself? I don’t know.

But what happened to me was having corrupted data which in turned led to a complete crash with an invalid opcode. Even worse the bug is somewhat random since the stack or corruption is not exactly the same each time I booted it up. Very annoying bug, since even MESS Debugger can’t help because when it ‘crashes’ on an illegal opcode, it simply stops working and doesn’t tell you anything about it. Arggh.

This post was submitted by remz.

5 comments to Dangerous loading

  • linville

    I’ve been loading my code at $0E00 — I remember doing some math to determine that as a decent place, beyond the normal coco text screen and the disk buffers, but I can’t recall the exact calculations. If you are desperate to know them, I might can find the info.

    Also, I would guess that this load address is a poor choice for compatibility with BASIC, so if your application has a BASIC component then YMMV. Of course in that case I think you are supposed to use the CLEAR command…? Can’t quite remember — I’ll be Robert Gault or someone else can explain that idiom. :-)

  • DarrenA

    Before loading your program you need to:
    CLEAR 200,&H3FFF

    This will set BASIC’s stack below $4000. You could create a BASIC loader which you RUN to load and execute the code. Something like:

    10 PMODE0,1:PCLEAR1:CLEAR 200,&H3FFF
    20 LOADM “MYPROG.BIN”:EXEC

  • remz

    Well that’s interesting but strange at the same time. When you load a machine language program with LOADM, you usually don’t have to specify anything or clear anything: normal programs are designed to be loaded from a freshly booted Coco. So it means that a “multi-origin” loaded program shouldn’t touch certain portion of memory, or else would risk corruption by the disk routine itself right?

    This means that using CLEAR to set the stack pointer can be used to “crash” any existing program, by deliberately setting the stack pointer inside a data section, am I right?

    However it is not a big deal to move data away from dangerous memory addresses. It’s just very strange when you don’t know about it and your program crashes for no apparent reason :)

    Personally I think it is a ‘bug’ or at least a weakness in the disk driver routine to actually access the stack while loading a program, since it can conflict.

  • DarrenA

    I see nothing strange about it. The BASIC interpreter must have a stack. JSR/BSR instructions and the TIMER interrupt need put data onto the stack.

    When BASIC starts up, it looks for the highest available RAM address in the machine and places the stack there. The second paramter to CLEAR is designed to allow you to reserve an upper area of memory for some other purpose and tell Basic not to touch it. It will not ‘crash’ any Basic program, but it could result in ?OM Errors if you don’t leave enough memory for Basic to operate.

    LOADM is a dangerous operation by nature. It will load data into whatever region of memory the file specifies. Basic does not in any way restrict the addresses available to LOADM. If you create a BIN file that may conflict with some area of memory used by Basic, it is your responsibility to ensure that it can be safely loaded. Using a Basic program to setup memory as needed and then load the BIN file is one way. You could also get fancy and design multi-origin BIN file that can take over the load duty from BASIC, and automatically execute itself so that Basic never gets control of the machine again.

  • remz

    Thanks Darren, excellent explanation.
    You are right, it totally make sense.
    Alright I’m off finishing my demo!