Re: A89: Exec


[Prev][Next][Index][Thread]

Re: A89: Exec




> Yes another question about exec. :)
> 
> Ok, I tried to modify Johan's key autorepeat program to accept parameters. 
> The asm code is below, if you are interested.
> 
> I tried to run it at the home like this :
> 
> Exec 227800C8206909204E90544F206909244E904E750000 ,18,70
> 
> It blew up, and I dont have access to a screwdriver. :(  Address Error.  
> Yeah the evil one with the black lines at the top. :)

Address error because the arguments are *NOT* pushed on the regular stack. They're pushed on the *estack* which is maintained by the OS and 
used as a temporary storage during evaluation and Basic execution. I think that the `e' is for `expression' (or maybe `evaluation').

`top_estack' points to a RAM variable that contains the ESI of the top (most recently pushed) element. ESI is short for EStack Index and 
it's a 32-bit variable that uniquely identifies this expression. (It's a (32-bit) pointer, of course.)
You can use `next_expression_index' to get the ESI to the next element, and `remaining_element_count' to find out how many args there are on 
the estack (if you supply `top_estack' as parameter). TI also provides `EX_getArg' that returns the ESI of to the n:th argument (first arg 
is number zero). Give me a hint if you can't C what I mean:


typedef void *ESI;

ESI next_expression_index(ESI first); /* returns ESI of expr following `first' */

short remaining_element_count(ESI first); /* number of items including `first' */

ESI EX_getArg(short num); /* I'm not sure about this one since I've never used it myself, but I can verify this later. */


You must use `estack_to_ushort' or `estack_to_short' to convert the argument into a 16-bit short, since only "native" TI formats (integer, 
float, string etc...) are passed as parameters. Variables will be passed by value if they exist, otherwise the name of the variable will be 
put on the stack.


short estack_to_ushort(ESI TI_Integer,unsigned short *destination); /* returns 1 if out of bounds, 0 if ok, -1 if not an integer *OR* 1 of 
ok, 0 if out of bounds and -1 if not integer */

short estack_to_short(ESI TI_Integer,short *destination); /* same as estack_to_ushort, but bounds are -32768<=destination<=32767 */


> It might be pushing two long words on the stack.  Does anyone know how to 
> tell it how to just push a word?  If that is not it, could someone look 
> through the asm code.  Thank you.  I appreciate the help!

As I've said, it doesn't push them on the stack. Your code makes no sense, except for a crash.

> 
> 
> Assembly language:
> 
> xdef _main
>
> _main:
>                        ; I don't need to push any registers
>   move.l 200,a1        ; get start of ROM table
>   move.l $920(a1),a0   ; get address of OSInitKeyInitDelay
>   jsr (a0)             ; do it.  Parameters should be on stack.
> 
>   addq.w #2,a7         ; get rid of first parameter

>   move.l $924(a1),a0   ; get address of OSInitBetweenKeyDelay

ARGH! STOP! YOU CAN'T REUSE A1 HERE!

ROM calls destroy d0-d2/a0-a1!!!
Maybe you're sure that this very ROM call doesn't destroy a1, but what about the next ROM release? You must NEVER assume that d0-d2/a0-a1 
are the same after a ROM call.

>   jsr (a0)             ; do it, with the second parameter

Assume that the parameters *were* pushed on the stack: Why do you discard the first parameter but not the second? As written now, RTS will 
use the second parameter as the return address. That's a bad thing, trust me :)

>   rts
>   dc.w 0               ; end of TI relocation table
> 
>   end



Follow-Ups: