Beware: C and Delphi uses different shift right operator. (Matters for negatives, both languages can

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top