|
| |


At a deeper level inside any computer, the CPU (central
processing unit) operates on numbers. It uses numbers to tell it what to do and it uses
numbers to tell it with what it should do it. If that last sentence is hard to chew, all I
really mean is that a CPU uses numbers in calculations but also for instructions on how to
perform those calculations. In short, numbers are everything to a CPU.
The only way a computer tells whether a number is data
or is an instruction is by which path the number arrives at the CPU. If it arrives though
the instruction path, it is a command to follow. If it arrives through the data path, it
is some kind of data being used by one of those commands.
Normally, QBASIC doesn't let you reach this level in
the computer. Instead, you enter in valid BASIC instructions and deep within QBASIC there
is already the needed numeric commands, which a CPU really uses, for interpreting your
BASIC instructions in some appropriate fashion. But you can arrange things in QBASIC so
that you can actually force it to directly execute specific and exact instructions,
written for a much deeper level. In other words, you can write assembly code and
have it execute within the QBASIC environment. To do this in QBASIC, assembly code is
first represented as numbers and then these numbers are placed precisely into memory. (To
do this in simple fashion, I usually use hexadecimal notation, as you will see.)
Assembly programs in QBASIC
In case you don't already know it, assembly code is
just a short semantic step above machine code. It provides a symbolic way of
describing machine instructions, rather than using the exact binary numbers that the CPU
really processes when it runs a program. It also provides a symbolic way of naming your
data, too, rather than having to specify specific memory addresses which are almost
impossible to remember or having to keep track of where they reside. Using symbols in this
way makes more sense to humans who need to read and write code and makes it much easier to
edit and change them, as well.
In the end, though, these assembly programs wind up
becoming just a series of numbers that the CPU interprets as code. The CPU only
operates on the binary code. Assembly code is designed for human readability and not
for direct use by the CPU. So an assembler is used to convert from the human
readable approximation into actual machine code (or something very close to it.)
Regardless, this means that if you can get the right numbers placed in the right order in
the computer's memory, you can just tell the computer to access that data as if it were
code and it will run it.
In short, you can get QBASIC to load actual code into
the computer memory by first treating it as data, a feature that QBASIC already handles
quite well. Then you can use another feature in QBASIC to ask it to treat that loaded data
as code. That is how QBASIC can be used to support accessing assembly programming.
For example, here's a short routine written in assembly
language and designed to accept a string length and a pointer to the string itself and
reverse the order of the characters in it:
ReverseStr PROC strlen:PTR WORD, strofs:PTR WORD
mov bx, strlen
mov cx, [bx]
mov bx, strofs
mov bx, [bx]
mov di, bx
add di, cx
.WHILE (cx > 1)
dec di
mov al, [di]
xchg al, [bx]
mov [di], al
inc bx
sub cx, 2
.ENDW
ret
ReverseStr ENDP
In the binary language of the x86 CPU though, those
instructions are converted into the following sequence of numbers in memory:
DATA &H8B55, &H8BEC, &H085E, &H0F8B, &H5E8B, &H8B06, &H8B1F, &H03FB
DATA &HEBF9, &H4F0B, &H058A, &H0786, &H0588, &H8343, &H02E9, &HF983
DATA &H7701, &H5DF0, &H04CA, &H0000
When the source code fragment above (as part of an
appropriate program "skeleton") is assembled with an assembler tool, those are
the values that are produced. And if those numbers are read into an INTEGER array in
QBASIC then they can be thought of as equivalent to the assembly source code above.
I won't spend a lot of time trying to drill this fact
in. If it doesn't make sense to you now, it will one day. But the fact remains
that these are equivalent to each other and that QBASIC can use this fact to make it
possible to use assembly programming as part of your QBASIC programming.
Even if you aren't familiar with writing assembly
programs, I think you can easily see from above which of the two would probably be easier
to work with, change, enhance, and otherwise maintain. That's why I strongly recommend
that you take the time to learn to properly use ML as your assembler tool and to rely on
it for any development you do for QBASIC interfacing. (I have a web page that
describes how to get the ML assembler here, along with some
other helpful software development tools. Also, if you want to read through a small
tutorial of mine on using the DEBUG program and ML assembler, you can look here.)
 |
Please also keep in mind that what I've shown above are fragments. The
assembly source code is incomplete -- it needs some additional directives before an
assembler can properly process it. (There is a completed version, given a little
later on.) The DATA statements are also incomplete -- additional QBASIC code is
required in order to properly use them. I've exerpted them solely to call attention
to their rough equivalence. (There also is a completed version, given a little later
on.)
|
Last updated: Wednesday, July 06, 2005 21:02
|