General Category > Programming

BASIC programming tips

(1/28) > >>

arnoldemu:
Here are some tips to help with BASIC coding.
If anyone has anymore, please add them and I'll compile a doc for the wiki to help those who want to program in BASIC.

------
A BASIC program to load a binary file

The simplest method to load a executable binary file using BASIC is:

10 memory <addr>-1
20 load"<filename>",<addr>
30 call <execution address>

where <addr> is the load address of the binary file, <filename> is the name of the binary file and <execution address> is the address to start the program from. e.g.

10 memory &1fff
20 load"demo.bin",&2000
30 call &3a56

Here, "demo.bin" is a binary file starting at &2000 with a execution address of &3a56.

If the code above is used, the minimum memory address that the file can be loaded to is &1173, without the "Memory full" error.

The above program can be improved to allow for a lower minimum memory address:

10 openout"d"
20 memory <addr>-1
20 closeout
30 load"<filename>",<addr>
40 call <execution address>

The minimum memory address now becomes &1a0.

NOTE:

    * The name of the file in line 10 can be anything. It is never written, and the above program will function on a write protected disc

The main advantage of a BASIC program to load a binary file is:

    * If a executable binary program is RUN directly: e.g.

      RUN"demo.bin"

      Then it will be started with the firmware function "MC BOOT PROGRAM". This will reset the state of the firmware and disable the disc operating system. Therefore the selected drive and other disc operating system variables are lost.

------
A HEX loader

This document describes various methods to poke a binary program into RAM using a BASIC program.

10 addr=&4000
20 read a$
30 if a$="*" then goto 70
40 poke addr,val("&"+a$)
50 addr=addr+1
60 goto 20
70 call &4000
80 data 3e,3a,cd,5a,bb,c9,*

Line 10 defines the start address (&4000) to poke the data to. Line 20 reads a string from the current data position. Line 30 tests to see if the string is the end of data marker Line 40 converts the string to a hexidecimal value which is poked into the memory address referenced by the "addr" variable. Line 50 increments the "addr" variable, so that the next byte is poked after the previous byte. Line 60 loops back to continue reading data. Line 70 executes the program Line 80 contains the data of the program

10 for addr=&4000 to &4006
20 read a%
30 poke addr,a%
40 next
50 call &4000
60 data &3e,&3a,&cd,&5a,&bb,&c9

Line 10 defines a loop for the entire range of the binary data. Line 20 reads a number from the current data position. Line 30 pokes the number to the destination RAM address. Line 50 executes the program Line 60 contains the data of the program.

------
Anthony Jordon writes:

Here's a little teaser for your CPC brain cells.

The short routine below (which could be part of a longer program) will display on the screen the highest line number of the program currently in memory.  Can you work out how it does it?

10 REM Last
30 last%=0
40 CALL &BFFE-35, &C970,&2371,&166,&DD00,&6EDD,&ED18,&4623,&4E23,&23EB,&19EB,&A28
,&B37A,&2B56,&235E,&EB00,&1,&170,&1100,@last%
50 PRINT last%

Executioner: Yes, it places the parameters on the stack which are opcodes for the routine below, then executes the code on the stack:

.at_last
dw #01ff
db 0

.start
ld de,#0170
ld bc,#0000

.loop1
ex de,hl
ld e,(hl)
inc hl
ld d,(hl)
dec hl
ld a,d
or e
jr z,exit
ex de,hl
add hl,de
ex de,hl
inc hl
inc hl
ld c,(hl)
inc hl
ld b,(hl)
jr loop

.exit
ld l,(ix+#00)
ld h,(ix+#01)
ld (hl),c
inc hl
ld (hl),b
ret

AJ: The hex values are basically just the machine code in reverse byte order.

For more details see my article in WACCI June 1994 Issue 79 page 17.

KT: Essentially it is a way to embed small binary programs inside basic without using a data statement to poke them. The values after the call are the 16-bit numbers to poke onto the stack and are poked from left to right, but because they are put on the stack the last number ends up being on the top of the stack. Note how the 16-bit values are two opcode bytes together and are the opcodes of the function. Then the CALL executes them on the stack. BFFE is the base of the stack in BASIC, and -35 is the length of the program.

-----------

Probably an old one:
POKE 370,0 hides first line number in BASIC
POKE the other line numbers also to 0 can hide a complete BASIC program.
(GOTO / GOSUB will not work then)

You can also reverse line numbers in listing like:
20 PRINT"HELLO"
10 GOTO 20

Play around with PEEKs and POKEs
-----------
 
- BASIC puts a limit on the number of parameters to a RSX (|) command to 32.

- RSX/CALL parameters are put onto the stack, this explains why you access them in reverse order compared to how they are written in the BASIC program.
-----------
Put setup code in a seperate loader program (e.g. font setup).
-----------
RAM available to BASIC.
RAM is available from the end of the BASIC program up to HIMEM-1.
You can find HIMEM with
PRINT HIMEM
HIMEM is also defined using MEMORY command.
The following effect the amount of RAM basic can use:
- expansion roms that are connected
- using MEMORY
- using SYMBOL AFTER to define a font
- variables defined in BASIC program
-----------
Finding the memory address of a BASIC variable.
PRINT HEX$(@<var name)
e.g.
PRINT HEX$(@a%)
For strings this actually points to a "string descriptor block" which is 3 bytes long. The first byte is the length of the string.
The 2nd and 3rd bytes are the memory address of the string itself.
-----------
MEMORY command
This sets the upper limit for BASIC. After this address you can store binary code and data safely. Basic will not overwrite it.
The upper limit is now dependant on the roms that have been installed. Around &a600 is normal.
You can find this upper limit by checking HIMEM before you modify it.
NOTE: If you define a font and then change MEMORY the font will still be in it's original position and could be overwritten.
Read how to relocate the font.
-----------
Moving the font in memory:
SYMBOL AFTER 256
MEMORY <address>
SYMBOL AFTER 32
If it tells you "Out of memory" then you need to increase HIMEM.
The font ends at HIMEM.
The size of the font can be worked out as follows:
If you entered SYMBOL AFTER n:
Size of font = (256-n)*8
So font will start at HIMEM-Size of font and end at HIMEM.
The first line "SYMBOL AFTER 256" will clear all defined chars. By default BASIC is initialised with "SYMBOL AFTER 240", and attempting to do this:
MEMORY <address>
SYMBOL AFTER 32
will give an "Improper argument" error.
Then you relocate HIMEM, then you tell it the chars you want to modify.s

Gryzor:
Hmmmm if this expands it would make a nice wiki article... Want me to make this a sticky topic?

arnoldemu:

--- Quote from: Gryzor on 12:48, 14 June 09 ---Hmmmm if this expands it would make a nice wiki article... Want me to make this a sticky topic?

--- End quote ---
yes.

More:

- BASIC puts a limit on the number of parameters to a RSX (|) command to 32.

- RSX/CALL parameters are put onto the stack, this explains why you access them in reverse order compared to how they are written in the BASIC program.

Gryzor:
Made sticky, thanks for your input. But I think it'd be better if one post only (the first one) is updated with new info instead of adding new posts?

Devilmarkus:
Probably an old one:
POKE 370,0 hides first line number in BASIC
POKE the other line numbers also to 0 can hide a complete BASIC program.
(GOTO / GOSUB will not work then)

You can also reverse line numbers in listing like:
20 PRINT"HELLO"
10 GOTO 20

Play around with PEEKs and POKEs  ;)

Navigation

[0] Message Index

[#] Next page

Go to full version
Powered by SMFPacks Media Embedder
Powered by SMFPacks Alerts Pro Mod
Powered by SMFPacks Mentions Pro Mod