Fixing a Bug in Rodnay Zaks' 'Programming the 6502'

preview_player
Показать описание
Rodnay Zaks' "Programming the 6502" is a classic, but it's also got a bug! We take a deep look at the Block Transfer Routine on pages 204-208, find the bug, and then demonstrate and (nearly, see notes below) fix it in Turbo Macro Pro on the C64.

UPDATE! The source in file BLKCPY8 (shown in the video) has a bug, discovered by RETRO Innovations. BLKCPY9 (included in the .d64 linked below) has the fix suggested by csbruce. Also on the .d64, viewer jjeeeekk came up with a faster-running fix which is file BLKCPY11 on the .d64, and also checkout elandje's version which is BLKCPY10.

Index:
0:00 Z80, 6502, and Rodnay Zaks
1:07 Programming the 6502 editions
2:40 A Block Transfer Routine p. 204
4:50 Reading time!
7:46 Looking at the printed source code
14:46 The kind of clever bit - which is the bug!
17:07 Indexed indirect?
23:14 FINALLY THE C64!
24:19 Loading Turbo Macro Pro
27:33 Running the program
30:14 Demonstrating the bug
32:15 Some cleanup
34:35 A fix (of a fix)!
38:08 A couple tests
40:30 Thanks to my patrons
Рекомендации по теме
Комментарии
Автор

Programming manuals need ring binders, without them there's no way to read and type with both hands. Bloody pages flipping over.

willproctor
Автор

Thanks to Retro Innovations for being the first to point out yet another bug in my code shown at the end of the video: if the low byte of the length is 1 (such as a length of $101 bytes) then that last byte won't be copied! The easiest solution (pointed out by csbruce) is to change the last BNE to a JMP. You can find this fix in file BLKCPY9 on the updated .d64 in the description.

Viewer jjeeeekk came up with a faster-running fix which is file BLKCPY11 on the .d64, and also checkout elandje's version (now bugfixed) which is BLKCPY10. Thanks to everyone for their comments.

_Bit
Автор

This brings back memories!. I learned assembler on a BBC Model B using that book!

Doug_in_NC
Автор

When I was in high school (in either 1984 or ‘85), I took a class on the weekends in 6502 assembly at my local community college, and this was what we used as the textbook. I want my money back! :)

DarthEd
Автор

The 32kb limit may have a good reason: You can't copy more than 32kb on an 64kb system without overlap.

Miestroh
Автор

Mr. Zaks was just making sure everyone was paying attention

MS-howq
Автор

I was lucky enough to be given a copy of the third edition of this book back in the 90s by a kind gentleman who used to visit the place I worked. I believe he used to write code for the BBC micro. We must have got talking about 6502 and one day he brought the book in and gave it to me. Sadly, I think he is no longer with us but the book lives on sitting proudly on my shelf.
Anyway, I remember he had highlighted an error so I just grabbed the book and sure enough there is an error on page 24. The second to last example (Negative-Negative) has an incorrect representation of -4. I'm amazed it still wasn't spotted by the third edition!

RobinElvin
Автор

These are so interesting. It's like you were reading my mind and creating these before I even knew I wanted to watch them! This one was very straightforward, and I enjoyed it immensely. Except for a pair of typos on my part, it was very easy to follow and experiment with.

mikegarland
Автор

Thank you, Robin, and Robin's patrons.

eugenetswong
Автор

Fantastic content Robin, thank you as always! This little routine will come in really handy for graphics routines in my program.

ShampooCell
Автор

Until I was about 17 and we got an IBM PC, Rodnay Zaks taught me everything I know about assembly language. I read the first edition front to back, some of it during classes at school. And I probably owe someone an apology for wearing out the covers by carrying it around in my book bag for a few weeks.

JacGoudsmit
Автор

0:56 I used to have that 6502 book.

0:58 Um, that's *_DOCTOR_* Zaks…

9:20 The LDX #BLOCKS is rather buggy. What if you wanted to copy just five bytes? You'd set BLOCKS to 0 and REMAIN to 5, but this code would copy the first block regardless. It's always a good plan to program defensively and handle sizes of 0 (or ≤0 with signed types). It's quite plausible that a calculated size of 0 bytes will be thrown at you at some point.

9:42 I was thinking that the memory-fill routine in your Patreon video the other day looked kind of familiar…

11:42 The copy-block routine could be optimized by unrolling it at last one time over by simply adding a second sequence of « LDA (FROM), Y : STA (TO), Y : DEY » (assuming this loop wasn't erroneously re-used). This would cut the overall cost of the BNE statement in half. It's also worthwhile in a tight loop to consider the cost of spanning page boundaries. The LDA (FROM), Y adds one cycle for crossing into the next page while that's free in the STA (TO), Y instruction. If the "FROM" address is at the start of a page, such as in your example of $1000, there won't be any additional cost.

12:15 I prefer to use operands like "FROM+0" instead of just "FROM" to make it very clear that "FROM" is the low byte of a multi-byte value. This extra clarity doesn't take any extra time or space in the assembled code. The post-increment «INC FROM+1» operation also prepares for the "REMAIN" copy of the last group of <256 bytes.

14:22 I'd go with what "csbruce" says! It's 128 blocks, since if you LDX #128 at the top, the DEX will produce value 127 in the first iteration, which won't trigger the BMI.

15:30 It won't copy the 0-offset byte, but it also WILL copy the byte one location beyond the end of the bytes you want to transfer. E.g., if REMAIN is 5, the code will copy offsets 1 to 5, where you actually want offsets 0 to 4.

A big problem with programming the 6502 is that you need to do clever things with the high and low bytes of 16-bit values to maximize efficiency, but every requirement for cleverness is a pitfall for mistakes.

18:05 LDX #0 : LDA (zp, X) could be used as a substitute for LDY #0 : LDA (zp), Y if the Y register were needed for something else.

22:52 That's not quite right. .X will be decremented into negative numbers twice, to 255 (-1) after entering from the «LDX #BLOCKS» portion, and then to 254 (-2) after entering from the «LDY #REMAIN» portion, since .X isn't altered for the sub-page copying.

24:20 Should they really call their program "TMP"? Someone might just delete that "temporary file" when tidying up!

28:32 I like using $CB…

31:08 It might have been better for demonstration purposes to copy the memory block to the screen RAM.

36:35 It would probably be better not to try to re-use the full-page loop and have a separate LDA/STA loop for sub-page copying. This way, the full-page loop doesn't need an extra CPY instruction and can easily be unrolled, and the bulk of a big copy won't be slowed down.

csbruce
Автор

@5:06 Well, if you know your value will never be zero, you can use 8 bits to represent 1-256...

KurtRichterCISSP
Автор

This is the book i went with when I was learning assembly a few years ago. I liked the cover more than the alternatives so i bought it. Glad i did.

KubuntuYou
Автор

I just happened to find this book at a thrift store in in Albany, CA the day after this was posted. I bought it on the spot.

bryanday
Автор

The books that I learned the most from were also the ones with the most errors (especially Amiga Machine Language from Abacus). After typing in the code you're wondering why it doesn't work, until at some point you realize the book has a mistake in it and you have to figure out by yourself how to fix it. That's much more instructive than just reading. I've considered writing a book that does this on purpose.

matthijsh
Автор

I literally woke up to the digital age with Sybex books in the 80-ties

professortrog
Автор

You can't copy more than 32K on a 6502 unless the source and destination overlap. If the block is over 32K, then the size of the source plus the size of the destination is greater than the entire memory space of the 6502.

BFLmouse
Автор

I have the 6502 book, but trying to find his Z80 book in the uk below £100 is not easy, some are close to £300 :(

leesmithsworkshop
Автор

Very interesting! But I found the fix a little bit boring. I would like to know if there is a way to reuse the block loop for the remainder without a performance penalty. But the ideas I came up with need more additional code than just using a separate loop for the remainder... So I suppose csbruce is right, just using a separate loop for the remainder is best since it also leaves the option open to optimize the block loop via unrolling.

Still, for a generic copy function this code is still not complete (or dare I say "buggy"?): because the source and target ranges may overlap the program needs to choose the best method (wether to copy in a decrementing or incrementing fashion) accordingly.

bitti
welcome to shbcf.ru