Translated and optimized for the Scenix SX by James Newton. Bug fix by Ted Inoue.
From Scott Dattalo
Please read the entire page before you use this code!
;inc dec high ;ERROR! Read below.. incsz low inc high ;ERROR! Read below.. A downcounting version; ;dec test low snz dec high dec low
Comments:
James Newton responds: "I have no idea how I managed to screw that up when I translated it from the original for the PIC at http://www.piclist.com/techref/microchip/math/incdec/best16.htm which matches your code. Must have been a moment of brain drain.
Yes, almost all of the code has been tested. But the human mind is not immune
from error. That is part of the point of this
Massmind web site. We can all share
and help each other catch our errors. I wonder how many people have used
that bad code, found the error and corrected it without using the form at
the bottom of this page to post a correction or even a warning. Thank you
very much for takeing the time to contribute the corrected code.
;inc dec high incsz low inc high
However, the first and last lines should have the opposite operations applied. In other words, it should look like this:
;inc inc high incsz low dec high
It's really frustrating to find a page that talks about a piece of broken code that was fixed but which still has the bug in it. Furthermore, while we're on this page, how about commenting the code so it teaches beginners better? I suggest the following verbosity:
; HOW THIS FUNCTION WORKS: ; A 16 bit variable is stored as two bytes in memory. In this case ; they are called "high" (for the high byte of the 16 bit word) and ; "low" for the low byte. ; In a 16 bit increment, we want to increment the low byte every time, ; but ONLY increment the high byte when the low wraps around from 255 ; back to 0. This function works by ALWAYS incrementing the high byte, ; followed by incrementing the low byte. Normally, the next instruction ; then decrements the high byte back to where it was originally. However, ; when the low byte wraps to zero, it sets the "zero" flag, and the instruction ; to "fix" the high byte is skipped. Since the first instruction already incremented ; the high byte, it is at the correct value, and the entire 16 bit word is correct. ;inc inc high ;Assume the low byte will wrap back to 0 incsz low ;Increment the low byte? Did it wrap? dec high ;No, so fix the high byte value ; The 16 bite decrement also needs to affect the high byte ONLY when the low ; byte wraps from 0 to 255. In this case, we check if the low byte is already ; at 0. If it is, then we decrement the high byte, followed by the decrementing the ; low byte. If the low byte is at any value other than zero, we simply decrement ; the low byte. ;dec test low ; Is the low byte at zero? snz ;If not, skip the next instruction dec high ; Low byte is zero, so dec the high byte dec low ; We always dec the low byte
At the very least, I suggest leaving the code comments I added so that programmers can read the intent of the code instead of playing human assembler.
James Newton responds: "Again, thank you for taking the time to share your version. I would like to note that the version you found and realized was incorrect is the original version and NOT the version that Ted fixed. I've added a comment to the original code so that future users will be less likely to miss this. I do NOT want to correct the original error as I think this serves as a good example of both the strengths and weakness of open source and code shareing."