Frage deutsch
~~~~~~~~~~~~~~
Wie funktionieren die Befehle PEEK und POKE?
Welche sinnvolle Adressen gibt es dafür?
 

Question English
~~~~~~~~~~~~~~
How does this PEEK & POKE stuff work?
How to access memory using PEEK and POKE?
 

Antwort 1
~~~~~~~~~
[ von Tobias Doerffel ("todo"; mailtodo*web.de ), per Mail, 29.4.02 ]
.
Also erst einmal ein paar grundlegende Dinge zum Speicher und dessen Organisation. Der Speicher wird im Real Mode (in dem die QB-Programme laufen) in Segmente eingeteilt. Ein Segment fasst 64 KB (65536 Bytes). Da man im Real Mode nur auf den ersten MB Speicher zugreifen kann, heißt das, dass es 16 Segmente gibt. Um nun innerhalb eines Segmentes auf ein bestimmtest Byte zugreifen zu können, gibt es noch die Offsetadresse. Diese liegt logischerweise zwischen 0 und 65535 (das erste Byte hat die Adresse 0, das zweite 1 usw.). Damit kann man also auf jedes Byte in einem Segment zugreifen.
Folglich muss man beim Speicherzugriff ein Segment und eine Offsetadresse angeben. Das Segment gibt also "grob" an, wo der Speicherzugriff stattfinden soll und die Offsetadresse erledigt die "Feinarbeit". Der Prozessor bildet dann intern eine lineare Adresse, ohne Segment usw. Eine lineare Adresse kann man wie folgt ausrechnen:

Adresse = Segment * 16 + Offsetadresse
 
Damit erhält man eine 20 Bit Adresse. Aber das soll hier nicht weiter von Interesse sein, da es wie gesagt eine Sache des Prozessors ist. Bei PEEK und POKE muss man auf ein Segment angeben. Das geschieht mit DEF SEG:
DEF SEG = &HA000
 
Nun wissen PEEK und POKE, auf welches Segment sie zugreifen sollen, in diesem Fall ist es ein Teil des Video-RAMs. Nun muss man also nur noch die Offsetadresse angeben. Dies geschieht direkt beim Aufruf von PEEK/POKE:
DEF SEG = &HA000
a = PEEK(&H1234)
 
Diese zwei Zeilen lesen den Inhalt der Speicherstelle A000:1234 und speichern den Wert der dort steht in a. So lautet die offizielle Notation (damit meine ich A000:1234). Man gibt Segment und Offsetadresse als Hexwerte, getrennt durch einen Doppelpunkt an. Natürlich kann man nicht nur lesen sondern auch schreiben:
DEF SEG = &HA000
POKE &H1234, 15
 
Hier wird der Wert 15 an die Speicherstelle A000:1234 geschrieben. Übrigens kann man das ganz praktisch im Bildschirmmodus 13h anwenden. Man kann Pixel setzen, indem man direkt in den Video-RAM schreibt:
SCREEN 13
DEF SEG = &HA000
POKE 0, 15
 
Mit diesem Beispiel wird das Pixel mit den Koordinaten (0, 0) auf weiß gesetzt. Allgemein gilt:

Video_RAM_Adresse = x * 320 + y
 
Um also Pixel (100, 100) zu auf hellgrau zu setzen, muss man den Wert 7 an die Speicherstelle 100 * 320 + 100 = 32100 = 7D64h, also A000:7D64 schreiben:
SCREEN 13
DEF SEG = &HA000
POKE &H7D64, 7
 
Weitere sinnvolle Adressen wären z.B. das BIOS-Datensegment, über das es unter http://www.datasource.de/programmierung/tab07_biosdatenbereich.htm eine genaue Beschreibung aller Werte und deren Bedeutung gibt. Einige Informationen aus dieser Webseite findest Du in dem Beitrag "Welche absoluten Speicheradressen gibt es für den Zugriff mit Peek und Poke?".

 

Antwort 2
~~~~~~~~~~
[ von Matthias Becker (alias "Helium" alias "Beckah";
M.Beckah*gmx.de ), 19.4.02 ]
 
Was ist Peek und Poke?
Im Speicher hat jede Variable eine Adresse. Diese besteht aus einem Segment und
einem Offset. Um das Segment einer Variable zu bestimmen verwendet man den
Befehl Varseg() und um das Offset zu erhalten Varptr().
a% = 7
segment = varseg(a%)
offset = varptr(a%)
 
Was mache ich mit solchen Adressen? Mit Peek kann man von einer solchen Adresse
lesen. Dazu setzt man das segment mit dem Befehl Def Seg (Leerzeichen Beachten)
und übergibt pekk das Offset:
Def seg = segment
b% = Peek(offset)
 
PEEK liest aber immer nur ein Byte und nicht den ganzen Wert. So kann man z.B.
einen Integer-Wert in das höhere und das nidrigere Byte aufteilen:
 
segment = varseg(a%)
offset = varptr(a%)
Def seg = segment
high% = Peek(offset)
low% = Peek(offset+1)
 
Analog kann man mit poke an eine Adresse einen Wert schreiben. Nachdem man so
auf den Speicher zugegriffen hat sollte man mit einem def seg ohne zuweisung das
Segment wieder aufs Standardsegment zurücksetzen.
Viel wichtiger ist aber, dass es einige Adressen gibt, die garnicht zu eigenen
Variablen gehören, sondern z.B. zur Grafikkarte oder zum Betriebssystem.
Beispielsweise leigt an Segement &HA000 Offset &H0000 (auch A000:0000h
geschreiben) der Bildschrimpuffer von SCREEN 13. Dieser ist 64000 Byte groß. Das
kann man sich zu nutze machen:
 
Sub EigenerPSet(x%, y%, c%)
Def Seg = &HA000
Poke x% + 320& * y%, c%
def seg
end sub
 
Wenn man mehrere Pixel setzen will, ist diese Methode sogar schneller als Pset.
Dann muss mannur vorher einmal das Segment setzen, alle Pikel poken und dann
erst wieder def seg aufrufen.
 

Antwort 3
~~~~~~~~~
[ von TT-Soft (
http://www.East-Power-Soft.de/ ) per Mail, 18.01.2002 ]
.
Wie funktionieren die Befehle PEEK und POKE und was kann ich konkret alles damit machen? Ziemlich viel...vor allem kaputt...;-)
 
Aber im Ernst. An einem solchen Tutorial arbeite ich gerade. Was auf jeden Fall geht ist Bilder im Screen 13 verflucht schnell auf den Bildschirm "zaubern". Siehe dazu ebenfalls unter http://www.East-Power-Soft.de/tutorial/bilder.html
 
 
Answer 4
~~~~~~~~~
 
'===========================================================================
' Subject: HOW TO USE POKE Date: 03-17-97 (11:35)
' Author: Benjamin L. McGee Code: QB, QBasic, PDS
' Origin: FidoNet QUIK_BAS Echo Packet: FAQS.ABC
'===========================================================================
' > ... I'm a little paranoid about using the POKE and PEEK
' > commands (mainly POKE, though). How will I know where to
' > POKE into and exactly what can I accomplish by POKEing there?

'From Ralf Brown's Interrupt list MEMORY.LST

' ----------M0400072--------------------------
' MEM 0040h:072h - POST RESET FLAG
' Size: WORD
' Desc: speify the action the BIOS should take at the beinning of the
' power-on self-test when the machine is reset

'(Table M020)
'Values for POST reset flag:
' 0000h cold boot
' 0064h Burn-n mode
' 1234h to bypass memory test (warm boot)
' 4321h [PS/2 except Mod 25,30] to preserve mmory
' 5678h [Conv] system suspended
' 9ABCh [Conv] manufacturing test mode
' ABCDh [Conv] POST loop mode


' ---------- WARMBOOT.BAS ----------
'$INCLUDE: 'qbx.bi'

DEF SEG = &H40
POKE &H72, &H34
POKE &H73, &H12

DEF SEG = &HFFFF
CALL Absolute(&H0)

' ---------- COLDBOOT.BAS ----------
'$INCLUDE: 'qbx.bi'

DEF SEG = &H40
POKE &H72, &H0
POKE &H73, &H0

DEF SEG = &HFFFF
CALL Absolute(&H0)

'There are, no doubt, many other useful memory locations that
'you can POKE values into. A good reference is as valuable as
'gold. Hope that helps...
 
 
Answer 5
~~~~~~~~~
[ von
http://qbtuts.qb45.com/tuts.shtml?page=hardware&file=peekpoke.txt ]
 
'============================================================
' Subject: PC MAGAZINE'S POKES & PEEKS Date: 11-12-85 (19:44)
' Author: David I. Schneider Code: TEXT
' Origin: Rolf*ice.prima.ruhr.de Packet: MEMORY.ABC
'===========================================================================
* * * POKES & PEEKS * * *
Did you know that there is a lot of information that may be
accessed from the ROM BIOS area in your IBM PC regarding the operating
characteristics and options found on your own IBM PC? After careful
analysis of data found in the IBM Technical Reference manual a summary
of the most useful information and where and how it may be referenced
has been prepared.
By specifying a DEF SEG=&H40 in any BASIC program, it is possible
to reference the following vectors (fields) in the ROM BIOS area by
using a PEEK function and the following offsets from the current
segment as defined by the DEF SEG statement.
&H0 - RS232 Addresses on your IBM PC. This will allow you to
tell how many (up to four) async cards are attached, if any.
&H8 - Printer Addresses on your IBM PC. This will tell you what
printer addresses, and how many (up to four) exist. Each is addressed
by a two-byte hex value.
&H10 - Equipment Flag. This field describes the setting of the
options switches. It describes what optional devices are attached to
the system. The following lists the bit-significance of this field:
Bit 0 - indicates that there are disk drives on the system
Bit 1 - not used
Bit 2,3 - Planar Ram Size (00=16K 10=32K 01=48K 11=64K)
Bit 4,5 - Initial Video Mode (00=Unused; 10=40x25 Color
01=80x25 Color 1; 1=80x25 Mono)
Bit 6,7 - Number of Disk Drives (00=1; 10=2; 01=3; 11=4
only if bit 0 = 1)
Bit 8 - Unused
Bit 9,10,11 - Number of RS232 Cards attached
Bit 12 - Game I/O Attached
Bit 13 - Not used
Bit 14,15 - Number of printers attached
 
&H13 - Memory Size in K bytes
&H15 - I/O RAM Size in K bytes
&H17 - Keyboard Flag. The following lists the masks set to
describe current keyboard status:
Byte 1:
&H80 - Insert state active
&H40 - CapsLock state has been toggled
&H20 - NumLock state has been toggled
&H10 - ScrollLock state has been toggled
&H08 - Alternate shift key depressed
&H04 - Control shift key depressed
&H02 - Left shift key depressed
&H01 - Right shift key depressed
Byte 2:
&H80 - Insert key is depressed
&H40 - CapsLock key is depressed
&H20 - NumLock key is depressed
&H10 - ScrollLock key is depressed
&H08 - Suspend key has been toggled
&H49 - Current CRT mode &H00 - 40x25 BW
&H01 - 40x25 Color
&H02 - 80x25 BW
&H03 - 80x25 Color
&H04 - 320x200 Color
&H05 - 320x200 BW
&H06 - 640x200 BW
&H07 - 80x25 B&W Card -- speS)CG\+MF;uuse, used internal
to the video routines.
&H4A - Number of CRT columns
&H50 - Cursor Position (one of eight)
&H60 - Current cursor mode
&H6C - Low word of Timer count
&H6E - High word of Timer count
&H71 - &H07 - Break key de8gIae--UROeTBHg
44E - Beginning of character regen memory
&HFF53 - PrtSc routine address
-----------------------------------------------------------------
 
PEEKing at Your PC's Memory
(PC Magazine Vol 4 No 23 Nov 12, 1985 by David I. Schneider)
 
 
 
 
 
 
Would you like to know the next number that will be generated by
BASIC's random number generator? Would you like to know the date 1,000
days from now? Would you like to determine which of your printers is
on-line? Or have six palettes at your disposal in medium-resolution
graphics mode instead of the normal two?
 
These and many more tasks are easily accomplished by PEEKing
(looking into a memory location), POKEing (placing a number into a
memory location), INPing (reading a number from a port), or OUTing
(sending a number to a port). This article attempts to give a thorough
documentation of the varied uses of these statements. While the
explanations are in BASIC, most of the information is applicable to
every programming language.
 
- - - - -
Before You Start: Before entering and executing any of the PEEK and
POKE statements in this article, be sure this statement is executed
first: DEF SEG = 0. PC Magazine tried the PEEKs and POKEs in this
article on standard IBM equipment, and they worked flawlessly.
However, since they bypass many built-in safeguards to work directly
with your system's memory, playing with them carelessly or on non-IBM
equipment is like playing with fire, so type them in carefully, observe
the proper DEF SEG, and don't try any variations unless you know what
you're doing.
- - - - -
 
PEEKs, POKEs, INPs and OUTs reveal the inner workings of the
computer and thus give the programmer direct control. IBM discourages
the use of PEEK, POKE, INP and OUT, however, since the company cannot
guarantee that future releases of DOS or future ROM chips will use the
current memory locations. Also, ports associated with nonstandard
hardware might function in different ways. To be safe, widely
distributed and commercial programs should avoid such undocumented
features. On the other hand, IBM has been quite consistent so far.
Most of the memory locations and ports presented in this article hold
for all existing versions of DOS and BASIC. Of course, this might
change with some future release.
 
Theoretically, the IBM PC can directly address 1048576 memory
locations, numbered 0 through 1048575. Normally, a maximum of 640K
locations of RAM is available for user programs. The remainder
consists of ROM or is otherwise reserved for present or future system
applications.
 
A segment is a 64K portion of memory beginning at a location that
is a multiple of 16. Segment 0 consists of memory locations 0, 1, 2,
3, ...65535. Segment 1 consists of memory locations 16, 17, 18, ...
65551. Segment 2 consists of memory locations 32, 33, 34, ...65567.
In general, then, segment m consists of memory locations 16*m, 16*m+1,
16*m+2, ...16*m+65535.
 
Within each segment, the first memory location is said to have
offset 0, the second memory location is at offset 1, and so forth;
the last memory location is said to have an offset of 65535. Memory
locations are specified by giving a segment that contains the location,
together with the offset of that location within the segment. Most
memory locations can thus be specified in many ways. For instance,
the designations "segment 0:offset 34," "segment 1:offset 18," and
"segment 2:offset 2" actually refer to the same memory location.
 
Each memory location holds a number from 0 to 255. These numbers
are often called bytes. In BASIC (either in immediate mode or in a
program), to read the number in the memory location segment m:offset n,
you execute: DEF SEG = m : PRINT PEEK (n). The DEF SEG statement
specifies the mth segment as the current segment, and the value of
PEEK(n) is the number contained in the memory location of offset n
in the current segment. In a similar way, to insert the number r
into the memory location segment m:offset n, you execute: DEG SEG =
m : POKE n,r. This POKE statement places the number r into the
memory location of offset n in the mth segment.
 
The PC's microprocessor receives data from and sends data to the
various components of the computer through ports. There are ports
associated with the keyboard, the disk drives, the speaker, and the
screen, for example. A byte of data consists of a number from 0 to
255, and each port has a number assigned to it. The value of the
function INP(n) is the value of the byte read from port n. The
statement OUT n,m sends byte m to port n.
 
The listings presented here deal with memory locations in
segment 0, which is often referred to as low memory. The program,
LOMEMRY.BAS, illustrates many of the applications.
 
Two important procedural considerations must be stressed if you
intend to enter the listings from the keyboard to try them out. First,
the statement: DEF SEG = 0 should be executed before the PEEK and
POKE statements in this section are executed. Second, to prevent a
Syntax Error message, remember to type PRINT before each of the PEEK
statements, so the result will be displayed on the screen. The words
AND and OR in these listings are logical operators and do not mean
"the sum of" or "an alternative to."
 
KEYBOARD
==========
1. The following statements are used to set or determine the
status of the keyboard toggle keys.
 
CapsLock Key: "PEEK (1047) AND 64" has a value of 0 if the
keyboard is in lowercase mode and a value of 64 if the uppercase mode
is active. To specify lowercase: POKE 1047, PEEK(1047) AND 191.
To specify uppercase: POKE 1047, PEEK(1047) OR 64. To toggle between
upper and lowercase: POKE 1074, PEEK(1047) XOR 64. The statement
"PEEK(1048) AND 64" has a value of 64 if the key is pressed, 0
otherwise.
 
NumLock Key: The statement "PEEK(1047) AND 32" has a 0 value in
the cursor-control mode and a value of 32 for the numeric-keybad state.
To specify the cursor-control state: POKE 1047,PEEK(1047) AND 223.
To specify the numeric-keypad state: POKE 1047,PEEK(1047) OR 32.
To toggle between states: POKE 1047,PEEK(1047) XOR 32. The statement
"PEEK(1048) AND 32" has a value of 32 if the key is pressed and a
value of 0 otherwise.
 
Ins Key: The statement "PEEK(1047) AND 128" has a value of 128
for the insert state, 0 otherwise. To specify the insert mode:
POKE 1047,PEEK(1047) OR 128. To specify noninsert mode: POKE 1047,
PEEK(1047) AND 127. To toggle the state: POKE 1047,PEEK(1047) XOR
128. The statement "PEEK(1048) AND 128" has a value of 128 if the key
is pressed a a 0 value otherwise.
 
ScrollLock Key: The statement "PEEK(1047) AND 16" has a value of
16 when ScrollLock is on and a value of 0 otherwise. To specify the
ScrollLock state: POKE 1047,PEEK(1047) OR 16. To specify the
alternate state: POKE 1047,PEEK(1047) AND 239. To toggle states:
POKE 1047,PEEK(1047) XOR 16. The statement "PEEK(1048) AND 16" has a
value of 16 if the key is pressed a a value of 0 otherwise.
 
2. The following statements test the status of some special keys.
The statement "PEEK(1047) AND 8" has a value of 8 if the Alt key is
pressed and a value of 0 otherwise. The statement "PEEK(1047) AND 4"
has a value of 4 if the Ctrl key is pressed, 0 otherwise. The
statement "PEEK(1047) AND 1" has a value of 1 if the right Shift key
is pressed and a 0 value otherwise. The statement "PEEK(1047) AND 3"
has a value of 0 if neither shift key is pressed. The statement
"PEEK(1048) AND 4" has a value of 4 if the Sys Req key is pressed;
otherwise its value is 0 (PC AT only).
 
3. In the numeric keypad state, the character with an ASCII
value n can be displayed on the screen by holding down the Alt key,
typing the number n on the numeric keypad, and they releasing the Alt
key. PEEK(1049) has a value of n from the time the number is typed
until the Alt key is released.
 
4. The circular keyboard buffer begins at location PEEK(1050) +
1024 and ends (possibly after cycling back to location 1054) at
location PEEK(1052)+1023. Ordinary characters use every other
location. Extended characters use two locations, the first location
containing the null character (CHR$(0)). The statement "POKE 1050,
PEEK(1052)" clears the keyboard buffer. The contents of the buffer
can be read by PEEK without first being removed from the buffer.
Further, characters can be POKEd into the buffer to ensure the
continuation of a program even if a program-terminating statement is
executed. For instance, if the string: "GOTO 99" + CHR$(13) is POKEd
into the buffer and a LIST command is executed, the program will
continue execution at line 99 after the LISTing has been completed,
which overcomes BASIC's annoying habit of stopping dead after certain
operations.
 
5. With PCs whose motherboard can hold 256K bytes of RAM, the
keyboard buffer can be assigned a different location and length.
The following program places the beginning of the keyboard buffer at
memory location 1024 + B and gives it the capacity of holding L
characters.
10 DEG SEG=0:H=INT(B/256)
20 POKE 1152,B-H*256:POKE 1153,H
30 T=B+2*L+2:H=INT(T/256)
40 POKE 1154,T=H*256:POKE 1155,H
50 POKE 1050,PEEK(1152):POKE 1051,PEEK(1153)
60 POKE 1052,PEEK(1152):POKE 1053,PEEK(1153)
The buffer contents always begin at: PEEK(1050)+256*PEEK(1051)+1024
and end (possibly after cycling back from location 1085 to location
1024+B) at location: PEEK(1052)+256*PEEK(1053)+1024. You must use
case in choosing B and L. Two possibilities are B=144, L<55 and
B=301,L<233.
 
6. To disable Ctrl-Break, enter: FOR I=0 TO 3:POKE(108+I),
PEEK(112+I):NEXT I. Before disabling Ctrl-Break, use PEEK to record
the bytes in locations 108-111. You can then POKE these bytes back in
to reenable Ctrl-Break.
 
7. The statement "PEEK(1137) AND 128" has a the value of 128 if
the Ctrl-Break sequence has been used since startup to terminate the
execution of a program.
 
8. To disable the keyboard (PC & XT only), send "OUT 97, INP(97)
OR 128". Remember that when the keyboard is disabled, subsequent
keystrokes are ignored.
 
9. To reenable the keyboard (PC & XT only), send "OUT 97, INP(97)
AND 127".
 
10. To disable all keyboard interrupts: OUT 33,130. If keys are
pressed after the interrupts are disabled, the scan codes of the first
20 keys will be held in a buffer located in the keyboard unit. These
codes will be read after the interrupts are reenabled.
 
11. To reenable keyboard interrupts: OUT 33,128.
 
12. Each key has an identifying number called its scan code. The
following program will usually obtain the scan code of a key. After
typing RUN, you must press the Enter key quickly. They press any key
to obtain its scan code. (The program will not work on the PC AT or
certain IBM PC-compatibles.)
10 OUT 33,130
20 WHILE INP(96)=0:WEND
30 PRINT INP(96)
40 OUT 33,128
 
13. For the PC AT only, when a key is held down for more than 1/2
second (the default delay time), it repeats ten times per second (the
default typematic rate). To change the delay rate do d quarter-seconds
(d=1,2,3 or 4) and the typematic rate to approximately r repetitions
per second (r between 2 and 30), you would enter: OUT 96,243:OUT 96,n
where n = (d-1) * 32 + CINT(11.5 * LOG(29/r)). Conversely, the
statement: OUT 96,243:OUT 96,n with n=0,1, ...127, specifies a delay
rate of 1+(n\32) quarter seconds and a typematic rate of 1/((8+(n MOD
8))*2^((n AND 24)/8)*.00417) repetitions per second. The default state
corresponds to n=44.
 
14. For the PC AT only, the green lights that indicate CapsLock,
NumLock and ScrollLock status can be turned on and off without
altering any of the states. The statement: OUT 96,237:OUT 96,n
produces the following results:
n = 7 all indicators on
n = 6 ScrollLock indicator off, others on
n = 5 NumLock indicator off, others on
n = 4 CapsLock indicator on, others off
n = 3 CapsLock indicator off, others on
n = 2 NumLock indicator on, others off
n = 1 ScrollLock indicator on, others off
n = 0 all indicators off
 
MONITOR STATUS
================
 
1. To check the type of display:
PEEK(1040) AND 48 = 0 is no monitors
PEEK(1040) AND 48 = 16 is a 40 x 25 graphics monitor
PEEK(1040) AND 48 = 32 is a 80 x 25 graphics monitor
PEEK(1040) AND 48 = 48 is a monochrome display
 
2. To select a display:
Monochrome POKE 1040,PEEK(1040) OR 48
Graphics POKE 1040,(PEEK(1040) AND 207) OR 16
The first POKE should be followed by: SCREEN 0:WIDTH 40:WIDTH 80:
LOCATE ,,1,12,13. The second should be followed by: SCREEN 1,0,0,0:
SCREEN 0:WIDTH 40:LOCATE ,,1,7,7. Before switching monitor types, it
is a good idea to record (in an array) the numbers that are contained
in memory locations 1097 to 1126. These values can then be confidently
restored after the return to the first display.
 
3. To check screen mode:
PEEK(1097) = 0 text mode, WIDTH 40, color disabled
PEEK(1097) = 1 text mode, WIDTH 40, color enabled
PEEK(1097) = 2 text mode, WIDTH 80, color disabled
PEEK(1097) = 3 text mode, WIDTH 80, color enabled
PEEK(1097) = 4 medium resolution graphics, color enabled
PEEK(1097) = 5 medium resolution graphics, color disabled
PEEK(1097) = 6 high-resolution graphics
PEEK(1097) = 7 monochrome display
PEEK(1098)+256*PEEK(1099) gives the width in columns. Color can be
suppressed only on composite monitors. RGB monitors will display color
even if you are in one of the color-disabled modes listed above.
 
4. Subscripts and superscripts can be displayed in the top half
of the graphics screens. The following programs place the string B$ as
a subscript of the string A$. The value of R must be between 1 and 12,
and the value of C can be at most one more than the width of the screen
minus the sum of the lengths of the two strings. To display B$ as a
superscript of A$, replace the R in line 40 by R-1.
10 SCREEN 1:CLS 10 SCREEN 2:CLS
20 LOCATE R,C:PRINT A$; 20 LOCATE R,C:PRINT A$;
30 POKE 1098,20 30 POKE 1098,40
40 LOCATE 2*R:PRINT B$ 40 LOCATE 2*R:PRINT B$
50 POKE 1098,40 50 POKE 1098,80
 
5. The contents of the graphics screen are stored in a buffer
beginning at offset: PEEK(1102)+256*PEEK(1103) in a portion of
memory that physically resides on a graphics board. The size of this
buffer is given by: PEEK(1100)+256*PEEK(1101)
 
6. When using text mode with a graphics monitor, there are
several memory pages at your disposal. The cursor locations for the
various pages are given as follows: Let CR(n) and CC(n) be the Cursor
Row and Cursor Column for page n. Then: PEEK(1105)+2*n) has a value
of CR(n)-1, and: PEEK(1104+2*n) has a value of CC(n)-1.
 
7. The shape of the cursor can be set with a statement of the
form: LOCATE ,,,I,J. In this LOCATE statement, "PEEK(1121) AND 31"
has value I, and "PEEK(1120) AND 31" has value J. If "PEEK(1121) AND
32" has a value of 32, then the cursor is not displayed.
 
8. To obtain the number of the visual page (that is, the page
currently being displayed), you simply "PEEK(1122)".
 
9. The adapter boards can be given instructions by OUTing to
ports on a chip known as the CRT controller chip. To determine the
number of the index register port for the adapter board currently in
use, "PEEK(1123)+256*PEEK(1124)". The value will be 948 for the
monochrome display board and 980 for the color/graphics adapter.
 
10. The following statements check the mode settings on the CRT
mode register currently in use:
PEEK(1125) AND 1 has value 1 if in text mode, width 80
PEEK(1125) AND 2 has value 2 if in graphics mode
PEEK(1125) AND 4 has value 4 if color is disabled (for instance, if
the statement SCREEN 1,1 has been executed)
PEEK(1125) AND 8 has value 8 if video is enabled, that is, not
blanked
PEEK(1125) AND 16 has value 16 if in high-resolution graphics mode
PEEK(1125) AND 32 has value 32 if blinking is enabled
The value of PEEK(1125) will change after appropriate SCREEN or
WIDTH statements are executed. It is not affected by OUT statements,
however. It will not always reflect the true status of the monitor,
therefore, unless it is updated after OUTs to port 984 or 952.
 
11. In the medium-resolution graphics mode, the background color
and palette are selected by the statement COLOR b,p. The statement
"PEEK(1126) AND 15" will have the balue b, and "(PEEK(1126) AND 32)/32"
will have the value p. In text mode, with a color monitor, the value
of "PEEK(1126) MOD 16" will be the border color and "PEEK(1126) AND 16"
will be 16 if the current color was specified by a statement of the
form COLOR f,b in which f is 0 through 15 and b>7.
 
The value of PEEK(1126) will change after appropriate SCREEN or
COLOR statements are executed. However, it is not affected by OUT
statements. Therefore, it will not always reflect the true status of
the monitor unless it is updated after OUTs to port 985.
 
12. In graphics mode, the statement "PRINT CHR$(n)" where n is a
number from 128 to 254, causes the computer to display the character
in an 8 by 8 rectangle of pixels. Each character is described by a
sequence of eight bytes. The eight bytes describing CHR$(128) are
contained in the eight successive memory locations beginning with the
location at offset "PEEK(124)+256*PEEK(125)" in segment "PEEK(126)+
256*PEEK(127)". The pattern for CHR$(129) is contained in the next
eight locations, and so on. To create a character set for ASCII values
from 128 to 254:
a. Select the portion of memory to hold the bytes describing
the characters.
b. POKE the pattern for character 128 into the first eight
memory locations, the pattern for character 129 into the next eight
locations, and so on.
c. POKE the offset and segment of the first byte into
locations 124 to 127.

13. The video parameter table consists of 64 bytes beginning at
memory location of offset "PEEK(116)+256*PEEK(117)" in segment
"PEEK(118)+256*PEEK(119)". The first 16 bytes are numbers that are
OUTed to registers on the color/graphics adapter board when the 40 by
25 text mode is initialized. The next two 16-byte sequences are
associated with the 80 by 25 text and graphics modes on the color/
graphics adapter. The final sequence of 16 bytes is used to initialize
the monochrome display. You must be very careful when changing these
bytes. Certain values for the first 10 bytes in each sequence could
damage your monitor.
 
PRINTER
=========
 
1. The number of printer adapters installed is given by "(PEEK
(1041) AND 192)/64".
 
2. To determine the first port associated with LPTn, "PEEK(1030
+2*n)+256*PEEK(1031+2*n)". If this number is 0, then LPTn is not
available. To swap two printers, interchange their initial port
numbers. Denote the first port associated with LPTn by Pn. The value
of P1 will by 956 if LPT1 is attached to the IBM monochrome display
and parallel printer adapter.
 
3. The ASCII value of the last character sent to the printer by
LPRINT or PRINT# is: INP(Pn).
4. To determine printer status: LET X = INP(Pn+1)
 
X AND 128 has value 128 if the printer is busy or off line
X AND 64 has value 0 if the printer has acknowledged that data has
been sent and is ready to receive more
X AND 32 has value 32 if the printer is out of paper
X AND 16 has value 16 if the printer is on-line
X AND 8 has value 0 if there is an I/O error
 
5. To initialize the printer, send: OUT Pn+2,8:OUT Pn+2,12
 
6. With PCs having 256K RAM motherboards, the parallel printer
timeout values can be read and set. The timeout value for LPTn is
approximately: 1.6*PEEK(1143+n) seconds. To set the timeout value
for LPTn to S seconds: POKE 1143+n,.64*S.
 
DISK DRIVES
=============
1. To determine the number of diskette drives: (PEEK(1040) AND
1)*(1+PEEK(1040)\64).
 
2. In determining the status of a drive motor: PEEK(1087) AND
128 has a value of 128 when a disk drive is being written to, and:
PEEK(1087) AND 15 has a value of 0 when no drive motor is running.
If drive L is running, then the value of "PEEK(1087) AND 2 ^ (ASC
("L")-65)" will be 1. Drive L here is A, B, C or D, and the letter
must be typed in uppercase. These value are not affected if an OUT
was used to turn on the motor.
 
3. To turn on drive L for n seconds, where n is at most 14:
POKE 1088,18.2*n:OUT 1010,2^(ASC("L")-61)+ASC("L")-53. Location 1088
holds the countdown, in clock ticks, until the diskette motor is shut
off.
 
4. To turn off all drives, send: OUT 1010,12
 
5. To determine the diskette track that was last accessed, use:
PEEK(1093).
 
6. To determine which diskette head (0 or 1) was last accessed,
use: PEEK(1094).
 
7. Similarly, to determine which diskette sector was last
accessed: PEEK(1095). When single-sided diskettes are used, items
5, 6 and 7 above may specify the sector following the one most recently
accessed.
 
8. The number of bytes per sector on a diskette is given by:
128*2^PEEK(1096).
 
9. The diskette parameter table consists of 11 bytes. To explore
this: LET D = PEEK(120)+256*PEEK(121). Then, after executing:
DEF SEG = PEEK(122)+256*PEEK(123) you can derive the following table:
(PEEK(D) AND 240)\8 is the time (in milliseconds) required for the
diskette drive to move from track to track
(PEEK(D) AND 15)*32 is the head unload time (in milliseconds) after
a read or write operation has occurred
(PEEK(D+1) AND 240)\4 is the head load time (in milliseconds)
PEEK(D+1) AND 15 is the Direct Memory Access mode
PEEK(D+2) is the wait time until turning the motor off
PEEK(D+3) is the number of bytes per sector on the disk;
a value of v specifies 128*2^v bytes per
sector, for v=0 to 3
PEEK(D+4) is the number of sectors per track, usually
8 or 9
PEEK(D+5) is the gap length (in bytes) between sectors
PEEK(D+6) is the data length that you read out or write
into a sector when the sector length is not
specified
PEEK(D+7) is the gap length used when formatting
PEEK(D+8) is the value the format operation uses to
initialize diskette sectors, usually 256
PEEK(D+9) is the number of milliseconds allowed for the
heads to stabilize
PEEK(D+10) is the number of eighths of a second to allow
for motor startup
 
Changing the values of PEEK(D+3) and PEEK(D+4) can modify the way that
diskettes are read and might require you to format your diskettes
manually.
 
10. The number of hard disks on a PC-XT can be found with:
PEEK(1141).
 
11. If a single diskette drive is used for both drives A: and
B:, its current roles is: CHR$(65 + PEEK(1284))
 
RS-232 INTERFACE
====================
 
1. The number of RS-232 cards attached can be found with:
(PEEK(1041) AND 14)/2
 
2. To determine the first of the seven ports associated with
COMn: PEEK(1022+2*n)+256*PEEK(1023+2*n). If this number is 0, then
COMn is not available. To swap two RS-232 interfaces, interchange
their initial port numbers. Denote the initial port associated with
COMn by Pn. Normally, the value of P1 is 1016 and the value of P2 is
760.
 
3. Interrupt enabling:
OUT Pn+1,1 enables an interrupt when a character has been received
OUT Pn+1,2 enables an interrupt when a character has been transmitted
OUT Pn+1,4 enables an interrupt when an error has occurred
OUT Pn+1,8 enables an interrupt when the modem status has changed
To enable several of the above interrupts at the same time, OUT the
sum of the associated numbers to port Pn+1.
 
4. To identify interrupts, use the port number determined above
(Pn) and: LET X = INP(Pn+2). "X AND 1" has a value of 1 as long as no
interrupts have been issued because of communications port activity.
Similarly, "X AND 6" is used to identify the highest priority interrupt
pending, as indicated in the table "Interrupt Control Functions" in the
IBM Technical Reference manual.
 
5. To establish the number of data bits (d), the number of stop
bits (s), and the parity (p=0 for no parity, p=1 for odd parity, p=3
for even parity), send: OUT Pn+3, d-5 + 4*(s-1) + 8 * p.
 
6. To establish the baud rate: H=INP(Pn+3):OUT Pn+3,H OR 128:
OUT Pn,DL:OUT Pn+1,DH:OUT Pn+3,H. Use values DL=128 and DH=1 for 300
baud, and DL=96 and DH=0 for baud rate 1200. Otherwise, DL=d MOD 256
and DH=d\256, where d is the divisor number given by the IBM Technical
Reference manual in the table "Baud Rate at 1.853 MHz."
 
7. To produce a break signal: X=INP(Pn+3):OUT Pn+3,X OR 64:PLAY
"MF":SOUND 32767,6:SOUND 32767,1:OUT Pn+3,X. The PLAY and SOUND
statements produce a delay of 1/3 second.
 
8. To control the modem, use:
OUT Pn+4,1 to assert that the data terminal is ready (DTR)
OUT Pn+4,2 to raise a request to send (RTS)
OUT Pn+4,16 to perform loopback testing
To accomplish several of the above tasks simultaneously, OUT the sum
of the associated numbers to port Pn+4.
 
9. To determine the status of data transfer, begin with:
LET X = INP(Pn+5). Now:
X AND 64 has a value of 64 if the transmitter shift register is idle
X AND 32 is 32 if the transmitter holding register is ready to
accept a character for transmission
X AND 16 has the value 16 if the received data input is held in the
spacing state too long (that is, if a break was received)
X AND 8 has the value 8 if the received character did not have a
valid stop bit; that is, if a framing error occurred
X AND 4 has the value 4 if the received character does not have
the correct parity
X AND 2 is 2 if the received data destroyed the previous character
(an overrun error)
X AND 1 has value 1 if a character is ready to be read from the
received buffer register
 
10. INP(Pn) will read the ASCII value of a character from the
serial port, provided: (INP(Pn+5) AND 1) = 1
 
11. You can use OUT Pn,m to write the character with ASCII value
m to the serial port, provided that: (INP(Pn+5) AND 32) = 32
 
12. To determine the status of the modem, use: X = INP(Pn+6).
Then:
X AND 128 has the value 128 if a Carrier signal has been detected
X AND 64 is 64 if the modem is ringing
X AND 32 has a value of 32 if the modem has asserted Data Set Ready
X AND 16 is 16 if the modem has asserted Clear to Send
X AND 8 is 8 if the Carrier Detect has changed state
X AND 4 has the value 4 if the Ring Indicator input has changed
from On to Off
X AND 2 is 2 if the Data Set Ready input has changed state since
the last time it was read
X AND 1 has a value of 1 if the Clear to Send input has changed
state since it was last read
 
SPEAKER
==========
 
1. The timer chip determines the frequency of the sound produced
by the speaker. To prepare to send a value to the timer chip, send:
OUT 67,182
 
2. The human ear can perceive sounds varying in frequency from
about 20 to 20,000 Hz. To set the timer chip to produce a frequency
of F Hz: A=INT(1193182/F):H=INT(a/256):L=A-H*256:OUT 66,L:OUT 66,H
 
3. To turn the speaker on, use: OUT 97,INP(97) OR 3
 
4. Conversely, to turn the speaker off: OUT 97,INP(97) AND 252
 
CASETTE PORT CONTROL
======================
 
1. To turn the cassette motor on: OUT 97,INP(97) AND 247
 
2. To turn the cassette motor off: OUT 97,INP(97) OR 8
 
Even if a cassette player is not attached, toggling the cassette motor
produces a clicking sound. Repeated togglings can produce interesting
sound effects, but since the relay involved is not designed as a
musical instrument, excessive use may cause its failure.
 
MISCELLANEOUS
===============
 
1. The number of game adapters attached is shown with: (PEEK
(1041) AND 16)/16
 
2. To find the size of RAM in kilobytes, use: PEEK(1043) +
256*PEEK(1044)
 
3. The internal clock ticks 18.20648 times per second. The
number of ticks that have occurred since midnight is given by:
PEEK(1132)+256*PEEK(1133)+65536PEEK(1134). This value increases until
it reaches 1,533,039 (an instant before midnight), and at midnight it
is reset to 0. The value of PEEK(1136) is increased by 1 as a result
of the reset. Executing either TIME$ or DATE$ changes the value of
PEEK(1136) back to 0.
 
To determine the date N days from now, execute: FOR I=1 TO N:
POKE 1136,1:A$=DATE$:NEXT I:PRINT DATE$. With versions of DOS prior
to 3.0, when N is less than 256, the entire FOR...NEXT loop can be
replaced by POKE 1136,N.
 
4. Memory locations 1264 to 1279 are not used by either DOS or
BASIC. Data can be passed from one program to another by POKEing it
into these locations and PEEKing it later.
 
5. To exit BASIC and complicate reinvoking it, you can: POKE
1295,2:SYSTEM. Memory location 1295 is set to 2 when the BASIC
command SHELL is executed.
 
6. The segment number of BASIC's data segment may be found with:
PEEK(1296)+256*PEEK(1297)
 
7. To disable the nth interrupt: POKE n*4,83:POKE n*4+1,255:
POKE n*4+2,0:POKE n*4+3,240. Prior to executing these statements, use
PEEK to record the contents of the four memory locations. To reenable
the interrupt, use POKE to restore these locations to their original
state.
 
This part of the article is divided into sections that each deal
with the memory locations found in a specified, common segment. When
typing in the applications that follow, you must be careful to execute
the proper DEF SEG statement for each section and to preface each PEEK
with a PRINT statement. The three programs, DEMO1.BAS, DEMO2.BAS and
DEMO3.BAS illustrate many of these applications.
 
BASIC's Data Segment
=======================
 
Prefix with DEF SEG unless otherwise noted
 
The segment of memory that is allocated to BASIC is referred to as
BASIC's Data Segment. When BASIC is first invoked, it is the current
segment. Also, the BASIC statement DEF SEG, when used without any
additional address, specifies this memory segment. BASIC's Data
Segment is partitioned into seven regions. The first of these is the
interpreter work area; the remaining six regions will be referred to
as BASIC's storage area.
 
A. Interpreter Work Area
---------------------------
 
In the following discussion, Classic PCs are the original PCs,
produced in 1981 and 1982, with a maximum of 64K bytes of RAM on the
motherboard. Their ROM chips are usually dated 4/24/81 or 10/19/81.
New PCs consist of all subsequent PCs, including the XT and the AT.
 
1. With a New PC, using BASIC versions 2.0, 2.1 or 3.0, you can
determine the last random number to be generated with
(1+PEEK(11)+256*PEEK(12)+65536*PEEK(13))/2^24
When using a Classic PC or using a New PC with BASIC 3.1, do not add
in the initial number 1. The procedure above assumes that RANDOMIZE
has not been executed since the last random number was generated. On
a New PC, the result will occasionally differ from the actual value of
RND in the last digit. The number 1 was added in the formula for New
PCs to reduce round-off errors.
 
2. To determine the next random number to be generated:
Successive random numbers are generated by a formula involving two
parameters, A# and B#, below. These two numbers vary according to the
type of PC and the version of BASIC. Some combinations are: A# =
214013, B# = 13737667 (a New PC and a version of BASIC prior to 3.1);
A# = 17405, B# = 10395331 (a Classic PC and a version of BASIC prior
to 3.1); A# = 214013, B# = 2531011 (a New PC and BASIC 3.1); and A# =
214013, B# = 10395331 (A Classic PC and BASIC 3.1). The following
program will compute the numbers A# and B# for your particular
configuration. Record the values of A# and B# for future use.
10 POKE 11,0:POKE 12,0:POKE 13,0:T=RND
20 B#=PEEK(11)+256*PEEK(12)+65536#*PEEK(13)
30 POKE 11,1:POKE 12,0:POKE 13,0:T=RND
40 A#=PEEK(11)+256*PEEK(12)+65536#*PEEK(13)-B#
50 PRINT "A# =";A#;"B# =";B#

AT any time, the following program will determine the next random
number to be generated by a Classic PC using any version of BASIC or
a New PC using BASIC 3.1.
10 S#=PEEK(11)+256*PEEK(12)+65536#*PEEK(13)
20 X#=A#*S#+B#
30 T#=X#-2#^24*INT(X#/2#^24)
40 PRINT "The next random number will be";CSNG(T#/2#^24)
 
 
For a New PC and a version of BASIC preceding 3.1, replace lines 10
and 30 with:
10 S#=PEEK(11)+256#*PEEK(12)
30 T#=1+x#-2#^24*INT(X#/2#^24)
 
POKEing numbers into locations 11, 12 and 13 reseeds the random-number
generator.
 
3. PEEK(40) returns the number of the most recent error message.
 
4. Normally, the first 24 lines of the screen scroll as the
screen fills. However, the scrolling portion of the screen can consist
of any rectangular portion beginning on the left side of the screen.
The following statements specify that the scrolling portion of the
screen consists of the first c positions of lines a through b. Once
the cursor has been moved to this region, it will be confined there.
POKE 41,c:POKE 91,a:POKE 92,b
 
To prevent all scrolling, even when characters are PRINTed into the
last line, execute: POKE 92.0. (Be careful to POKE another number
into location 92 before the program terminates.) To scroll all 25
lines, execute: KEY OFF:POKE 92,25
 
5. For the current BASIC line number, PEEK(46)+256*PEEK(47)
 
6. To determine the screen mode,
PEEK(72) = 0 text mode, WIDTH 40, color burst disabled
= 1 text mode, WIDTH 40, color burst enabled
= 2 text mode, WIDTH 80, color burst disabled
= 3 text mode, WIDTH 80, color burst enabled
= 4 medium-resolution graphics, color burst enabled
= 5 medium-resolution graphics, color burst disabled
= 6 high-resolution graphics, color burst disabled
= 7 monochrome display
 
7. To determine the text-mode foreground color, PEEK(75)
 
8. For the text-mode background color, PEEK(76)
 
9. For the text-mode border color, PEEK(77)
 
10. For medium-resolution text color, PEEK(78) AND 3
 
11. To set the text color in medium-resolution graphics mode to
color c of the current palette (c = 1, 2 or 3), POKE 78,c
 
12. For the medium-resolution background color, PEEK(81) AND 15
 
13. For the medium-resolution palette, PEEK(82) MOD 2
 
14. The row number of the cursor is given by, PEEK(86). The
column number is given by, PEEK(87).
 
15. For the WIDTH of each line printed on LPT1, PEEK(98). To set
the WIDTH to w, execute: POKE(98),w.
 
16. The position of the print head within the buffer of LPT1 is
given by: PEEK(99). To move the print head to position n, execute:
PEEK(99),n
 
17. PEEK(100) returns a value of 1 if the cassette motor is off,
0 if the motor is on.
 
18. To determine if the soft keys are displayed on line 25:
PEEK(113) = 0 not displayed
= 1 displayed ever since BASIC was invoked
= 255 displayed as a result of executing KEY ON
 
If the soft keys are displayed and 0 is POKEd into location 113, the
keys will continue to be displayed. However, the combination of LOCATE
and PRINT will be able to display characters on the 25th line, and CLS
will erase the 25th line.
 
19. To determine the exact user response to an INPUT, LINE INPUT,
INPUT#, or LINE INPUT# statement, use:
A$="":N=503:WHILE PEEK(N)<>0:A$=A$+CHR$(PEEK(N)):N=N+1:WEND:? A$
 
(Note: This line must be part of a program. If executed in direct
mode, it will just read itself. While numeric responses are often
rounded, truncated, or converted to floating-point form, the string A$
will consist of the exact digits typed.)
 
20. To show the location of the end of the last statement
executed: PEEK(835)+256*PEEK(836). (Note: This pointer points to
either the null character at the end of a line or to the colon
separating a pair of statements.)
 
21. The memory location pointed to by the BASIC stack pointer is
returned by: PEEK(837)+256*PEEK(838)
 
22. The line number of the last BASIC error is shown by:
PEEK(839)+256*PEEK(840)
 
23. For the location of the program line n specified in an ON
ERROR GOTO n statement: PEEK(845)+256*PEEK(846)
 
24. The segment number of BASIC's Data Segment is returned by:
PEEK(848)+256*PEEK(849). Machine language programs must be POKEd into
an unused portion of memory where they can be CALLed. One safe place
is the segment whose number is 4096 higher than the segment number of
BASIC's Data Segment. The available space can be determined by
executing: DEF SEG=0:PRINT PEEK(1043)+256*PEEK(1044). This returns
the size of the random access memory in kilobytes.
 
25. The memory location (in the text of a program) of the byte
following the most recently READ piece of DATA is shown by:
PEEK(862)+256*PEEK(863)
 
26. The minimum allowable value for array subscripts is at:
PEEK(1116)
 
27. To protect the current program so that it cannot be LISTed
or EDITed: POKE 1125,255
 
28. To determine if the current program is protected: PEEK(1124)
has value 0 if the program is not protected; the message "Illegal
function call" is produced if the program is protected.
 
29. To show the number of files specified by the /F option when
BASIC was invoked, use: PEEK(1247)
 
30. To determine the File Control Blocks: LET X=PEEK(1248) +
256*PEEK(1249). Then the File Control Block for the nth file begins
at the location shown by: PEEK(X+2*n)+256*PEEK(X+2*n+1). Bytes 3
through 13 of the File Control Block contain the name of the file.
The drive containing the file is: CHR$(64+PEEK(2nd location)).
 
31. The disk drive containing the file most recently accessed by
BASIC is: CHR$(64+PEEK(1264))
 
32. The name of the file most recently accessed by BASIC is
given by: FOR I=0 TO 10:PRINT CHR$(PEEK(1265+I));:NEXT I
 
33. For the coordinates of the last point referenced: PEEK(1341)
+256*PEEK(1342) is the x coordinate; PEEK(1339)+256*PEEK(1340) is the
y coordinate.
 
34. To set the coordinates of the last point referenced to (a,b),
use: POKE 1341,a MOD 256:POKE 1342,a\256
POKE 1339,b MOD 256:POKE 1340,b\256
 
35. Strings of up to 15 characters can be assigned to the
function keys with the KEY statement. These strings are stored in the
160 memory locations beginning with the location of offset 1619. Every
16th memory location and the unused locations contain a null character.
You can use this information, in conjunction with redefining the scroll
window, to customize the display that normally occupies the 25th line
of the screen.
 
36. The current color to be used by DRAW statements is returned
by: PEEK(1782) AND 3. To change the color to color c of the current
palette, execute: POKE 1782,85*c. (Note: Any graphics statement
containing a color parameter changes the value of PEEK(1782) AND 3 to
the specified color.)
 
37. BASIC's environment begins at offset 0 in segment ENV, where
the numeric value of ENV can be determined with the following program.
Each equation in the environment is followed by a null character, and
the final equation is followed by two null characters.
10 DEF SEG
20 PSP=PEEK(1794)+256*PEEK(1795) 'Program Segment Prefix
30 DEF SEG=PSP
40 ENV=PEEK(44)+256*PEEK(45)
 
38. The following listing will show the program that was executed
and the options (such as /F:4) that were specified when BASIC was
invoked.
10 DEF SEG
20 PSP=PEEK(1794)+256*PEEK*1795) 'Program Segment Prefix
30 DEF SEG=PSP
40 FOR I=130 TO 129+PEEK(128)
50 PRINT CHR$(PEEK(I));
60 NEXT
 
39. The buffer size for random files specified by the /S option
when BASIC was invoked is returned by: PEEK(N)+256*PEEK(N+1) where
N = 1851, 1854, 1858 and 1858 for BASIC Versions 2.0, 2.1, 3.0, and
3.1, respectively.
 
40. Similarly, for the communications buffer size specified by
the /C: option when BASIC is invoked: PEEK(N)+256*PEEK(N+1) where
N = 1861, 1864, 1868 and 1870 for BASIC Versions 2.0, 2.1, 3.0, and
3.1, respectively.
 
41. To locate the communications buffer in BASICA 2.1:
LET X=PEEK(1866)+256*PEEK(1867) for COM1:
LET X=PEEK(1868)+256*PEEK(1869) for COM2:
The buffer for receiving data when using the Asynchronous
Communications Adapter begins at location PEEK(X+1)+256*PEEK(X+2)
and it ends at PEEK(X+3)+256*PEEK(X+4)-1. The buffer for transmitting
data begins at location PEEK(X+5)+256*PEEK(X+6) and ends at
PEEK(X+7)+256*PEEK(X+8)-1.
The numbers 1866-1869 should be changed to 1863-1866, 1870-1873,
and 1872-1875 for BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
42. The position of the print head within the buffer of LPT2 is
returned by PEEK(N) where N = 1875, 1878, 1882, and 1884 in BASIC
Versions 2.0, 2.1, 3.0, and 3.1, respectively. To move the print head
to position n, execute POKE N,n.
 
43. Similarly, the position of the print head within the buffer
of LPT3 is returned by PEEK(N) where N = 1876, 1879, 1883, and 1885 in
BASIC Versions 2.0, 2.1, 3.0, and 3.1, respectively. To move the print
head to position n, execute POKE N,n.
 
44. For the WIDTH of each line printed by LPT2: PEEK(N) where
N = 1877, 1880, 1884, and 1886 in BASIC Versions 2.0, 2.1, 3.0, and
3.1, respectively. To set the WIDTH to w, execute POKE N,w.
 
45. Similarly, for the WIDTH of each line printed by LPT3:
PEEK(N) where N = 1878, 1881, 1885, and 1887 in BASIC Versions 2.0,
2.1, 3.0, and 3.1, respectively. To set the WIDTH to w, execute
POKE N,w.
 
46. In direct mode, pressing Ctrl-PrtSc causes the printer to
print all output as it appears on the screen. This is referred to as
an echo to the printer. In program (or direct) mode, the statement
POKE N,255 turns on echoing and the statement POKE N,0 turns off
echoing, where N = 1880, 1883, 1887, or 1889 in BASIC Versions 2.0,
2.1, 3.0, or 3.1, respectively.
 
47. To determine the music parameters in BASICA 2.1:
PEEK(2140) has value 0 for the Music Foreground mode and values 1 or
255 for the Music Background mode.
PEEK(2141) is the current octave number.
PEEK(2142) is the current tempo in quarters per minute.
PEEK(2143) is the reciprocal of the length of a standard note.
 
It is set by the statement PLAY "Ln".
PEEK(2145) has the value 1, 2, or 3 to demote Music Legato, Music
Staccato, or Music Normal, respectively.
 
The numbers 2140-2145 should be changed to 2144-2149 and 2149-2154
for BASICA Versions 3.0 and 3.1, respectively. In BASICA Version 2.0,
2141-2145 should be changed to 2136-2140, and 2140 should be changed to
2141.
 
48. PEEK(N) shows the scale to be used by DRAW, where N = 2161,
2163, 2167, and 2172 in BASICA Versions 2.0, 2.1, 3.0, and 3.1,
respectively. To set the scale to n, execute POKE N,n.
 
49. Use the following statements to determine the angle at which
future DRAWings will be turned in BASICA 2.1. (Such angles are set by
the statement DRAW "TA n", where n is the number of degrees in the
angle.)
 
PEEK(2165) is the low byte in the integer representation of n. (Hence,
if n is between 0 and 255 degrees, PEEK(2165)=n.)
CVS(CHR$(PEEK(2166))+CHR$(PEEK(2167))+CHR$(PEEK(2168))+CHR$(PEEK(2169)))
 
is the cosine of the angle n.
CVS(CHR$(PEEK(2170))+CHR$(PEEK(2171))+CHR$(PEEK(2172))+CHR$(PEEK(2173)))
 
is -1/1.2 times the sine of the angle in SCREEN mode 1.
CVS(CHR$(PEEK(2174))+CHR$(PEEK(2175))+CHR$(PEEK(2176))+CHR$(PEEK(2177)))
is 1.2 times the sine of the angle in SCREEN mode 1.
Replace 1.2 with 2.4 for SCREEN mode 2. This information can be
used to compute the cosine and sine of the angle, and hence the value
of the angle.
The numbers 2165-2177 should be chanted to 2163-2175, 2169-2181,
and 2174-2186 for BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
50. To determine status of light-pen trapping in BASICA 2.1, use:
PEEK(2203) = 0 if trapping of light pen is OFF
= 1 if trapping of light pen is ON
= 2 if trapping of light pen is STOPped while OFF
= 3 if trapping of light pen is STOPpen while ON
Activating the light pen causes the program to branch to the program
line stored at location PEEK(2204)+256*PEEK(2205). The numbers 2203-
2205 should be changed to 2201-2203, 2207-2209, and 2212-2214 for
BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
51. To determine the status of key-trapping in BASICA 2.1, use:
PEEK(2203+3*n) = 0 if trapping of key n is OFF
= 1 if trapping of key n is ON
= 2 if trapping of key n is STOPped while OFF
= 3 if trapping of key n is STOPped while ON
Pressing key n causes the program to branch to the program line stored
at location PEEK(2204+3*n)+256*PEEK(2205+3*n). The numbers 2203-2205
should be changed to 2201-2203, 2207-2209, and 2212-2214 for BASICA
Versions 2.0, 3.0, and 3.1, respectively.
 
52. To determine the status of joystick-button trapping in
BASICA 2.1, use:
PEEK(2266+3*n/2) = 0 if trapping of button n is OFF
= 1 if trapping of button n is ON
= 2 if trapping of button n is STOPped while OFF
= 3 if trapping of button n is STOPped while ON
 
Buttons 0 and 4 are the lower and upper buttons of the first joystick,
and buttons 2 and 6 are the lower and upper buttons of the second
joystick. Pressing button n causes the program to branch to the line
stored at location PEEK(2267+3*n/2)+256*PEEK(2268+3*n/2). The numbers
2266-2268 should be changed to 2264-2266, 2270-2272, and 2275-2277 for
BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
53. To determine the status of ON PLAY(n) trapping BASICA 2.1:
PEEK(2278) = 0 if trapping is OFF
= 1 if trapping is ON
= 2 if trapping is STOPped while OFF
= 3 if trapping is STOPped while ON
 
When the changing of the number of notes in the music background buffer
from n to n-1 is trapped, the program branches to the program line
stored at location PEEK(2279)+256*PEEK(2280). The numbers 2278-2280
should be changed to 2276-2278, 2282-2284, and 2287-2289 for BASICA
Versions 2.0, 3.0, and 3.1, respectively. The value of n is PEEK(N),
where N = 2142, 2146, 2150, and 2155 in BASICA Versions 2.0, 2.1, 3.0,
and 3.1, respectively.
 
54. To determine the status of the ON TIMER(n) trapping in
BASICA 2.1:
PEEK(2281) = 0 if trapping is OFF
= 1 if trapping is ON
= 2 if trapping is STOPped while OFF
= 3 if trapping is STOPped while ON
 
The elapsing of n seconds causes the program to branch to the program
line stored at location PEEK(2282)+256*PEEK(2283). The numbers 2281-
2283 should be changed to 2279-2281, 2285-2287, and 2290-2292 for
BASICA Versions 2.0, 3.0, and 3.1, respectively. The value of n is
PEEK(N)+256*PEEK(N+1)+65536*PEEK(N+2), where N = 2145, 2149, 2153, and
2158 in BASICA Versions 2.0, 2.1, 3.0, and 3.1, respectively. At any
time, the number of seconds remaining until a branching occurs is
PEEK(n+3)+256*PEEK(N+4). To induce a branching as soon as possible,
execute POKE N+4,0:POKE N+3,1. (Note: For values of n between 65536
and 86400, the ON TIMER statement causes a branching after just
n-65536 seconds.)
 
55. To determine the keys or key combinations associated with the
user-defined key traps in BASICA Version 2.1: If PEEK(2284)+2*(n-15))=
0, then the key with scan code PEEK(2285+2*(n-15)) is associated with
Fn. (Here n = 15, 16, ....or 20.) Otherwise, the key combination
consisting of one or more latched keys along with the key having scan
code PEEK(2285+2*(n-15)) is associated with Fn. The following table
gives the latched keys included in the combination.
Let L% = PEEK(2284+2*(n-15)).
 
L% AND 3 = 3 Shift key
L% AND 4 = 4 Ctrl key
L% AND 8 = 8 Alt key
L% AND 32 = 32 NumLock key
L% AND 64 = 64 CapsLock key
 
The numbers 2284-2285 should be changed to 2282-2283, 2288-2289, and
2293-2294 for BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
56. To determine the status of a VIEWport in BASICA Versions 2.1:
If PEEK(2323) = 1, a viewport has been established
If PEEK(2324) = 0, then VIEW has been executed
If PEEK(2324) = 1, then VIEW SCREEN has been executed
 
The x coordinates of the points in the viewpoint are stored in the
range from PEEK(2315)+256*PEEK(2316) to PEEK(2317)+256*PEEK(2318), and
the y coordinates range from PEEK(2319)+256*PEEK(2320) to PEEK(2321)+
256*PEEK(2322). The numbers 2315-2324 should be changed to 2313-2322,
2319-2328, and 2324-2333 for BASICA Versions 2.0, 3.0, and 3.1,
respectively.
 
57. In the world coordinate system of BASICA 2.1, PEEK(2359) has
the value 1 if a WINDOW statement has been executed. If so, the
coordinate system is right-handed if PEEK(2360)=0 and left-handed if
PEEK(2360)=1. The x coordinates range from x1 to x2, and the y
coordinates range from y1 to y2, where
x1 = CVS(CHR$(PEEK(2361))+CHR$(PEEK(2362))+CHR$(PEEK(2363))+CHR$
(PEEK(2364)))
y1 = CVS(CHR$(PEEK(2365))+CHR$(PEEK(2366))+CHR$(PEEK(2367))+CHR$
(PEEK(2368)))
x2 = CVS(CHR$(PEEK(2369))+CHR$(PEEK(2370))+CHR$(PEEK(2371))+CHR$
(PEEK(2372)))
y2 = CVS(CHR$(PEEK(2373))+CHR$(PEEK(2374))+CHR$(PEEK(2375))+CHR$
(PEEK(2376)))
 
To return the physical coordinate system: POKE 2359,0. The numbers
2359-2376 should be changed to 2357-2374, 2363-2380, and 2368-2385 for
BASICA Versions 2.0, 3.0, and 3.1, respectively. The world coordinates
can be altered by appropriate POKEing.)
 
58. The music buffer is a circular buffer analagous to the
keyboard buffer. In BASICA 2.1 it consists of the number of bytes
returned by PEEK(2417)+256*PEEK(2418), and it extends from the location
PEEK(2427)+256*PEEK(2428) to the location preceding PEEK(2425)+256*
PEEK(2426). The notes to be played are stored in the bytes extending
from PEEK(2421)+256*PEEK(2422) (the head) to the location preceding
PEEK(2423)+256*PEEK(2424) (the tail), after possibly cycling back to
the beginning of the buffer. Each note is described by 4 bytes. The
 
duration of the note is (256*[1st byte]+[2nd byte])/583 seconds and the
frequency is 596591/(256*[3rd byte]+[4th byte]) Hertz. In Music
Background mode, the number of bytes remaining in the buffer at any
time is given by PEEK(2419)+256*PEEK(2420). (Note: The beginning and
end of the buffer are also given by PEEK(2394)+256*PEEK(2395) and
PEEK(2396)+256*PEEK(2397)).
 
The numbers 2394-2428 should be changed to 2420-2454, 2398-2432,
and 2403-2437 for BASICA Versions 2.0, 3.0, and 3.1, respectively.
 
The music buffer can be enlarged and relocated by POKEing into the
above-mentioned memory locations. The buffer normally holds 32 notes.
The program DEMO1.BAS shows how to create a buffer capable of holding
N = 125 notes. By changing the value of N (which appears twice in the
program), you can create even larger buffers. (Note: In the Music
Normal or Music Staccato modes, the pause between successive notes is
counted as a note.)
 
B. BASIC's Storage Area
----------------------------
 
The six regions in BASIC's storage area hold the text of the
program, the values of the variables, and BASIC's stack.
 
1. The program text begins at PEEK(48)+256*PEEK(49) and ends,
with a terminating null character appended at PEEK(854)+256*PEEK(855).
(Note: The second value will be zero unless requested in direct mode
after the execution of the program. From within the program mode it
can be computed as PEEK(856)+256*PEEK(857)-3.) Key words are
tokenized, and each 2-byte line number is preceeded with the 2-byte
offset of the beginning of the next line.
 
This information can be used to recover a program after NEW has
been executed, provided you know the first line. To illustrate,
suppose that the first line of a program is: 0 REM Can unNEW.
 
This line is stored in 16 bytes: 2 bytes for the pointer to the
location of the next line, 2 bytes for the line number, 1 byte for the
token of REM, 1 byte for the space after REM, 9 bytes for "Can unNEW",
and 1 null byte at the end of the line. To recover the program,
 
a) Execute PRINT PEEK(48)+256*PEEK(49) (This is referred to as
the number X, but be sure not to declare it as a variable, X.)
b) Execute POKE X,(X+16) MOD 256:POKE *x+1,(X+16)\256
c) SAVE the program in ASCII format.
d) LOAD the program.
e) LIST the program. Every line will appear. (Note: As a
precaution against losing a program, then, you can always make the
first line 0 REM Can unNEW. Otherwise, in step (b), replace 16 with
the number of bytes needed to store the first line of your program.)
 
2. Simple variables (that is, all variables except arrays) are
stored beginning at PEEK(856)+256*PEEK(857). This region contains the
values of the numeric variables and pointers to the locations of the
string variables.
 
3. Array variables are stored beginning at PEEK(858)+256*PEEK(859)
 
4. Free space begins at PEEK(860)+256*PEEK(861). New variables
take locations from the beginning of free space and new strings take
locations from the end.
 
5. String space occupies the region extending from PEEK(815)+
256*PEEK(816) to PEEK(778)+256*PEEK(779). New strings are added to
the bottom of string space by taking memory locations from free space.
 
6. The space allocated for BASIC's stack follows the sgring space
and extends to PEEK(44)+256*PEEK(45), the end of the portion of memory
available to BASIC. (Normally, it is the end of BASIC's Data Segment,
but it can be restricted by a CLEAR statement.) At any time, the byte
on the top of the stack is in location PEEK(837)+256*PEEK(838).
 
Monochrome Display
====================
DEF SEG = 45056
The 4000 memory locations at the beginning of segment &HB000
reside on the monochrome display adapter board and hold the contents
of the screen. Each of the following PEEK and POKE statements should
be preceded by DEF SEG = 45056 (or DEF SEG = &HB000). (Caution: The
OUTs discussed in this section might cause physical damage if executed
with a board other than the IBM monochrome display adapter.)
1. To place th
e character having ASCII value n in row r, column c:
POKE 2*(80(r-1)+(c-1)),n
To define the attribute for this character:
POKE 2*(80(r-1)+(c-1))+1,a
where a = 7 when normal (that is, white on black)
= 1 when normal and underlined
= 112 when reverse video (that is, black on white).
Add 8 to each of the first two numbers to obtain high-intensity white
and add 128 to any of the numbers to cause the characters to blink.
(Note: When POKEd, the ASCII values 7, 9, 10, 11, 12, 13, 28, 29, 30,
and 31 produce symbols.)
 
2. To disable blinking: OUT 952,15
 
3. To blank the screen: OUT 952,1
 
4. To restore the screen (and enable blinking): OUT 952,255
 
5. To turn off all but the first n rows of the screen:
OUT 948,6:OUT 949,n
 
Graphics Monitor
==================
 
DEF SEG = 47104
The 16K memory locations at the beginning of segment &HB800 reside
on the color/graphics adapter board and hold the contents of the
screen. The graphics screen has three modes: text, medium-resolution
graphics, and high-resolution graphics. Each of the following PEEK or
POKE statements should be preceded by DEF SEG = 47104 (of DEF SEG =
&HB800). (Caution: The OUTs discussed in this section might cause
physical damage if executed with a board other than the IBM color/
graphics adapter.)
 
A. Text Mode
--------------
 
In text mode (invoked by the statement SCREEN 0), characters can
be displayed in rows of either 40 characters (invoked by the statement
WIDTH 40) or 80 characters (invoked by the statement WIDTH 80).
 
1. To place the character having ASCII value n in row r, column c,
with foreground color f and background color b: POKE a,n:POKE a+1,k
where a = 160*(r-1)+2*(c-1) in WIDTH 80 and = 80*(r-1)+2*(c-1) in WIDTH
40, and where k = 16*b+f if the foreground should not blink and
= 16*b+f+128 if the foreground should blink. The number f ranges from
0 to 15, and b ranges from 0 to 7. (Note: These locations correspond
to page 0. To obtain the analogous results for page p, add p*4096 to a
in WIDTH 80 and add p*2048 to a in WIDTH 40.)
 
2. To disable blinking: OUT 984,8 in width 40
OUT 948,9 in width 80
(Note: With blinking disabled, the number b in item 1 can range from
0 to 15.)
 
3. To blank the screen: OUT 984,32 in width 40
OUT 984,33 in width 80
 
4. To restore the screen: OUT 984,40 width 40, blinking enabled
OUT 984,8 width 40, blinking disabled
OUT 984,41 width 80, blinking enabled
OUT 984,9 width 80, blinking disabled
 
5. To set the border color to d: OUT 985,d
 
6. The color/graphics adapter board contains 16K bytes of memory.
Each pair of locations holds the information for one character. (The
first location holds the ASCII value of the chracter and the second
 
holds the attribute.) Any consecutive block of 2000 (in 40 by 25 mode)
or 4000 pairs (in 80 by 25 mode) can be used to determine the
characters appearing on the screen. To display the characters
determined by pairs N, N+1, N+2, ...:
OUT 980,12:OUT 981,N\256:OUT 980,13:OUT 981,N MOD 256
(To display the pth page in 40 by 25 mode, use N = p*2048. In 80 by 25
mode, use N = p*4096.)
 
B. Medium-Resolution Graphics Mode
--------------------------------------
 
In medium-resolution graphics mode, which is invoked by the
statement SCREEN 1, the screen is partitioned into 320 by 200 pixels.
 
1. To turn on the pixel with coordinates x,y in color c of the
current palette:
Z=40*y+x\4+8152*(y MOD 2):W=2^(6-2*(x MOD 4)):POKE Z,(PEEK(Z) AND
(255-3*W))+c*W
 
2. To use background color c and palette p: OUT 984,c+32*p
The palette colors can be intensified by adding 16 to the number
c+32*p. Therefore, four different palettes are available.
 
3. With an RGB monitor, an undocumented palette (and its
intensified version) is available. To obtain the background color c
and a palette consisting of the colors cyan, red, and white:
OUT 984,46:OUT 985,c
(Note: The palette colors can be intensified by adding 16 to the
number c. Hence, there are actually 6 palettes available with an
RGB monitor.)
 
4. To reverse the foreground and background colors (and
interchange colors 1 and 2 of the palette) on the current display, use:
FOR I% = 0 TO 16191:POKE I%,PEEK(I%) XOR 255:NEXT
(Note: This procedure is sometimes valuable before doing a graphics
dump to the printer.)
 
5. To blank the screen: OUT 984,2
 
6. To restore the screen: OUT 984,10
 
C. High-Resolution Graphics Mode
--------------------------------------
In high-resolution graphics mode (invoked by the statement SCREEN
2), the screen is partitioned into 640 by 200 pixels.
 
1. To turn on the pixel with coordinates x,y:
Z=40y+x\8+8152*(y MOD 2):POKE Z,PEEK(Z) OR 2^(7-x MOD 8)
 
2. To turn off the pixel with coordinates x,y:
Z=40y+x\8+8152*(y MOD 2):POKE Z,PEEK(Z) AND (255-2^(7-x MOD 8))
 
3. To change the foreground color to c: OUT 985,c
(The background color is normally black.)
 
4. To reverse the foreground and background colors of the current
display, use:
FOR I% = 0 TO 16191: POKE I%,PEEK(I%) XOR 255:NEXT
 
5. To blank the screen: OUT 984,18
 
6. To restore the screen: OUT 984,26
 
D. Low-Resolution Graphics Mode
----------------------------------
 
The following programs set up a 160 by 100 pseudo-graphics mode
with background color B.
10 KEY OFF:SCREEN 0,0,0:WIDTH 80
20 OUT 984,9
30 OUT 980,4:OUT 981,127
40 OUT 980,6:OUT 981,100
50 OUT 980,7:OUT 981,112
60 OUT 980,9:OUT 981,1
70 DEF SEG=&HB800
80 FOR I%=0 TO 16382 STEP 2
90 POKE I%,222:POKE I%+1,17*B
100 NEXT
 
Although text cannot be PRINTed and pixels cannot be lit with PSET, the
point with coordinates X,Y can be turned on in any one 16 colors, C, by
executing:
200 S=X AND 1
210 A=160*Y+(X OR 1)
220 POKE A,(PEEK(A) AND (15+S*225))+(C*(16-15*S))
 
E. All Modes
-----------------
 
1. The following program allows a graphics monitor and a
monochrome display to be used at the same time. Suppose that BASIC
is currently writing to the monochrome display. After this program is
executed, data can be PRINTed onto the monochrome display and POKEd
into the color/graphics adapter as in sections A, B, C, and D of the
Graphics Monitor portion of this article.
 
10 FOR R=0 TO 15
20 READ V:OUT 980,R:OUT 981,V
30 NEXT
40 READ M:OUT 984,M
50 DATA 56,40,45,10,127,6,100,112,2,1,6,7,0,0,0,0,42
 
This program results in medium-resolution graphics. To obtain
high-resolution graphics, replace the last number in the DATA statement
with 26. To obtain text mode with 40 characters per line, replace line
50 with:
50 DATA 56,40,45,10,31,6,25,28,2,7,6,7,0,0,0,0,40
 
and to obtain text mode with 80 characters per line, replace line 50:
50 DATA 113,80,90,10,127,6,100,112,2,1,6,7,0,0,0,0,9
 
2. To move the screen horizontally by approximately h characters
from the standard position:
OUT 980,2:OUT 981,45+h in width 40
OUT 980,2:OUT 981,90+h in width 80
(Note: If h is positive, the screen moves left; if h is negative, the
screen moves right.)
 
3. To move the screen vertically by about v pixels or characters
from the standard position:
OUT 980,7:OUT 981,112+v in graphics mode
OUT 980,7:OUT 981,28+v in text mode
 
(NOte: If v is positive, the screen moves up; if v is negative, the
screen moves down.)
 
4. To turn off all but the first n rows of the screen:
OUT 980,6:OUT 981,n
 
5. To decrease the amount of snow on the screen when POKEing
characters or pixels into the screen, precede each POKE (or small
group of POKEs) with:
WHILE 1 AND INP(986):WEND:WHILE NOT(1 AND INP(986)):WEND
 
Read Only Memory
==================
 
DEF SEG = 61440
The following memory locations are part of read only memory (ROM).
Each PEEK in this section should be preceded by DEF SEG = 61440 (or
DEF SEG = &HF000).
 
1. Error messages with numbers ranging from 1 to 30 and 50 to 67
are stored in ROM in the 741 memory locations beginning with the
location at offset 25525. A null character appears at the end of each
message, and question marks serve as place holders for the numbers with
no messages. This information can be used, with ON ERROR and ERR, to
display the nature of an error without first terminating the program
currently in operation.
 
2. The strings that are assigned to the ten function keys when
BASIC is first invoked are stored in ROM in the 71 memory locations
beginning with the location of offset 44269. A null character appears
at the end of each string. This information can be used to restore the
original values to the function keys in the even that reassignments
have been made with the KEY statement.
 
3. To determine possible parameters for BASIC's random number
generator:
PEEK(49771)+256*PEEK(49772)+65536*PEEK(49773)=214013
PEEK(49774)+256*PEEK(49775)+65536*PEEK(49776)=2531011
 
These numbers sometimes serve as parameters for the random number
generator. In particular, they are the values of A# and B# for a New
PC using BASIC 3.1.
 
4. In graphics mode, each character is displayed in an 8 by 8
array of pixels that can be stored as a sequence of 8 bytes. The bytes
for the characters having ASCII values 0 to 127 are stored in the
memory locations having offsets from 64110 to 65113. This information
can be used to write a program that will display characters upside-
down, enlarged, or sideways and to create banners with a printer.
 
5. To obtain the machine part number:
FOR I=57344 TO 57350:PRINT CHR$(PEEK(I));:NEXT I
 
6. To obtain the IBM copyright notice:
FOR I=57352 TO 57365:PRINT CHR$(PEEK(I));:NEXT I
(Note: This information can be used to determine if the computer is an
IBM or an IBM compatible.)
 
7. To obtain the version date of the ROM BIOS:
FOR I=65525 TO 65532:PRINT CHR$(PEEK(I));:NEXT I
(Note: Certain hardware, such as the IBM enhanced graphics monitor, can
be used only if this date is sufficiently recent.)
 
8. To determine the computer being used:
PEEK(65534) = 255 PC
= 254 PC-XT or Portable PC
= 253 PCjr
= 252 PC AT
(Note: The identification numbers of PC compatibles will most likely
differ from these numbers. Some early XTs have a machine ID code of
255.)
Exceptions for the PCjr
The PEEKs, POKEs, INs, and OUTs presented in this article hold
for the IBM PC, XT and AT; however, many of the items do not hold for
the PCjr, such as outs to the color/graphics adapter and the POKEs
that relocate the music buffer. And for non-IBM compatibles, remember
that compatible is as compatible does.
 

Answer 6
~~~~~~~~~
[ von
www.tek-tips.com/ ]
 
What are segments and offsets, PEEK(), POKE and DEF SEG, and how does QB store strings?
Since this post was originally a reply to a question, I'll show the question here too.
Post by: hardcore100110
>This is a sub from a huffman encoder. Buffer$ is a string
> * 10000. My question is I do not know what the code
> following the get statement is doing. It seems to me that
> using the MID$ command is the best way to examine the
> contents of Buffer$.
>
> I guess A& is a memory address and the math is done to
> advance the position correctly? Address = 1:Endaddress=0
>
>
>
> GET #1, , Buffer$
>
> A& = SADD(Buffer$)
> A& = A& - 65536 * (A& < 0)
> BufferSeg = VARSEG(Buffer$) + (A& \ 16)
> Address = (A& MOD 16)
> EndAddress = Address + BufferLength
> DEF SEG = BufferSeg
>
 
My reply:
 
Addresses in memory in real mode (which is the name of the processor mode in which QB, and thus QB programs, execute) are pointed at by overlapping segments & offsets. Segments and offsets are both represented by 16-bit integers, since everything up to the 286 was 16 bits, internally (or less -- but those are sufficiently obsolete by now that we can forget about them). Each segment starts 16 bytes into the previous segment, but you can specify an offset of up to 65535 into any given segment. Since device-mapped memory starts at segment A000h, which is absolute offset A0000h, there are exactly 655360 bytes of addressable memory in pure real mode. This is where the "640K of memory" thing comes from. Basically, memory is one long string of bytes, and the actual address of the byte being referred to is calculated on-the-fly by the processor as (segment * 16 + offset). It is fairly conventional to write segment:offset, in hexadecimal, when referring to a spot in memory. For instance, VGA graphics start at A000:0000, which is device-mapped onto the video card.
 
VARSEG and VARPTR return the segment and offset of a variable's contents, respectively. Strings in QB, however, are prefixed in memory by a descriptor that specifies the length of the string. Thus, VARSEG(stringvariable$):VARPTR(stringvariable$) points at the length of the string. Because they wanted to leave room for expansion of this descriptor, Microsoft made a separate function -- SADD -- that returns the offset of the start of the string. In later versions of QuickBASIC, they take advantage of this small abstraction, and add another function -- SSEG -- that returns the segment of the start of the string. In these versions of QuickBASIC, the header not only contains the length of the string, but it also contains a far pointer (ie, an offset accompanied by a segment) to the string, or an EMS page number, since they support storing strings in EMS.
 
In QB, whenever you use a function that returns a string, it creates a new descriptor & allocates space for the descriptor & the string off of the heap. This means that there is a significant setup overhead when you call, for example, the MID$() function. This overhead is even higher when the string is stored in EMS. PEEK and POKE have virtually no overhead, however. The code for them is actually produced inline with the surrounding code, so no function call is generated. Thus, using PEEK() is far more efficient than using MID$(). The author of that code snippet was obviously programming for efficiency, rather than readability. His code was never intended to be read, but rather to run quickly. What he is doing in this particular snippet is retrieving an absolute address (i.e., number of bytes from start of memory), and converting it into a segment and an offset, which the processor can use to index the memory with. Since PEEK() and POKE take just offsets, not segments, QB needed a way to provide the user with access to the other segments in memory, and this is what DEF SEG does: it stores a segment value somewhere in memory, or in a register, and when PEEK() or POKE is called, it takes that offset into the segment specified by the previous DEF SEG.
 
Note that since segments overlap so much, you can usually take any segment:offset pointer, and add 1 to the segment while subtracting 16 from the offset, or subtract 1 from the segment while adding 16 to the offset. The author here wants to minimize the maximum value of the offset, so he picks the highest possible segment that still contains the first byte of the buffer. This also happens to be the easiest way to do it.
 
 

Answer 7
~~~~~~~~~~~~~~~~~~
[ by -/\lipha (
aliphax*hotmail.com - www.geocities.com/aliphax ) ]
 

PEEK and POKE, an "advance" and "dangerous" topic...
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:
DEF SEG
 
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)
'
CLS
INPUT "Enter in a value: ", value
'
PRINT
PRINT "Byte #", "Value"
'
FOR i = 0 TO 3
PRINT i, PEEK(offset + i)
NEXT i
END
 
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:
 
SCREEN 13
DEF SEG = &HA000
offset = (100 * 320&) + 160 'start at center of screen
col = 15
'
DO
SLEEP
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)
END
 
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.

[ The QBasic-MonsterFAQ --- Start Page: www.antonis.de/faq ]