If you have Computer One Forth (release 2.0), you need this :
Code: Select all
.( tests and patch for some bugs in ComputerOne FORTH rel 2.0 )
hex
: PATCH
671A 0684 ! 3400 0688 ! B342 068C ! 6A0C 068E ! 4A41 0690 !
6708 0692 ! D240 0694 ! 4841 0696 ! 5341 0698 ! 4841 069C !
4E75 069E ! 0A56 09F8 ! FFFF 09FA ! 60B0 09FC ! D1B5 0DFC ! ;
decimal
: /mod. 8 -8 do i . i over /mod . . cr loop drop ;
: not0=. 8 -8 BINARY do i u. i not u. i 0= u. cr loop DECIMAL ;
Comments (do not compile this !) :
you may use the test words /mod. and not0=. before and after
using PATCH ; this way :
n /mod. (n a one digit integer) will give a list of quotients
and remainders, and before PATCHing you will notice irregular
behaviour of the flooring around 0 (zero). This bug is serious
not0=. (nothing on the stack is needed) will show that before
PATCHing the words NOT and 0= yield the same results ; they
should not ! 0= yields a boolean with 0 meaning FALSE and -1
TRUE, whereas NOT is bitwise negation of a 16 bits integer.
To test for another PATCHed bug with word D+!, you may type :
2VARIABLE foo
OK 1. foo 2!
OK foo 2@ D.
1 OK 2. foo D+!
OK foo 2@ D.
3 OK (you get '3' after patching ; before, you get garbage !)
The most serious bug (that I found first) affected all the words that implemented some kind of integer division ( / mod /mod ... etc). Somehow, around zero, the "flooring" seemed not right.
In such cases, the Forth programmer has an alternative : either, he programs "high level words" that check for the error condition and work "around" it, giving the new words the same name as the old buggy ones, thus hiding them ; or he digs into the machine code and looks for a way to "patch" the bug at the lowest level.
The first way adds some exec time penalty each time you call the functions, and takes some room.
The second way is more radical but also more difficult : you have to disassemble "by hand" machine code, find the bug, and invent a way to correct it by using no more than the memory space of the original code. But then, you are not done ! after that, you have to check all the higher level routines that use the code, to ascertain that your correction does not affect adversively their execution (that may have been "twitched" to accomodate the bug). Fortunately, I could do it, and the correction has no influence on higher level words, because the flooring (and remainder) was affected only for division of negative numbers that yielded a quotient of 0 (should have been -1). Integer division is seldom used for negative numbers (because programmers obviously are not familiar with how flooring will be handled, so they usually avoid these situations).
Afterward, I discovered two minor bugs affecting only two words :
"NOT" in Forth83 is defined as "bitwise negation" of a 16 bits number, whereas is this release, it behaved like "0=", a boolean test. In Forth (like in C) there is no special boolean type : instead, any non zero value is taken as TRUE and zero is equated to FALSE (by the testing words like "IF" etc). But the "boolean" functions (like "0=" etc) always return -1 for TRUE. So, obviously, if NOT behaves like 0=, it has no use. I corrected this too, but was very uncertain that this one would not have adverse influence of a lot of higher level words. Fortunately, it did not !
"D+!" is a word that nobody would never use but once I did, and had some hard time finding that it produced garbage. To correct it, I had only to patch one instruction.
I used Forth so intensively that I am almost sure that no other bug will remain after you patched these three. You should use the "test words" to see the bugs before patching and after, to see if they were corrected. If everything is OK, FORGET PATCH and SAVE mdv2_FORTH, your corrected version (that will not replace the old one, unless you want).
Paul