As per boz's suggestion, here is a small tutorial on parameter passing between C and Assembler. Just wrote it in 20 minutes so apologies if it doesn't make sense. Please ask away if you have questions:

Parameter Passing from C to ASM Using Belboz's Jagdev Environment Toolset
-------------------------------------------------------------------------
This took me a little while to figure out so it makes sense to pass on
what I have learnt.
When writing Jaguar code that has both C and Assembler using this environment
you will be using SMAC to compile the assembler and VBCC to compile the
code. Using these tools are not covered here but it is important to understand
that this tutorial relates to this specific setup. So lets begin...
Lets say that you have written an optimised 68000 assembler routine to display
a string on screen but your core code is in C so you want to be able to pass
the X and Y coordinate to display at as well as the memory address of the
string to display.
Although not necessary to compile, it is good practise to have a forward
decleration of this function in your C code before you use it. It also helps
the C compiler to ensure that correct variables are passed to the routine in
question. The forward decleration below shows what this may look like:
extern void foo_str(unsigned long int x, unsigned short int y, char *str);
Remember, this function does not exist in C code and is just a 68000 routine
in an assembly (.s) file.
Using this function in C is, as I am sure you know, a simple task. For example,
lets call it from func1():
void func1(void) {
char *string = "Hello World!\0";
foo_str(10, 12, string);
}
Thats the C end all sorted, no black magic or dark arts, just simple C coding.
Now, the fun stuff, reading in those parameters. But first, lets understand
where the passed parameters, X, Y and string, have gone. Just before the
routine was called these parameters were placed on the stack at the top of RAM
and this is where we need to get them from. Each parameter, regardless of
whether it is a byte (8-Bit), short (16-Bit) or long (32-bit) are stored in
long words (32-bit) on the stack. I want to avoid all the mechanics of stack
management in this tutorial, as thankfully much of it is managed for us. The
key information to know is that we will be using the A7 register as this has
the base address of the stack. Each parameter on the stack has a byte index,
so combining the A7 address with the parameter index we can obtain our
parameters.
All parameter indexes start at $4 (hex) with each parameter being stored four
further bytes (log word) later. So with our example in mind, the parameter
indexes are:
Parameter Index
x $4
y $8
str $c
The index increases by 4 bytes for each parameter passed, for example if we
had a function passing six parameters we would have the following indexes:
Parameter Index
param1 $4
param2 $8
param3 $c
param4 $10
param5 $14
param6 $18
Now that we know what indexes we can find our parameters at we need to
combine this with the A7 stack register. So, in our code, if we want to
get the contents of the first parameter and place them into register d0
we would type:
move.l ($4,A7),d0
Its that simple. Well, not quite;)
You will have noticed earlier that our second parameter was a short integer
and if we try to access it from index $8 we will get zero. Because the stack
is made up purely of long integers we need to add to the index to obtain
short integers. Parameter 2's base index is $8, we want the short integer
stored there so we need to add $2 to the base index. Therefore, to load
our second parameter into d1, we would type;
move.w ($a,A7),d1
Our third parameter, is an address to a string of characters. All addresses
are long integers so we can read directly from the parameter index, as such;
move.l ($c,A7),a0
So, our 68000 routine may look something like this;
_foo_str:
move.l ($4,A7),d0 ; Get X Parameter
move.w ($a,A7),d1 ; Get Y Parameter
move.l ($c,A7),a0 ; get String Address
; .... Do Some Processing with this Data ...
rts
It is VERY IMPORTANT to remember to preceed your function label with an
underscore so that the Linker can correctly marry up C and Assembler
functions.
This is where the story should end, and when I first was playing around with
this I though so too. But I forgot one key issue. When calling assembler
routines from C, YOU MUST ensure that your assembler function saves all the
registers you use in your assembler function to the stack before processing
and return them after processing is completed.
THIS AFFECTS THE STACK INDEXES !!!!!!! ARGGGGHHH !!!!
But it is relatively straight forward to understand. In our example, code
above we used registers d0, d1 and a0 in our routine. First, lets ensure
these get pushed to the stack at the start of the function and popped off
at the end. Our code would look like this:
_foo_str:
movem.l d0-d1/a0,-(sp); Save registers
move.l ($4,A7),d0 ; Get X Parameter
move.w ($a,A7),d1 ; Get Y Parameter
move.l ($c,A7),a0 ; get String Address
; .... Do Some Processing with this Data ...
movem.l (sp)+,d0-d1/a0; Restore registers
rts
The problem you may have noticed is that if our passed C parameters are on
the stack and now are saved registers are also then the indexes we use to
access our parameters are wrong. If you did, then you are correct :)
To resolve this issue we need to add the number of bytes of stack space used
for saving our registers to the base parameter indexes. In this example, we
have saved (pushed) three registers to the stack, each register being a long
integers, so four bytes long each. Therefore we have increased the stack by
12 bytes (or $c in hex).
To make sure we can access our parameters we need to add the stack increase
to the base indexes, so our code would now look like this;
_foo_str:
movem.l d0-d1/a0,-(sp); Save registers
move.l ($10,A7),d0 ; Get X Parameter ($4 + $c)
move.w ($16,A7),d1 ; Get Y Parameter ($a + $c)
move.l ($18,A7),a0 ; get String Address ($c + $c)
; .... Do Some Processing with this Data ...
movem.l (sp)+,d0-d1/a0; Restore registers
rts
This covers the basics of parameter passing in C. I have not covered
return addresses here and will probably do so soon.
Hopefully, this kinda makes some sense. Am happy to answer any questions
you may have....

To follow on from my brief tutorial of parameter passing I thought I would highlight a real world example, displaying a sprite on screen using the blitter. In C, the forward decleration of the routine is:

Its important to note that this isn't necessarily the right or wrong way to do it, its just a way I find works for me. It should also provide a good insight to various methods I personally use.

Enjoy

What came after the Jaguar was the PS1 which for all it's greatness, ushered in corporate development and with it the bleached, repetitive, bland titles which for the most part we're still playing today. - David Wightman