Wilcox wrote: > Well, I figured that much out, but I don't see how to pass parameters with > the toolbox calls. Such as, in the toolbox call DebuggStr, it takes one > parameter, a string. How would I pass Debuggstr something like "FOOBAR"? > Would I MOVE "FOOBAR" into the a6, or a7, or what? > > What about functions with >1 parameters? Parameters are generally passed in one of two ways. In some of the older (but still widely used) Toolbox routines, you pass parameters by loading them into one or more of the sixteen "CPU registers," which are called A0 through A7 and D0 through D7 (actually, A5, A6 and A7 are reserved for other purposes, so you're really limited to 13 registers to use in this way. In practice, you rarely use more than three or four of them). Each CPU register can hold up to 4 bytes. Routines that work this way are called "Register-based routines." NEWHANDLE is an example of such a routine. To call it in assembler, you store the desired size into D0, then execute the "NewHandle trap," which means you put $A122 as the next machine language "instruction". NewHandle then executes, and it puts the result code into the lower half of D0 (this will be zero if all went well) and puts the handle itself into A0 (this will be NONzero if all went well). As you probably know, you can use MOVE instructions to copy numbers from FB variables into CPU registers, and vice-versa. Other Toolbox routines are called "stack-based routines." In such routines, you store input and output values in a certain area of RAM called the "stack." You never have to worry about where the stack is, nor where within the stack you should put your parameters, because one of the CPU registers (A7, to be exact) always acts as a "stack pointer," and contains the address of the current location in the stack where the next parameter should be put into. In stack-based routines, you specify an input parameter by "pushing" it onto the stack. That means: you first subtract either 2 or 4 from the current value of A7 (depending on the size (2 or 4 bytes) of the parameter that you're passing), and then store your parameter at the new location that A7 now points to. All of this can be done with a single machine-language instruction. You "push" all the parameters onto the stack in this way. They must be "pushed" in the same order in which they appear in the routine's description in Inside Macintosh. If the (stack-based) routine is a "function"--that is, if it returns a value--then there's an additional requirement: _before_ you push any parameters onto the stack, you must subtract 2 or 4 bytes (depending on the size of the returned value) from the stack pointer. You can do this with a CLR.W -(A7) or a CLR.L -(A7) command, or by explicitly subtracting 2 or 4 from A7. Moving the stack pointer in this way "leaves room" on the stack for the returned result. Once you've done all this, you code the "trap" for the Toolbox routine (sometimes it's also necessary to store a "selector" value, usually into D0. This allows a single "trap number" to handle many, many different routines, each of which responds to a different selector value). The Toolbox routine knows where to find the parameters simply by looking at the value of A7. If the routine is a function and hence returns a value, then the return value will be "on the stack" when the routine finishes. You retrieve this value by "popping" it off the stack; this means, read the 2 or 4 bytes at the location that A7 points to, then add 2 or 4 to A7 (so that it points to a new location). Again, this can all be done with a single machine-language instruction. Notice that parameters are _always_ 2 bytes or 4 bytes long. In cases where you need to "pass" something longer, like a string, what you should pass is the objects _address_ (i.e., a pointer to the object's location in memory), which is always 4 bytes. In stack based routines, you _must_ push and pop the exactly correct number of bytes onto and off of the stack (for example, you're not allowed to just "ignore" the return value and fail to pop it off the stack). The reason is that pushing and popping always adjusts the value of the stack pointer, and the stack pointer _must_ be adjusted by the right amount. If it's pointing to the wrong address when you exit the LOCAL FN, a system error could easily result. Here's an example using DebugStr: LOCAL FN myDebugStr(stringPtr&) ` MOVE.L ^stringPtr&,-(A7) ;push stringPtr& onto stack ` _debugStr ;can also be coded as: DC.W $ABFF END FN You could call this as follows: msg$ = "This is a message." FN myDebugStr(@msg$) Hope this helps. - Rick