S
Skybuck Flying
Hi,
Delphi and C use a different shift right operator, which matters for
negative values:
For signed integers:
Delphi 7 and Delphi 2007:
-512 shr 1 = 2147483392
Converted to IA32 instruction:
-512 shr 1 = 2147483392
Visual Studio .Net 2003, C language:
-512 >> 1 = -256
Converted to IA32 instruction:
-512 SAR 1 = -256
However they do use the same shift left operator:
Delphi 7 and Delphi 2007:
-512 shl = -1024
Converted to IA32 instruction:
-512 shl = -1024
Visual Studio .Net 2003, C language:
-512 << 1 = -1024
Converted to IA32 instruction:
-512 shl = -1024
Demonstration programs:
// *** Begin of Delphi 2007 Code: ***
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a,b,c : integer;
begin
// signed, negative, shift left
a := -512;
b := 1;
c := a shl b; // -1024
// writeln(a);
// writeln(b);
writeln(c);
// writeln;
// signed, negative, shift right
a := -512;
b := 1;
// shr operation works on unsigned integers.
// -512 is interpreted as longword(-512) = 4294966784
// result will be: 2147483392
// C language: c = a >> b; // returns -256;
// Dangerous/Different !
c := a shr b;
// writeln(longword(a));
// writeln(b);
writeln(c);
// writeln;
readln;
end.
// Dissassembly:
<program startup snipped>
Project1.dpr.47: a := -512;
0040914D B800FEFFFF mov eax,$fffffe00
Project1.dpr.48: b := 1;
00409152 BA01000000 mov edx,$00000001
Project1.dpr.49: c := a shl b; // -1024
00409157 8BCA mov ecx,edx
00409159 8BD8 mov ebx,eax
0040915B D3E3 shl ebx,cl
<writeln stuff snipped>
Project1.dpr.57: a := -512;
00409173 B800FEFFFF mov eax,$fffffe00
Project1.dpr.58: b := 1;
00409178 BA01000000 mov edx,$00000001
Project1.dpr.64: c := a shr b;
0040917D 8BCA mov ecx,edx
0040917F 8BD8 mov ebx,eax
00409181 D3EB shr ebx,cl
<writeln stuff snipped>
<program exit snipped>
// *** End of Delphi 2007 Code ***
// *** Begin of Visual Studio .Net 2003, C Code: ***
// TestShiftRightForNegatives.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int a, b, c;
a = -512;
b = 1;
c = a >> b; // shift right
printf("%d\n", c ); // prints -256
a = -512;
b = 1;
c = a << b; // shift left
printf("%d\n", c ); // prints -1024
getchar();
return 0;
}
// disassembly:
<program startup snipped>
int a, b, c;
a = -512;
00411A6E mov dword ptr [a],0FFFFFE00h
b = 1;
00411A75 mov dword ptr ,1
c = a >> b; // shift right
00411A7C mov eax,dword ptr [a]
00411A7F mov ecx,dword ptr
00411A82 sar eax,cl
00411A84 mov dword ptr [c],eax
<print snipped>
a = -512;
00411A98 mov dword ptr [a],0FFFFFE00h
b = 1;
00411A9F mov dword ptr ,1
c = a << b; // shift left
00411AA6 mov eax,dword ptr [a]
00411AA9 mov ecx,dword ptr
00411AAC shl eax,cl
00411AAE mov dword ptr [c],eax
<print snipped>
<program exit snipped>
// *** End of Visual Studio .Net 2003, C Code ***
One final note/warning for C programmers
-9 IDIV 2 = -4
-9 SAR 2 = -3
9 SHR 2 = 4
Final conclusion:
In both languages replacing a DIV 4 with a shift right 2 could be dangerous
especially if the values could be negatives.
In Delphi: result will be large positive. (See IA32 manuals, shr
instruction, unsigned only)
In C: result could be incorrect negative. (See IA32 manuals, sar
instruction,different behaviour for negatives)
Bye,
Skybuck.
Delphi and C use a different shift right operator, which matters for
negative values:
For signed integers:
Delphi 7 and Delphi 2007:
-512 shr 1 = 2147483392
Converted to IA32 instruction:
-512 shr 1 = 2147483392
Visual Studio .Net 2003, C language:
-512 >> 1 = -256
Converted to IA32 instruction:
-512 SAR 1 = -256
However they do use the same shift left operator:
Delphi 7 and Delphi 2007:
-512 shl = -1024
Converted to IA32 instruction:
-512 shl = -1024
Visual Studio .Net 2003, C language:
-512 << 1 = -1024
Converted to IA32 instruction:
-512 shl = -1024
Demonstration programs:
// *** Begin of Delphi 2007 Code: ***
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a,b,c : integer;
begin
// signed, negative, shift left
a := -512;
b := 1;
c := a shl b; // -1024
// writeln(a);
// writeln(b);
writeln(c);
// writeln;
// signed, negative, shift right
a := -512;
b := 1;
// shr operation works on unsigned integers.
// -512 is interpreted as longword(-512) = 4294966784
// result will be: 2147483392
// C language: c = a >> b; // returns -256;
// Dangerous/Different !
c := a shr b;
// writeln(longword(a));
// writeln(b);
writeln(c);
// writeln;
readln;
end.
// Dissassembly:
<program startup snipped>
Project1.dpr.47: a := -512;
0040914D B800FEFFFF mov eax,$fffffe00
Project1.dpr.48: b := 1;
00409152 BA01000000 mov edx,$00000001
Project1.dpr.49: c := a shl b; // -1024
00409157 8BCA mov ecx,edx
00409159 8BD8 mov ebx,eax
0040915B D3E3 shl ebx,cl
<writeln stuff snipped>
Project1.dpr.57: a := -512;
00409173 B800FEFFFF mov eax,$fffffe00
Project1.dpr.58: b := 1;
00409178 BA01000000 mov edx,$00000001
Project1.dpr.64: c := a shr b;
0040917D 8BCA mov ecx,edx
0040917F 8BD8 mov ebx,eax
00409181 D3EB shr ebx,cl
<writeln stuff snipped>
<program exit snipped>
// *** End of Delphi 2007 Code ***
// *** Begin of Visual Studio .Net 2003, C Code: ***
// TestShiftRightForNegatives.cpp : Defines the entry point for the console
application.
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int a, b, c;
a = -512;
b = 1;
c = a >> b; // shift right
printf("%d\n", c ); // prints -256
a = -512;
b = 1;
c = a << b; // shift left
printf("%d\n", c ); // prints -1024
getchar();
return 0;
}
// disassembly:
<program startup snipped>
int a, b, c;
a = -512;
00411A6E mov dword ptr [a],0FFFFFE00h
b = 1;
00411A75 mov dword ptr ,1
c = a >> b; // shift right
00411A7C mov eax,dword ptr [a]
00411A7F mov ecx,dword ptr
00411A82 sar eax,cl
00411A84 mov dword ptr [c],eax
<print snipped>
a = -512;
00411A98 mov dword ptr [a],0FFFFFE00h
b = 1;
00411A9F mov dword ptr ,1
c = a << b; // shift left
00411AA6 mov eax,dword ptr [a]
00411AA9 mov ecx,dword ptr
00411AAC shl eax,cl
00411AAE mov dword ptr [c],eax
<print snipped>
<program exit snipped>
// *** End of Visual Studio .Net 2003, C Code ***
One final note/warning for C programmers
-9 IDIV 2 = -4
-9 SAR 2 = -3
9 SHR 2 = 4
Final conclusion:
In both languages replacing a DIV 4 with a shift right 2 could be dangerous
especially if the values could be negatives.
In Delphi: result will be large positive. (See IA32 manuals, shr
instruction, unsigned only)
In C: result could be incorrect negative. (See IA32 manuals, sar
instruction,different behaviour for negatives)
Bye,
Skybuck.