Jump to content
IGNORED

How to load Assembly routines with Atari Basic.


gs80065xe

Recommended Posts

I'm trying to get back into Atari Basic and 6502 Assembly language. One feature I was already aware of in Atari Basic was calling machine language routines using the USR function. But back in the early 80's I lacked books and magazines which elaborated on how to do this. I've seen some examples in De Re Atari and other sources. But what I haven't figured out is how you translate the Assembly routines into Basic data statements. And Google is not being as friendly with Atari Basic as it is with C# or Java. I've been reading a blog posted in this forum on the topic. But it too shows the Assembly code and the basic code. But I did not see how that assembly code was converted to Basic data statements.

Link to comment
Share on other sites

There's various methods and each has pros and cons.

 

- plain DATA statements. The pro is that small changes to the asm stuff can be made easily. The cons is that a lot of memory is wasted. Additional to where the routine gets POKEd into there's also 2-4 bytes within the data for every byte of the asssembler routine, plus some extra overhead for each program line used and the loop that pokes the routine in. I once did a program that allowed doing hex data which allows for some level of saving there but still it's somewhat wasteful.

 

- storing routines in strings. The pro is that for very small routines that are relocatable, there's no duplication and not much extra overhead. For longer routines it can amount to singly duplicating the data, plus the bit of extra overhead to construct the string from the data. The cons - much harder for small modifications, user unfriendly for type-in programs.

 

- external files. The pro is that the overhead can be kept low. The cons are that the program becomes a bit less "portable" in that you need the program and data file on the same media, e.g. disk image. Also, if it's tape based then you generally want the data to not be erased from memory which in Basic can be tricky at times.

 

For routines under several hundred bytes, generally just easiest to use DATA statements. There's methods of generating them automatically, or just write that part of a program to a seperate file and use the ENTER command to append to your program.

Edited by Rybags
  • Like 3
Link to comment
Share on other sites

Never really liked the idea of embedding machine language in BASIC, seemed a waste of memory having it as data statements and then as code in memory, I understand that some stuff can be done easier in BASIC but may need certain parts to have a bit of ommph to speed it up but I just could not get on with BASIC and jumped in to ML.

 

Shame my maths was so poor then, now I have some more time I've lost the spirit to try again.

Link to comment
Share on other sites

You can combine the various versions for testing and "production", i.e. you can test your code using DATA statements and then write them into a string that takes up less space.

 

Unless you're doing very short routines, it's probably easier to use an assembler or WUDSN to finish the assembler part, write it to a binary file and then read from that binary file and e.g. print into another file with a string which you can then ENTER into your BASIC program.

 

Short routines can be efficiently stored and called with A=USR(ADR("xx$%**"))-like calls which may mess up your listings if they contain unprintable characters, though.

 

BTW and OT, the (much larger) BBC BASIC actually allowed to assemble within BASIC programs. Very cool and definitely a BASIC version that would merit converting to the ATARI.

  • Like 1
Link to comment
Share on other sites

I don't know about the Atari, but on Microsoft BASIC machines I've embedded machine language into strings or REM statements on the first line of code.
Once it's loaded, I can delete the lines with the DATA statements, the lines that read them in, and save it that way.
The one thing I have to be careful of, is the machine language cannot have any zeros in it.
That's the end of line terminator in Microsoft BASIC. If you try to list the program when there is a zero in the string, the machine crashes.

Link to comment
Share on other sites

Short routines can be efficiently stored and called with A=USR(ADR("xx$%**"))-like calls which may mess up your listings if they contain unprintable characters, though.

I used to get around this by replacing unprintable characters ($9B, quotes, etc) with innocuous characters and assigning a variable to the literal string (MC = ADR("code")). I'd then poke the awkward bytes at the appropriate offsets.

Link to comment
Share on other sites

I used to get around this by replacing unprintable characters ($9B, quotes, etc) with innocuous characters and assigning a variable to the literal string (MC = ADR("code")). I'd then poke the awkward bytes at the appropriate offsets.

Yeah, that will work. I guess I was still in Tenliners minimum space mode;)

 

 

Gesendet von iPhone mit Tapatalk

Link to comment
Share on other sites

Never really liked the idea of embedding machine language in BASIC, seemed a waste of memory having it as data statements and then as code in memory, I understand that some stuff can be done easier in BASIC but may need certain parts to have a bit of ommph to speed it up but I just could not get on with BASIC and jumped in to ML.

 

Shame my maths was so poor then, now I have some more time I've lost the spirit to try again.

There were some things that could not be done at all in BASIC, like 'Display List Interrupts', but they only took a few bytes of machine code to implement, so it was worth doing.

  • Like 2
Link to comment
Share on other sites

Thanks for the info guys. I understand I can create the assembly routines. Save them to the file. Then do a binary load to get them in memory before executing the Basic code. But the thing that still alludes me is the Data statements. How do you convert assembly instructions into Basic Data statements to Poke into memory? For example convert *=$0600 or LDX #100 to a Basic data statement.

Link to comment
Share on other sites

Create the binary code

Assemble to a file on disk

in BASIC:

 

10 open #1,4,0,"D:file.ext":get #1,A:?A;" ";:goto 10

 

The shown values of A are the decimal equivalent of the numbers you need to "read" with "data" within BASIC.

 

Don't forget about the PLA rule for X=USR routines...

Edited by Fox-1 / mnx
  • Like 1
Link to comment
Share on other sites

Create the binary code

Assemble to a file on disk

in BASIC:

 

10 open #1,4,0,"D:file.ext":get #1,A:?A;" ";:goto 10

 

The shown values of A are the decimal equivalent of the numbers you need to "read" with "data" within BASIC.

 

Don't forget about the PLA rule for X=USR routines...

And don't forget to strip out the headers from the binary file...

  • Like 1
Link to comment
Share on other sites

There is also one smart possibility.

 

There are tools that allow you to embed a tokenized Atari BASIC program in a binary load file. Assuming you have your machine code in another binary load file, you can just combine these two binary load files in one (the machine code should go first). If you plan your address space usage a little bit (address of your BASIC program vs. address of the machine code), it might work very well. And without those DATA lines.

 

The only disadvantage can be limitations of the embedding tools. Your file might not work with drop-in Atari BASIC replacements, e.g. Altirra BASIC.

One of such tools is the BCOM utility (side A), but there are others.

  • Like 2
Link to comment
Share on other sites

DSPFLG @766 is useful but could be better. Utility of the location IMHO is not brought up enough. It would be better if the native keyboard handler had a hot key sequence to toggle it non zero/zero. Been a while but I recall using it with a short ~5 line BASIC program to store ML and graphics data from disk to BASIC strings.

 

For short ML, I seem to recall you could just press ESC key followed by the key that would normally interact with the full screen editor. i.e. ESC <up arrow> prints an arrow pointed up that will move the cursor up when run from BASIC. I can't remember the limits off hand, something like you still can't use " character but for most functions it works fine. I don't have an emulator installed on the computer I am using at the moment or I would see if I could refresh my memory. :)

Link to comment
Share on other sites

Using DATA lines in Basic programs most often results in the well known starting screen "please wait initializing". And if your Basic program has a lot of Data statements, this can be 1, 2 or 3 minutes of initialization time. Maybe this was okay in the 80s, but nowadays I am not that patient anymore to wait that long for a Basic game to initialize. Therefore I prefer the string method or a faster Basic (e.g. Altirra Basic that loads an Atari Basic game and initializes 50% faster, as long as the game is still playable regarding speed)...

 

Homesoft converted dozens of Basic programs with lots of Data lines (and long init. time) into XEX files that start immediately but still require Basic to run. But I still have hundreds of Basic games in my collection, where I would like to see the Data lines converted into strings for faster (shorter) init. time.

Link to comment
Share on other sites

There is also one smart possibility.

 

There are tools that allow you to embed a tokenized Atari BASIC program in a binary load file. Assuming you have your machine code in another binary load file, you can just combine these two binary load files in one (the machine code should go first). If you plan your address space usage a little bit (address of your BASIC program vs. address of the machine code), it might work very well. And without those DATA lines.

 

The only disadvantage can be limitations of the embedding tools. Your file might not work with drop-in Atari BASIC replacements, e.g. Altirra BASIC.

One of such tools is the BCOM utility (side A), but there are others.

Does an Un-BCOM utility exist?
Link to comment
Share on other sites

Does an Un-BCOM utility exist?

 

I am not aware of such utility.

In most cases, pressing BREAK or RESET and entering SAVE"D:FILENAME.BAS" should do the trick. If the program sets the COLDST to nonzero (a popular "protection" against RESET) then it can be zapped to 0 in an emulator.

 

Link to comment
Share on other sites

Create the binary code

Assemble to a file on disk

in BASIC:

 

10 open #1,4,0,"D:file.ext":get #1,A:?A;" ";:goto 10

 

The shown values of A are the decimal equivalent of the numbers you need to "read" with "data" within BASIC.

 

Don't forget about the PLA rule for X=USR routines...

 

You can also do this in nested loops or with some other constructs to add the line numbers and DATA statements automatically.

 

Assuming you open #1 to read your machine code and #3 to save your data lines you can use something along the lines of :

10 OPEN #1,4,0,"D:MYMLCODE.BIN"
20 OPEN #3,8,0,"D:DATLINES.LST"
30 FOR X = 1000 TO 2000 STEP 100
35 REM ADJUST NUMBERS IN LINE 30 ACC. LINE NUMBERS NEEDED AND NUMBER OF DATA BYTES
40 PRINT #3,X;" DATA ";
50 FOR Y= 1 TO 8
60 GET #1,A
70 PRINT #3,A;
80 IF Y<8 THEN PRINT ",";
90 IF Y=8 THEN PRINT "(ESC)RETURN"
100 NEXT Y
110 NEXT X
120 CLOSE #1: CLOSE #3 

You can then use ENTER "D:DATLINES.LST" to insert the data lines into your program.

You can use the same concept to write to a string using CHR$(A) and adding quotes at the beginning and end with CHR$(34).

 

It never ceases to amaze me how much "self-modification" and "automatic code generation" simple Atari BASIC is capable off. Not really needed here, but with some clever programming you can actually enter automatically generated lines into a running program.

  • Like 1
Link to comment
Share on other sites

There was a common machine routine I used but I don't remember the source. It was short machine language routine that was just a hook into the already existing Atari Serial Input Output routines. It then allowed you to load or save to files using those high speed routines instead of the slow Atari Basic Put/Get commands. I used it in the attached program to load a large picture file and a short assembly routine into memory. Take a look at line 9010 of the attached bas file to see the hook into the Atari SIO routine, and line 9050 makes 2 loads using the hook. Wish I still had the docs for the routine because it also supported save and appends to files but I don't remember the parameters for those. Maybe someone else will be familiar with the routine and it's parameters.

 

Bob

Space Station Multiplication.bas

Space Station Multiplication.atr

  • Like 2
Link to comment
Share on other sites

There was a common machine routine I used but I don't remember the source. It was short machine language routine that was just a hook into the already existing Atari Serial Input Output routines.

iirc, This method relies on the used DOS, usually DOS 2.0 / 2.5.

Link to comment
Share on other sites

Doing a Basic program that brings Binary Load/Xex files into memory is easy and compact but the IO speed will suck. Sadly the XIO statement doesn't work properly either for doing CIO requests with requested buffer address and length.

 

The solution is just read the header segments for start/finish and use a short routine that calls CIO for you, pulling the relevant parameters like buffer length and address from the stack, and return the Y register CIO status on return.

Such a CIO call routine can easily be done relocatable and fit into a string constant, so you'd end up with something like:

 

1000 GET #1,STARTL : GET #1,STARTH : IF STARTL=255 AND STARTH=255 THEN GET #1,STARTL : GET #1,STARTH

1010 GET #1,FINISHL : GET #1,FINISHH : START=STARTL+STARTH*256 : FINISH=FINISHL+FINISHH*256

1020 Y=USR(ADR("hhh* my CIO caller routine"),1,START,FINISH) : IF Z<128 THEN 1000

Link to comment
Share on other sites

The method to choose depends entirely on the program in where it's being used.

 

For just a few bytes, READ/DATA is fine.

If a DOS is required to use the program, prepend the binary to the AUTORUN.SYS that runs the basic program.

When in need for speed, compile the basic to an EXE and prepend your own binary to it.

When using TurboBASIC, use BLOAD. You'll need to load TB with DOS anyways.

Link to comment
Share on other sites

  • 11 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...