Running a program by loading it in memory

When you want to run a program on Amstrad CPC, the procedure is to use RUN command in BASIC. It will read data on the floppy disk (or cassette), transfer it to RAM and jump to the program’s entry point. Let’s write a small program that can be executed with a simple LOAD command, meaning that simply transferring it to RAM will trigger its execution!

Loading with AMSDOS

AMSDOS cannot load a file to an area of the memory,that is too low. However, if a program is located in an area that is high, then the loading pushes through. It is important to note that the the stack initially points to &C000. Every time the CPC calls a function, it stores the return address into the stack (SP is then decreased by 2).

In other words, if Basic interpreter executes a CALL xxxx in &1234 , then &1237 is stored in the stack at &BFFE-&BFFF (SP = SP-2). When the function in xxxx ends, a RET is executed, which will then jump back to &1237 and put the stack back at &C000 (SP = SP + 2).

That being said, if we load a file located at &BEBE that goes up to &C000, and if the area to which the stack is currently pointing is filled by &BE bytes (&BE, &BE, &BE, &BE…. ), then the first RET that the system will encounter after loading will take the Z80A directly to &BEBE and thus run the loaded code!

Our program

 di
 ld bc,#7F10
 ld hl,#4B5C
 out (c),c
noend
 out (c),h
 nop
 out (c),l
 nop
 jr noend
 defs 140,#be ; #bfff-#bebe = 140

If you attempt to SAVE this code from the CPC, tou’ll have to assemble it at another address (luckily our little piece of code is relocatable), save it, and modify the AMSdos header so that the program is located at the correct address.

Another solution consists of using RASM, which can directly generate this DSK with a correct Amsdos header for our file:

org #BEBE
start:
 di
 ld bc,#7F10
 ld hl,#4B5C
 out (c),c
noend:
 out (c),h
 nop
 out (c),l
 nop
 jr noend
 defs #bfff-$,#be
end:

save 'arg.bin', start, end-start, DSK,'arg.dsk'

Let’s see if it works:

Something that has never been done, is a program launch using a simple CAT. I think it’s impossible,but who know?