Jump to content
IGNORED

kenjennings' Blog - Part 5 of 11 -- Simple Assembly for Atari BASIC


RSS Bot

Recommended Posts

DPOKE

Writing a two-byte, 16-bit value (DPOKE) goes hand-in-hand with reading (DPEEK). An 8-bit computer environment has many opportunities for managing 16-bit address and the Atari environment is no exception. Address of display lists, Address of screen memory. Numerous buffers and pointers. Address pointers abound.

OSS BASIC XL provides the DPOKE command to perform a 16-bit, two-byte write to a specified memory location. Like DPEEK, this can be duplicated in regular Atari BASIC, although much slower. So, in BASIC XL the action:

Dpoke Address, Value


is frequently seen in Atari BASIC programs expressed as:

POKE ADDRESS, VALUE - INT( VALUE / 256 ) * 256
POKE ADDRESS + 1, INT( VALUE / 256 )


That’s a bit more complicated than DPEEK. Here the value must be broken down into the high byte (integer result of the value divided by 256) and the low byte (the remainder after division), and then the two values assigned to the two consecutive bytes in memory in low byte, high byte order. This can also be worked into a reusable subroutine in Atari BASIC:
  
This is still fairly simple code. A small difference here is the high byte is calculated and retained to avoid multiple occurrences of the same floating point division. But, again, expressed in Atari BASIC this is fairly slow using one floating point division and one multiplication. As before, applying assembly language rocketry yields:

DPOKE in Mac/65 Assembler Code
The error detection and handling have a few differences from DPEEK.  The DPOKE routine does not inherently require a response value where DPEEK does, so the DPOKE code does not have separate, early-exit code and uses only one place to set the response value merely to indicate general success or failure.

This code uses an additional Page Zero value to accept the value to write to the address:
  
The real work part of the code is obviously different since writing bytes into memory (DPOKE) is not the same as reading bytes from memory (DPEEK):
The DPOKE version above conforms to my standard plan (more or less) for stack management and error handling.  Most of the remaining utilities will stick with this plan.

However, for the sake of (averting) argument there are admittedly more optimal ways to accomplish this depending on the programmer's definition of optimal. For instance, the value to write to the address need not be temporarily stored in Page Zero. After the code pulls the target address from the stack and establishes it in Page Zero it could pull the value and directly store it to the target address, like this:
  
That does look clever as it subtracts two bytes from the code, and removes ZVAL from Page Zero. However, to make this work the argument handling must be different to pull two, not four bytes worth of arguments, and the Y value must be reset to 1 before arriving at this code, and the error return value needs to be reworked. In other words, the code savings in one place may be consumed by code needed in another place.

The standardized approach may not be the most optimal, but it is conceptually consistent, flexible, and doesn't need to be re-factored from scratch for each different routine. Also, regardless of the degree of inefficiency in this less-than-optimal method the execution time is negligible compared to slower Atari BASIC. More time is spent by Atari BASIC converting the floating point values into 16-bit integers to pass as arguments to the machine language routine than the amount of time for execution of the the machine language routine.


Testing DPEEK and DPOKE

The Atari BASIC program below, TESTDPK.BAS, demonstrates how to load the machine language routines into strings and it tests the two routines:
 "*** DPOKE ***"300 ? "10 + 256 * 68 = ";10+256*68310 CL=PEEK(711)+256*PEEK(712)320 ? "BASIC After Dpoke = ";CL330 CL=0340 CL=USR(DPEEK,711)350 ? "USR() After Dpoke = ";CL360 END970 REM980 REM DPEEK AND DPOKE990 REM10000 DIM DPE$(36),DPO$(38)10001 DPEEK=ADR(DPE$):DPOKE=ADR(DPO$)10010 RESTORE 2700010011 FOR I=0 TO 3510100 READ D:POKE DPEEK+I,D10101 NEXT I10110 FOR I=0 TO 3610111 READ D:POKE DPOKE+I,D11000 NEXT I11001 RETURN28000 REM dpeek.obj27000 DATA 104,168,240,10,10,168,201,227010 DATA 240,9,104,136,208,252,132,21227020 DATA 132,213,96,104,153,213,0,13627030 DATA 208,249,177,214,133,212,200,17727040 DATA 214,133,213,9629000 REM dpoke.obj29000 DATA 104,168,240,28,10,168,201,429001 DATA 240,6,104,136,208,252,240,1629002 DATA 104,153,213,0,136,208,249,16529003 DATA 214,145,216,200,165,215,145,21629004 DATA 132,212,132,213,96

First the program performs DPEEK the slow way in BASIC by calculating the 16-bit address of the display list (at locations 560 and 561) with a multiply in BASIC (line 160). Then the program performs the same action using the DPEEK USR() routine (line 190). The value determined by each method is displayed for comparison:



Next the program tests the DPOKE USR() routine by assigning a 16-bit value to locations 711 and 712. First it calculates the 16-bit value and reports it. Then it performs DPOKE via the USR() routine (Line 250). Then it retrieves the contents of the two memory locations by the slower BASIC method for DPEEK and by the DPEEK USR() routine. Finally, it reports the value determined by each method to verify the value was written to memory correctly:




Below are the source files and examples of how to load the machine language routine into BASIC included in the disk image and archive:


DPOKE File List:


DPOKE.M65 Saved Mac/65 source
DPOKE.L65 Mac/65 source listing
DPOKE.T65 Mac/65 source listed to H6: (linux)
DPOKE.ASM Mac/65 assembly listing
DPOKE.TSM Mac/65 assembly listing to H6: (linux)
DPOKE.OBJ Mac/65 assembled machine language program (with load segments)
DPOKE.BIN Assembled machine language program without load segments
DPOKE.LIS LISTed DATA statements for DPOKE.BIN routine.
DPOKE.TLS LISTed DATA statements for DPOKE.BIN routine to H6: (linux)


MAKEDPOK.BAS BASIC program to create the DPOKE.BIN file. This also contains the DPOKE routine in DATA statements.
MAKEDPOK.LIS LISTed version of MKDPOKE.BAS
MAKEDPOK.TLS LISTed version of MKDPOKE.BAS to H6: (linux)

TESTDPK.BAS BASIC program that tests the DPEEK and DPOKE USR() routines.
TESTDPK.LIS LISTed version of TESTDPK.BAS.
TESTDPK.TLS LISTed version of TESTDPK.BAS to H6: (linux)



ZIP archive of files:




Tar archive of files (remove the .zip after download)





For we are his workmanship, created in Christ Jesus for good works, which God prepared beforehand, that we should walk in them.
Ephesians 2:10

Attached thumbnail(s)
  • blogentry-32235-0-29368800-1469492439.pn
  • blogentry-32235-0-35702600-1469492459.pn
Attached File(s)


http://atariage.com/forums/blog/576/entry-13180-part-5-of-11-simple-assembly-for-atari-basic/
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

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