artrag Posted June 4, 2022 Share Posted June 4, 2022 My question is also about the CP1600 I have this segment of code if (#ex(n)/256 > (160+8)) then ' test both for x<0 and x>160 gosub en_exits_screen elseif (#ex(n)/256 < 0) then ' test both for x<0 and x>160 gosub en_exits_screen end if That is transleted to ;[1261] if (#ex(n)/256 > (160+8)) then MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 SWAP R0 ANDI #255,R0 CMPI #168,R0 BLE T213 ;[1262] gosub en_exits_screen CALL label_EN_EXITS_SCREEN ;[1263] elseif (#ex(n)/256 < 0) then B T214 T213: MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 SWAP R0 ANDI #255,R0 CMPI #0,R0 BGE T215 ;[1264] gosub en_exits_screen CALL label_EN_EXITS_SCREEN ;[1265] end if T214: T215: Everithing works fine, and en_exits_screen is called only if #ex()/256<0 or if #ex()/256>168 Now I wanted to get rid of the division by 256. I was expecting that #ex()/256<0 is the same of #ex()<0 and that #ex()/256>168 is the same of #ex()>168*256. So I tried this code if (#ex(n)> (160+8)*256) then ' test both for x<0 and x>160 gosub en_exits_screen elseif (#ex(n) < 0) then ' test both for x<0 and x>160 gosub en_exits_screen end if which translate to this ;[1262] if (#ex(n)> (160+8)*256) then MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 CMPI #$A800,R0 BLE T213 CALL label_EN_EXITS_SCREEN ;[1264] elseif (#ex(n) < 0) then B T214 T213: MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 CMPI #0,R0 BGE T215 CALL label_EN_EXITS_SCREEN ;[1266] end if T214: T215: The ASM seems correct, but it happen to not work and I suspect it as to do with signed math in the CP1600 More precisely: - CMPI #0,R0 seems to trigger the jump to en_exits_screen both if #ex()<0 and #ex()/256>127 - CMPI #$A800,R0 seems to trigger the jump to en_exits_screen always, with any value of #ex() This latter in particular is strange.... Any insignt ? Quote Link to comment Share on other sites More sharing options...
artrag Posted June 4, 2022 Author Share Posted June 4, 2022 Ok some answers to my questions $A800 is negative thus any positive value is larger and the code triggers always the call to en_exits_screen Also comparing to 0, implies that the max positive is 32.767 which corresponds to 127 one divided by 256. Any larger value is negative and triggers the call to en_exits_screen. I think that BGE and BLE are based on the sign of the result of CMPI. Are they? Is there a way to make intybasic produce jumps on the carry flag instead of the sign flag? Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted June 4, 2022 Share Posted June 4, 2022 (edited) 18 minutes ago, artrag said: Ok some answers to my questions $A800 is negative thus any positive value is larger and the code triggers always the call to en_exits_screen Also comparing to 0, implies that the max positive is 32.767 which corresponds to 127 one divided by 256. Any larger value is negative and triggers the call to en_exits_screen. I think that BGE and BLE are based on the sign of the result of CMPI. Are they? Yes. For unsigned comparisons, you use BNEQ and BNC. http://wiki.intellivision.us/index.php/Extended_Precision_Arithmetic#Comparison http://wiki.intellivision.us/index.php/CP1610#Instruction_Set Quote Is there a way to make intybasic produce jumps on the carry flag instead of the sign flag? I haven't tested it (I'm not close to my computer), but have you tried defining the variable with the UNSIGNED modifier? It prompts the compiler to treat the variable as unsigned during expression evaluation, and I think this extends to comparisons. dZ. Edited June 4, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted June 5, 2022 Share Posted June 5, 2022 (edited) 13 hours ago, DZ-Jay said: I haven't tested it (I'm not close to my computer), but have you tried defining the variable with the UNSIGNED modifier? It prompts the compiler to treat the variable as unsigned during expression evaluation, and I think this extends to comparisons. Good news! I just tested this and it worked as expected: declaring the "#en" array as "unsigned" will prompt the compiler to generate unsigned comparisons. I used the same code from the top of your first post, and it resulted in the following code. Notice the use of BEQ and BNC instead of BLE and BGE. ; if (#ex(n)/256 > (160+8)) then ' test both for x<0 and x>160 MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 SWAP R0 ANDI #255,R0 CMPI #168,R0 BEQ T7 BNC T7 ; gosub en_exits_screen CALL label_EN_EXITS_SCREEN ; elseif (#ex(n)/256 < 0) then ' test both for x<0 and x>160 B T8 T7: MVII #array_&EX,R3 ADD var_N,R3 MVI@ R3,R0 SWAP R0 ANDI #255,R0 CMPI #0,R0 BC T9 ; gosub en_exits_screen CALL label_EN_EXITS_SCREEN ; end if T8: T9: The only difference was to use the "UNSIGNED" directive when declaring the variable: Dim #ex(SOME_VALUE_HERE) Dim n Unsigned #ex -dZ. Edited June 5, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted June 5, 2022 Share Posted June 5, 2022 (edited) EDIT: I've updated this post with some corrections pointed out by @artrag. For clarity, and to help any others who may encounter a similar case, here's the relevant portion from the SDK documentation (intro_to-cp1600.txt) : To perform unsigned comparisons, the situation is a little simpler, since we don't care about overflows. Since the numbers are unsigned, though, the sign bit doesn't contain the information we're interested in. Instead we can look directly at the carry and zero bits. If this Then so And these is true... is this... status bits are set. ----------------------------------------------------------------- x < y x - y < 0 C = 0, Z = 0, O = ? x > y x - y > 0 C = 1, Z = 0, O = ? x = y x - y = 0 C = 1, Z = 1, O = ? We can then use the branches that look at the carry bit and zero bit to handle greater-than, less-than, and equals on unsigned numbers: Mnemonic Branch if... Test -------------------------------------------------------------- BC Carry is set C = 1 BNC Carry is not set C = 0 BEQ Zero is set Z = 1 Notice that "BC" is effectively "Branch if Greater or Equal", and "BNC" is "Branch if Less Than." We can use "BEQ" before a "BC" to sort out the "Equals" cases from the "Greater" cases. For IntyBASIC programmers who are not familiar with Assembly Language, what all this means is that the CPU treats logical comparisons (i.e., IF expressions) differently depending on whether the expression is "signed" (involving positive and/or negative values), or "unsigned" (involving only absolute values). IntyBASIC automatically handles this for you in the following way: By default, 16-bit variables are signed, meaning that they can be positive or negative. The most significant bit (i.e., the highest order bit) is reserved to mark the sign, which reduces their range by a power of 2. Therefore, 16-bit variables are treated really as 15-bit variables (215 + sign), so their range is from -32,768 to +32,768. This is important: any positive value in a signed variable that goes over the range above will be interpreted as a negative value, and therefore affect the outcome of your "IF" expressions. This is essentially the problem @artrag encountered in his first post. By default, 8-bit variables are unsigned, meaning that they can never be negative. (Actually, they are absolute values, just numbers without being positive or negative.) 8-bit variables are treated using all their bits for their value (28), so their range is from 0 to 255. This is important: unsigned variables can never have negative values. A negative value assigned to an unsigned variable will be interpreted as larger positive value -- that is, what would be the sign-bit will be treated as part of the number. This obviously will affect the outcome of your "IF" expressions. You can reverse the default behaviour of variables using the modifiers SIGNED and UNSIGNED, as applicable. (See the IntyBASIC manual for more details, or take a look at the example in an my earlier post). When applied to corresponding variables, their range changes as follows: Signed 8-bit variables are treated as 7-bit values (27 + sign), so their range is from -127 to +127. Unsigned 16-bit variables are treated as such (216), so their range is from 0 to 65,536. The "signness" of variables in an "IF" expression determines how the expression logic will be handled by the CPU: Any signed variable (either default or marked with the SIGNED modifier) will result in the expression being treated as signed. All unsigned variables (either default or marked with the UNSIGNED modifier) will result in the expression being treated as unsigned. I hope this makes sense. -dZ. Edited June 6, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
artrag Posted June 5, 2022 Author Share Posted June 5, 2022 Dz, the 8 bit variables are by default unsigned, the 16 bit variables are by default signed. The SIGNED and UNSIGNED qualifier can revert the default. The exception is that 16 bit multiplications and divisions are always unsigned. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted June 5, 2022 Share Posted June 5, 2022 (edited) 18 hours ago, artrag said: Dz, the 8 bit variables are by default unsigned, the 16 bit variables are by default signed. The SIGNED and UNSIGNED qualifier can revert the default. Yes, this is what I explained above, in the first bullet point. EDIT: You are right, I corrected the previous post with the correct information. I am sorry for the confusion. The rest of my post here is correct. Moreover, you can apply the SIGNED/UNSIGNED modifier at any point, as many times as needed, for instance: Dim #A, #B ' Treat #A as unsigned from now on ... UNSIGNED #A If ((#A > 100) Then Goto MainLoop End If ' Treat it again as signed ... SIGNED #A Quote The exception is that 16 bit multiplications and divisions are always unsigned. The 16-bit multiplications are unsigned, yes, but the results of a logical expression (even those including multiplication of 16-bit values) depends on the whether the variables are signed or unsigned. For example, the following code: Dim #A, #B If ((#A * #B) < 1) Then Goto MainLoop End If Compiles to the following: ;[46] If ((#A * #B) < 1) Then MVI var_&A,R0 MVI var_&B,R1 CALL qs_mpy16 MOVR R1,R0 CMPI #1,R0 BGE T7 The results of the multiplication is unsigned, but when the full expression is evaluated, it only considers the attributes of the variables, which in this case are signed (default). -dZ. Edited June 6, 2022 by DZ-Jay Corrected an error. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted June 6, 2022 Share Posted June 6, 2022 (edited) 18 hours ago, artrag said: Dz, the 8 bit variables are by default unsigned, the 16 bit variables are by default signed. The SIGNED and UNSIGNED qualifier can revert the default. The exception is that 16 bit multiplications and divisions are always unsigned. Sorry, I just caught my error -- I don't know how I missed it earlier. You are right: by default, 8-bit variables are unsigned and 16-bit variables are signed. Sorry for the confusion. I've updated the two posts above with the correct information. Please let me know if you see anything else wrong. :) Thanks, -dZ. Edited June 6, 2022 by DZ-Jay Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.