BBS: Inland Empire Archive Date: 05-10-92 (13:11) Number: 139 From: MATT PRITCHARD @ 930/21 Refer#: NONE To: RICHARD VANNOY Recvd: NO Subj: Bit shift & rotate 1/2 Conf: (2) Quik_Bas
MP>I've seen the recent discussion on Bit Shifting and must admit...
RV> As a beginner in ASM, I've never tried putting ASM in
RV> any other language's code. Just a few questions on your
RV> code to see if I have the basic idea.
RV> Is this right?
RV> 1. Write the ASM procedure(s).
RV> 2. Compile to .OBJ.
RV> 3. Name all procedures in .INC.
RV> 4. Compile your program normally, except pull in the
RV> assembly .OBJ with the linker.
Richard,
You're only a beginner in ASM? I would have thought
otherwise; but your questions are quite valid and
worthwhile; so here it goes.
I provided a dump of the ".OBJ" file at the start of the
messages on Bit shifting so that you could skip steps 1 & 2
above. and a listing of all the routines so you could skip
step 3. The purpose in providing the Assembly listing here
in the Quick_Bas echo was to let people see the inner
workings of the routines.
You have to have the .OBJ to start with. From there you
make a .QLB for use in the environment. If you have the
.ASM (source code) that's great; you can get in there are
change the code if you want to.
The QB/QBX Environment takes care of finding the actual
routines in the .QLB file and the Linker takes care of that
when it makes the .EXE file.
----------------------------------------------
RV> Let's say you have a PROC XYZ declared as
RV> DECLARE SUB XYZ(a%, b$)
RV> How does your assembly sub know where to find a% and b$?
Good Question: a% and b$ are "parameters" that are
"passed" to the XYZ routine. And there are 2 ways that
QuickBASIC/PDS will pass parameters: "Pass by Value" and
"Pass by Reference". What you see above is "Pass by
Reference"; to "Pass By value" you use the "BYVAL" keyword
in the DECLARE SUB|FUNCTION statement. Both of these
methods involve placing data on the "Stack".
"Pass by Value" - If you have the number "1234", you push the number "1234"
directly on the stack before you call XYZ.
"Pass by Reference" - If you have the number "1234" you
put it in memory somewhere, and push the memory location
(to find it at) onto the stack.
or.. another way to say it:
"Pass By Reference"
DECLARE SUB XYZ (a%)
a% = 1234
CALL XYZ (a%)
a% is an integer variable whose value (1234) is stored at (for sake
of discussion) memory location 500. To call XYZ, the computer: 1)
puts "500" on the stack, and 2) Calls XYZ.
XYZ reads the address 500 off of the stack, and says "ahh, I can find
the value I am looking for at memory address 500" It goes and reads
memory at address 500 and finds the value 1234.
"Pass By Value"
DECLARE SUB XYZ (BYVAL a%)
a% = 1234
CALL XYZ (a%)
a% is an integer variable whose value (1234) is stored at memory
location nnnn. To call XYZ, the computer: 1) reads the value at
nnnn, 2) put that value on the stack, and 3) Calls XYZ
XYZ reads the value (1234) directly off the stack.
-----------------------------------------------------------------
As we can see, Pass by Value adds an extra step before the call, but
the called routine has less work to do.
By default, all calls in QuickBASIC are "Pass by Reference", you
can't "Pass by value" without using BYVAL in declarations.
One more *important* thing:
sub XYZ can *change* the value of a% if it is passed by reference.
If it is passed by value, it can't change a%. It knows what value a%
has, but it doesn't know where in memory a% is actually stored.
Another effect of the 2 ways to pass paramemters. When passing by
reference, the compiler has to turn a constant into a variable before
it can make the call.
When you have:
DECLARE SUB XYZ( x1%, x2%, y1%, y2% )
CALL XYZ (10, 5, 100, 50)
you actually get:
DECLARE SUB XYZ( x1%, x2%, y1%, y2%)
< temp.x1 = 10 >
< temp.x2 = 5 > '(Slight of hand by the compiler)
< temp.y1 = 100 >
< temp.y2 = 50 >
CALL XYZ( temp.x1, temp.x2, temp.y1, temp.y2 )
When you allways call a routine with constants, you can get
tighter code by passing by value.
---------------------------------------------------------
Strings in QuickBASIC and PDS are a special case.
Strings are allways passed by reference. The reference that is
passed has to be decoded to get the real memory address as well as
the length of the string. PDS 7.1 adds a whole new way to decode the
string reference.
----------------------------------------------------------
RV> How do you return a value? Do you put it in AX, then use
RV> CALL Interrupt in BASIC to read it, or do you put the
RV> address of the answer somewhere or what?
There are a couple ways to return values to QuickBasic:
The only difference between DECLARE SUB and DECLARE
FUNCTION is that DECLARE FUNCTION will return information
in the AX and DX registers. Depending on what type of
function was declared, QuickBASIC will know how to handle
the info it gets back.
Take this snippit of code:
DECLARE FUNCTION AssemblySUB%
X = AssemblySub%
>>> Continued to next message
===

Books at Amazon:
Back to BASIC: The History, Corruption, and Future of the Language
Hackers: Heroes of the Computer Revolution (including Tiny BASIC)
Go to: The Story of the Math Majors, Bridge Players, Engineers, Chess Wizards, Scientists and Iconoclasts who were the Hero Programmers of the Software Revolution
The Advent of the Algorithm: The Idea that Rules the World
Moths in the Machine: The Power and Perils of Programming
Mastering Visual Basic .NET