PEEK and POKE, an "advance" and "dangerous" topic...
March 23 2002 at 7:07 PM
FAQ008 = How do you use PEEK and POKE?
well, not really dangerous, most you can do is crash Qbasic and possibly your computer (by "crash", I mean, you have to restart it.. no permanent [sp?] damage)
What PEEK and POKE do, is read from and write to memory. So, no harm comes from PEEKing at memory, you can PEEK all you want, but you'll want to avoid randomly POKEing at places.
To briefly cover memory arrangement, memory is divided into 65536 segments, or groups of memory. Then, in a segment, you can reference 65536 bytes, each byte being called an offset. (65536 segments and offsets, starting at 0 and ending at 65535)
POKE offset, byte
PEEK(offset) 'returns the byte value
But now, how do you change what segment to access? You use DEF SEG:
DEF SEG = segment
if you just use:
Then it'll reset to QBasic's default data segment, where all variables and strings are stored. And this segment should be what DEF SEG is set to by default, so if I didn't use DEF SEG in my program, that probably was why.
Anyway, an IP consists of 4 numbers, separated by periods (.) and each number ranges from 1 to 255 (0 isn't used). A byte's value, how conveniently, can range from 0 TO 255. So, an IP can be compactly stored in 4 bytes.
If you see an IP represented as a long integer, then, most-likely, if you put the number in a variable and look at the 4 bytes that make up that value, you'll find them to be the IP.
Ok, so how do you read or change the bytes of a variable? Well, you'd have to know the memory address first. All variables are stored in QB's data segment, so we know the segment, but what about the offset? You'll use VARPTR (VARiable PoinTeR) to find the offset.
DIM value AS LONG 'makes a 4-byte (long) integer
offset = VARPTR(value)
INPUT "Enter in a value: ", value
PRINT "Byte #", "Value"
FOR i = 0 TO 3
PRINT i, PEEK(offset + i)
As you can see, bytes (and almost everything else in a computer) are numbered starting at 0, not 1.
Note I declared value as a LONG-integer. SINGLE-percision floating-point values are stored in a very complex manner, that I'm not going to get into. So you should probably limit your exploration to INTEGERs and LONG-integers (integers are the same as LONG-integers, but they are only 2 bytes long).
I'm sure, with some experimentation, you'll quickly see the relation of the bytes that make up a variable and its value. Perhaps you'll venture to figure out negative numbers too.
Now, to give you a safe environment to POKE in. You can't do any damage in the video segment, so you can have some fun there.
The video segment is segment &HA000 (that's hexadecimal). If you POKE in this segment, you'll change the graphics on the screen (if you are in a graphics mode and you don't POKE past the end of the screen [though no damage will be done if you do so, as long as you stay in &HA000]).
To plot a pixel of color c at coordinate (x, y) in screen 13, you simply do this:
DEF SEG = &HA000
POKE (y * 320&) + x, c
The & is on 320 to make it a LONG-integer, since the offset can be over 32767 (the limit of an INTEGER).
Here's a program to play with:
DEF SEG = &HA000
offset = (100 * 320&) + 160 'start at center of screen
col = 15
k$ = INKEY$
IF k$ = CHR$(0) + CHR$(72) THEN offset = offset - 320 'move up
IF k$ = CHR$(0) + CHR$(75) THEN offset = offset - 1 'move left
IF k$ = CHR$(0) + CHR$(77) THEN offset = offset + 1 'move right
IF k$ = CHR$(0) + CHR$(80) THEN offset = offset + 320 'move down
IF k$ = "+" THEN col = col + 1
IF k$ = "-" THEN col = col - 1
POKE offset, col
LOOP UNTIL k$ = CHR$(27)
Notice a few things. First off, to move up or down a row, you +/- 320. The screen is 320 bytes (and pixels) wide in mode 13.
Notice that you can move off the right side of the screen and appear on the other side, but one row down. (same with moving off left side and appearing on the right side one row up).
Notice how you can move off the top of the screen and appear on the bottom. But you don't appear right away on the bottom, you have to press up a few more times before you do. Why is that? Well, the screen is 320*200 = 64000 bytes, but the segment is 65536 bytes long. So, for a couple of rows, you'll be off the screen.
Why are you able to go off the top of the screen and appear on the bottom? Well, QBasic will interpret -1 as 65535 and -2 as 65534, etc. (did you play around with negative numbers in the 4-byte program?) Though notice that you'll get an overflow error if you try to go off the bottom and appear on the top (numbers greater than 65535 give an error).
Oh, this should be obvious, but you can, of course, PEEK from the screen too.