|
Most assembly routines aren't worth much unless you can provide them with specific information, from time to time, and/or unless you can receive back values they compute or gather for you. Specifying parametersCALL ABSOLUTE makes provisions for passing parameters to an assembly routine and for getting values back out, as well. You should read the help on CALL ABSOLUTE, because I'm not going to repeat every detail here. However, the general form is simply: CALL ABSOLUTE (p1, p2, p3, ..., pn, offset) The last parameter specified to CALL ABSOLUTE is always taken by QBASIC to provide the offset portion of the address of your assembly program. But the other parameters, the ones preceeding the last, are placed on the stack so that the assembly routine can access their values. Pass-by-referenceCompilers (and intepreters like QBASIC) have been using one of three common methods for passing parameters for many, many years. These are:
I won't go into any further detail of these here, except to say that QBASIC uses pass-by-reference for everything. You may begin to understand the others later, by implication, if you don't already know what they mean. Pass-by-reference means that you assembly routine is given a memory address that points to the actual values, rather than being given the actual values, themselves. Your assembly routine will need to use those addresses and read what is located there in order to process the actual value. Similarly, your assembly routine can also use those addresses to update or modify the value, as well. However, not all parameters are treated the same by QBASIC. When QBASIC passes a literal value via CALL ABSOLUTE, such as 10, it constructs a temporary, unnamed variable in the available memory for it and stores the value 10 there. It then takes the offset portion of the address to it and places that offset value onto the stack, from which your assembly program can indirectly find the value 10. When the CALL ABSOLUTE routine finishes and returns to QBASIC, QBASIC destroys this temporary value and the storage it required. Such literal values are only temporary -- existing only long enough for the call to finish. When QBASIC passes a variable's value via CALL ABSOLUTE, it simply passes the offset portion of the address for that variable. This way, if the assembly program wishes to do so, it can modify that variable's value before it returns to QBASIC. This is the usual way that values get returned from assembly language subroutines, using CALL ABSOLUTE. It's also a common way to pass values into those same subroutines. So, for example, if you wrote this: CALL ABSOLUTE (10, myvar, asmaddr) Then QBASIC would construct a temporary variable for the value 10, store the value 10 in it, and pass the offset of the address to that new variable to the assembly code. QBASIC would also pass the offset to the address to 'myvar', as well. After the call was complete, QBASIC would then destroy the temporary storage for the value 10, so any changes made to it by the assembly routine would be lost. However, QBASIC leaves 'myvar' intact, so changes made to myvar's value would remain. When you write your assembly programs, you will need to remember that the values passed on the stack by QBASIC are not the values themselves, but rather the offset portion of the address to those values. This is an essential detail you must remain conscious of, while writing assembly programs. QBASIC doesn't need to tell the assembly routines the segment portion of the address for each parameter value because they are all in a segment group called DGROUP and QBASIC makes certain that the DS register is already correctly set for that group before your assembly routine starts up. So the offset portion is all you need. The rest is already done for you. Let's revisit my earlier example in more detail.
Last updated: Thursday, June 17, 2004 19:28
|