Beginners guide to VARSEG and VARPTR
This article was written by Fling-master
This article will discuss the use of VARSEG and VARPTR in your QBasic programs. It is intended mainly for newbies to QB but also for people who aren't 100% confident with using these commands.
VARSEG and VARPTR, first of all deal with a variables position in your computer's memory. To get a firm grasp of these commands you should know how to use the values returned. So I will discuss segments and offsets! =)
Segments and offsets are a pair of numbers telling the computer where to read and write data to. A segment is a group of 16 bytes in memory. An offset on the other hand is a group of 1 byte. These two numbers are used together to get the address of something in memory. So if I want to get the data at address 156 in memory I would set the segment to 9 and the offset to 12. If I wanted to get the data at address 34 in memory I would set the segment to 2 and the offset to 1. You could just set the offset to 156 in the first example and 34 in the second but we just don't do that, especially if the desired address is a big number 64000! Also the segment is always first e.g. segment:offset.
So now you know what they are. Now what do they have in common with VARSEG and VARPTR you ask? Well VARSEG returns the passed variables segment address as an unsigned integer (a positive number), and VARPTR returns the passed variables offset address also as an unsigned integer. This is a handy thing especially if you're using stuff like BSAVE, BLOAD, POKE, PEEK, and CALL ABSOLUTE.
So let's do a simple example program here, to show you how you'd use it. We're gonna get the segment and offset address of an integer variable in QB:
'This program will print an integer's segment and offset address. DIM myvariable% 'We're gonna dim in just in case. =) segment% = VARSEG(myvariable%) 'Get the segment address offset% = VARPTR(myvariable%) 'Get the offset address 'Display the variable memory location PRINT "myvariable% is located at "; segment%; ":"; offset%
There you go! Try it to see if it works. This example though really isn't useful. BUT, when you get a variables address you can do other things like use BSAVE to save it to a file. Make sure that when you get a variables address you do whatever it is you are gonna do with it quickly as the address could change!
Let's make an example that actually does something that could turn into something useful. We're gonna make a program that adds two numbers together and saves the result, using BSAVE to a file. This will require the use of VARSEG.
DIM c% 'Just in case =) INPUT "Enter number 1: ", a% 'Get number 1 to add INPUT "Enter number 2: ", b% 'with number 2! c% = a% + b% 'Add them together 'Here we're setting the default data segment used by QB to the c% variable. This way BSAVE 'get the data from there and save it to the file. DEF SEG = VARSEG(c%) 'Here we're specifying a file and secondly the offset of c%, then we tell BSAVE the length 'to save which, because c% is an integer, happens to be 2. BSAVE "c:\number.dat", VARPTR(c%), 2 'Unless you know what you're doing, you should always restore the default segment back to the 'original basic segment. Which is what this does. DEF SEG PRINT "Result is"; c%; "!" 'Show the user the result of the addition
Go ahead and try it out! You will see that after the program has finished there will be a file called number.dat in your harddrives root directory. Although the file will be saved as binary. To read this file we use BLOAD. Here's an example which will read the number.dat file from before and display the contents:
DIM c% 'Just in case =) DEF SEG = VARSEG(c%) 'Set the default segment to c% 'Here we use BLOAD and specifiy the file which contains the number, and the offset of c% BLOAD "c:\number.dat", VARPTR(c%) DEF SEG 'Restore the default segment PRINT "The number you got when you added was"; c%; "!" 'Show the result
There! Simple right? Now you should have a good understanding of VARSEG and VARPTR. You can also use this with strings to but instead of using VARPTR use SADD. Now you can use POKE and PEEK, especially since you know what segments and offsets are. Before using POKE or PEEK you should first set the default segment using DEF SEG to the segment address you want to write/read data from, similar to the above examples.
'$DYNAMIC DEFINT A-Z DIM myvar 'Dimension just in case PRINT "myvar is set to 13." myvar = 13 'Set myvar=13 DEF SEG = VARSEG(myvar) 'Set default segment to myvar POKE VARPTR(myvar), 27 'Poke a new value, 27, into the offset of myvar DEF SEG 'Resetore the default segment PRINT "myvar now equals:"; myvar 'Print the new value of myvar
There ya go. That'll let you put numbers into variables. Now these examples are sorta useless, but they can be expanded and worked with to meet your needs. A good use for POKE and PEEK is with the famous memory segment A000. This of course is the address of the video segment. Since it's in hexadecimal you should precede it in QB with a &H. POKE will let you draw a pixel, and PEEK will let you read a pixel. One last thing, you can't POKE a value of more than 255, if you do you'll get the value of the number you poked minus 255 (This will never be larger than 255 either.)
If you don't understand this then please e-mail me. Have fun!
|All site content is © Copyright 2001, HyperRealistic Games. This excludes content submitted by other people.|