Starting addr for .prgs

Basic and Machine Language

Moderator: Moderators

Post Reply
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Starting addr for .prgs

Post by Bobbi »

This seems like a stupid / simple question, but I figured I may as well ask the wise folk here.

When I download cartridge images from zimmers, they usually autostart. With other random .prgs, I know the loading address from the first two bytes, but is there some convention for the entry point? I can load the .prgs in the Vice monitor but I need to know the address to jump to with the 'g nnnn' command or 'SYS nnnnn' from BASIC.

For example I have been trying to run PractiCalc. How do I find the start address?
User avatar
srowe
Vic 20 Scientist
Posts: 1325
Joined: Mon Jun 16, 2014 3:19 pm

Re: Starting addr for .prgs

Post by srowe »

For .PRG files the start address is the first two bytes, byte 0 is the least significant, byte 1 the most significant.
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

That's what I thought. That is also the address used by the Vice monitor 'load' command as the load address if not specified manually.

However if I run from the Vice load address, it doesn't work. (It does work with my self-developed program file, where I know the starting address is the load address though!)

eg: (in Vice monitor)

Code: Select all

l "foo.prg" 0
Loading foo.prg from 1200 to 12ff (255 bytes)
r 1200  <--- DOESN'T WORK
r 1201 <-- ALSO NO GOOD
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

I am trying to run Practicalc.prg (the spreadsheet program.)
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Starting addr for .prgs

Post by Mike »

BASIC programs and machine code programs with a BASIC stub (which shows up as a single line with a SYS statement, when LISTed) are usually started with the RUN command. :)

This also works with PractiCalc. :mrgreen:

...

Normally you'd only ever use ",8,1" with "pure" machine code programs, i.e. those without a BASIC stub. In that case, their start address most often is (but not necessarily needs to be) also the address they are loaded to. As mentioned earlier in this thread, the first two bytes of a PRG file define the load address.

When you have loaded such a file with ",8,1", it is best to first issue a NEW afterwards, because some address pointers of the BASIC interpreter have been dislocated. *) This especially applies to programs loaded to higher addresses (like BLK5 for soft-loaded cartridges). Then, a SYS command starts the program.

As it's rather difficult the remember all those SYS addresses for pure machine code programs, people went and transformed those into machine code programs with BASIC stubs. In those cases, they can be loaded like a normal BASIC program and started with the RUN command. The single line SYS statement then either executes the machine program in place, or a small routine first installs the payload at the intended place in RAM and then calls it there.

You should be aware though, that even though you can omit the ",1" (load absolute) of the ",8,1" in that case, and just load ",8" (load relative), the VIC-20 has the peculiarity that it changes the start address for BASIC programs with different RAM expansions (i.e., unexpanded, +3K and >= +8K have a different start address for BASIC). That means you'll have to set the exact necessary RAM size for those type of programs, otherwise they won't run - 65xx code is not relocatable, and the SYS anyway will still point to the old, correct address. Changing the SYS address accordingly is of no use either, as - once again - 65xx code won't run at a wrong address.

See also the two threads: RAM... what to get? and ML code memory area, and to quote from the latter:
Mike wrote:What you shouldn't do is, assemble a piece of machine code directly at the start of BASIC (i.e. to $1001 on unexpanded VIC-20, for example). If that code is loaded, the BASIC interpreter assumes, that it is a BASIC program and will invoke the line relinker, which will inevitably change your code quite unexpectedly or even will crash: see here.
Greetings,

Michael


*) the NEW can be omitted, if you're only going to run the machine code program itself. If you however intend to use it alongside a BASIC program, the NEW is necessary, otherwise you'll be greeted by ?OUT OF MEMORY error messages at times or some other undefined behaviour.
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

Ah I hadn't thought about a BASIC stub. Makes sense though!
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

Awesome ... thank you! Armed with this information I can now run everything on zimmers :)

I guess I should work out how to add a tiny BASIC stub to my pure machine code program so it is more convenient to start!
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Starting addr for .prgs

Post by Mike »

Well, here's how I would go about to construct a BASIC stub for an empty machine code program with the VICE monitor:

- This assumes a RAM expansion >= +8K, with BASIC starting at address $1201,
- enter the VICE monitor,
- enter f 1203 7fff 2a
- this fills the entire BASIC RAM (except the empty BASIC program) with a non-0 character that's easily recognizable,
- return to the emulation with x,
- enter the line "2016 SYS XXXX" (without the enclosing quotes, and with SPACEs before and after SYS),
- to replace the X's with the correct start address, we'll enter the monitor again and take a look at the memory with m 1200 120f:

Code: Select all

>C:1200  00 0c 12 e0  07 9e 20 58   ...... X
>C:1208  58 58 58 00  00 00 2a 2a   XXX...**
$1200: this is initialised to 0 by the BASIC interpreter beforehand, and is *not* part of the program!
$1201..$1202: start of the first line - contains a link pointer to the next line at $120c
$1203..$1204: the line number. $07E0 = 2016 to indicate the year when the program was written. ;)
$1205: $9E: the token for the SYS statement. Note the SPACE between line number and SYS is not stored. It's rather automatically inserted when LISTed again!
$1206: $20: the SPACE inserted on purpose so there's a more eye-pleasing layout. :)
$1207..$120A: the placeholders for the correct start address,
$120B: a 0-byte signifying the end of line,
$120C..$120D: the link pointer of the second line. It's a NULL pointer actually, and this signifies the end of program.

That means we can store the machine program beginning at $120E = 4622. This is $34 $36 $32 $32 in PETSCII.

The X's are now replaced with: >1207 34 36 32 32

As seen with m 1200 120f:

Code: Select all

>C:1200  00 0c 12 e0  07 9e 20 34   ...... 4
>C:1208  36 32 32 00  00 00 2a 2a   622...**
Now for the empty machine code program:

Code: Select all

a 120e rts
Leave the prompt .120f with enter.

The whole program, including the RTS, is then saved with save "empty.prg" 0 $1201 $120E to the currently mounted directory. Note (once again) the 0-byte before the BASIC start in $1200 is not part of the program, and thus also not saved!

When you examine the file, you'll see the VICE monitor correctly prepends the load address as $01 $12 ^= $1201. This would also happen if you'd store a BASIC program with the SAVE command. However, the BASIC interpreter currently knows nothing about the extra data stored behind the BASIC program and would leave it out with SAVE, and that's why we need to use the VICE monitor save command at this time.

Upon return to the emulation, you can LIST up the program which shows the BASIC stub as "2016 SYS 4622" (as was intended), and you can RUN the program, and it will successfully do - nothing! :mrgreen:

Cheers,

Michael

P.S. unfortunately, a posting in the General section won't allow for attachments. Could a mod please move the thread to the Programming section? (Edit: Thanks!)

P.P.S. empty.prg attached as *.zip, as *.prg files still are not allowed as attachments...

P.P.P.S. the monitor of VICE takes the actual end address of the memory range with the save command. Many native monitors expect you to supply the end address + 1!
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

Thank you so much for that Mike!

I had began to piece together the ideas by entering a one line BASIC program (10 SYS 1234) and looking at the corresponding bytes in Vice.

However you saved me having to work out all the details!!
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Re: Starting addr for .prgs

Post by Boray »

PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
Bobbi
Vic 20 Afficionado
Posts: 355
Joined: Thu Oct 13, 2016 11:35 am
Location: Toronto
Occupation: Programmer

Re: Starting addr for .prgs

Post by Bobbi »

Added a BASIC stub loader to my work-in-progress assembly language program. Worked first time!

Many thanks Mike!!
Post Reply