Re: A89: Paramaters for ASM programs


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

Re: A89: Paramaters for ASM programs




On Fri, Jun 25, 1999 at 02:50:50PM +1000, Wesley Moore wrote:
> I was wondering if and how you access the parameters passed to a ASM
> program. I am looking to pass a byte (char) as follows
> program("a")
> 
> Wesley

The arguments are pushed on the estack prior to executing the program. They
are pushed in reverse order, the first argument is on the top.

	move.l	200,a2
	; a2 => ROM function address table

	move.l	top_estack(a2),a0
	move.l	(a0),a3
	; a3 => ESI of the topmost object on stack (the first argument)

An "ESI" is a pointer to *the last byte* of an object. This last byte is a
tag byte that indicates the type of the object. A string looks like this:

$00,"The string",$00,$2D
                      ^--- The ESI is the address to this byte.
		           $2D is the tag for a STRING object.

	; a3 => an ESI
	cmp.b	#$2D,(a3)
	bne	Not_A_String	
	lea	-1(a3),a0
Find_Start_Of_String
	move.b	-(a0),d0
	bne	Find_Start_Of_String
	addq.w	#1,a0
	; (a0) = first char in the string or $00 if string is ""

Every data type and every (math) operation in the OS has its own tag. The
special tag $E5 indicates the end of a sequence (argument list).

	; a3 => an ESI
	move.l	a3,-(a7)
	move.l	remaining_elements_count(a2),a0
	jsr	(a0)
	addq.w	#4,a7
	; d0.w = number of objects (arguments) at and following
	;        the given ESI up to the next $E5 tag. This count
	;	 can be 0 (zero) if (a3) = $E5.

	; a3 => an ESI
	move.l	a3,-(a7)
	move.l	next_expression_index(a2),a0
	jsr	(a0)
	addq.w	#4,a7
	; a0 => the ESI of the element that follows 'a3'. I don't
	;       know what happens if you try to get past the $E5
	;       tag... it might or might not work.

To advance to the next object in the sequence (the next argument), you MUST
call "next_expression_index". You cannot find the next object by yourself
since you will never be able to support every possible OS tag in your program.

Note that the "next object" on the estack is physically located *before* the
current object. That is, "next_expression_index" will always return an
ESI (address) that is (numerically) LESS than the ESI of the current object.
You usually don't need to care about this, but it's nice to know when you
try to compare pointers...

If your program is invoked with two string arguments (program("AB","CD")),
the estack (top) will look like this:

..., $E5, $00,$43,$44,$00,$2D, $00,$41,$42,$00,$2D
      ^                    ^                    ^--- Top of the estack and the
      |                    |	                     ESI of the first argument
      |                     --- The ESI of the next argument
       --- End-of-sequence marker


(The equates "top_estack" and others can be found in "exec.inc". Remember
that ROM calls always destroy d0-d2/a0-a1.)


There's a ROM function called "EX_getArg" that is supposed to do most of the
work described above, but it looks *very* questionable to me:
(decompiled into C from a ROM dump)

	/* typedef char *ESI;  <- in some header file */
	/* #define TAG_END 0xE5  <- in another header file */
	ESI EX_getArg(short argnum) {
	  ESI arg = top_estack;
	  while(argnum--) {
	    arg = next_expression_index(arg);
	    if(*arg == TAG_END) return 0;
	  }
	  return arg;
	}


//Johan


References: