I have done some test on Windows using VC++ 2010
I have used the following code
Code: Select all
int main() {
signed int i, j, k;
bool ij, jk;
i = 2147483648;
i++;
j = i - 1;
k = i - 2;
ij = i > j;
jk = j > k;
fprintf(stdout, "%d %d %d *** %u %u %u *** %d %d\n", i, j, k, i, j, k, ij, jk);
}
Guess the answer
Code: Select all
-2147483647 -2147483648 2147483647 *** 2147483649 2147483648 2147483647 *** 1 0
We have i++ that causes an overflow resulting in a negative number, Then i-1 gives the min negative number, Then i-2 gives an underflow resulting in a positive number
This is if you print the numbers as signed int (interpreted as two complement) but if you print them as unsigned int then it is "easier to follow"
The last two printed values are the comparison and you are getting i > j but j < k which make sense
but probably not what you expect.
Lets look at the assembly (not optimized)
Code: Select all
; 4 : signed int i, j, k;
; 5 : bool ij, jk;
; 6 :
; 7 : i = 2147483648;
mov DWORD PTR _i$[ebp], -2147483648 ; 80000000H
; 8 : i++;
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
; 9 : j = i - 1;
mov eax, DWORD PTR _i$[ebp]
sub eax, 1
mov DWORD PTR _j$[ebp], eax
; 10 : k = i - 2;
mov eax, DWORD PTR _i$[ebp]
sub eax, 2
mov DWORD PTR _k$[ebp], eax
; 11 : ij = i > j;
mov eax, DWORD PTR _i$[ebp]
xor ecx, ecx
cmp eax, DWORD PTR _j$[ebp]
setg cl
mov BYTE PTR _ij$[ebp], cl
; 12 : jk = j >k;
mov eax, DWORD PTR _j$[ebp]
xor ecx, ecx
cmp eax, DWORD PTR _k$[ebp]
setg cl
mov BYTE PTR _jk$[ebp], cl
OK so now what would happen if we replace the declaration of i,j,k by unsigned?
Result is
Code: Select all
-2147483647 -2147483648 2147483647 *** 2147483649 2147483648 2147483647 *** 1 1
This is exactly the same result with the exception of the compare. And in that case it is more intuitive i>j and j>k
If we look at the assembly
Code: Select all
; 4 : unsigned int i, j, k;
; 5 : bool ij, jk;
; 6 :
; 7 : i = 2147483648;
mov DWORD PTR _i$[ebp], -2147483648 ; 80000000H
; 8 : i++;
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
; 9 : j = i - 1;
mov eax, DWORD PTR _i$[ebp]
sub eax, 1
mov DWORD PTR _j$[ebp], eax
; 10 : k = i - 2;
mov eax, DWORD PTR _i$[ebp]
sub eax, 2
mov DWORD PTR _k$[ebp], eax
; 11 : ij = i > j;
mov eax, DWORD PTR _i$[ebp]
cmp DWORD PTR _j$[ebp], eax
sbb ecx, ecx
neg ecx
mov BYTE PTR _ij$[ebp], cl
; 12 : jk = j > k;
mov eax, DWORD PTR _j$[ebp]
cmp DWORD PTR _k$[ebp], eax
sbb ecx, ecx
neg ecx
mov BYTE PTR _jk$[ebp], cl
We can see that all operations on the number are exactly the same whether signed or unsigned. However the comparison are different because now the compile has to take care of the sign.
The above result are not a surprise, but they are somewhat specific to VC++ and of course to Intel asm.
So back to your original post doing operations on signed or unsigned should probably gives same results but must be treated carefully. For example in cpu_timer-cpu_cycles I assume that cpu_timer is always bigger (from an "unsigned point of view") than cpu_cycles otherwise you may be in trouble.
However if you try to compare the cpu_timer-cpu_cycles value with other values you will have problems almost for sure.
Bottom line cpu_timer and cpu_cycles (in steemh.h) should probably be converted to unsigned int.
But as I already said this seems to be a recurrent problem in Steem for example to avoid C4309 warnings (truncation) in steemh.h I had to declare
Code: Select all
unsigned short m68k_src_w; // jlg_4309
unsigned long m68k_src_l; // jlg_4309
unsigned char m68k_src_b; // jlg_4309
...