Few weeks ago I converted a little function from C language to Delphi. I kept getting completely wrong results all the time even though I was sure the C to Pascal conversion was right (it was really just few lines). After some desperate time, I just tried replacing SHR operator by normal DIV (as A SHR 1 = A DIV 2 and so on). To my surprise, I immediately got the right results. Can Delphi’s (I didn’t test it in Free Pascal) SHR operator behave differently than C’s >> operator?
It does in fact. SHR treats its first operand as unsigned value even though it is a variable of signed type whereas >> takes the sign bit into account. In the function I converted the operand for right shift was often negative and Delphi’s SHR just ignored the value of the sign bit.
A Bit of Code
int a, b1, b2; a = -512; b1 = a >> 1; b2 = a / 2;
After running this C code both b1 and b2 have a value of -256.
var A, B1, B2: Integer; A := -512; B1 := A shr 1; B2 := A div 2;
This Delphi code however yields different result: B2 is -256 as expected but B1 has a value of 2147483392.
A Bit of Assembler
Assembler output of C code:
Unit1.cpp.22: b1 = a >> 1; mov eax,[ebp-$0c] sar eax,1 mov [ebp-$10],eax Unit1.cpp.23: b2 = a / 2; mov edx,[ebp-$0c] sar edx,1 jns $00401bb9 adc edx,$00 mov [ebp-$14],edx
Assembler output of Delphi code:
Unit1.pas.371: B1 := A shr 1; mov eax,[ebp-$0c] shr eax,1 mov [ebp-$1c],eax Unit1.pas.373: B2 := A div 2; mov eax,[ebp-$0c] sar eax,1 jns $00565315 adc eax,$00 mov [ebp-$20],eax
As you can see, asm output of C and Delphi divisions is identical. What differs is asm for shift right operator. Delphi uses shr instruction whereas C uses sar instruction. The difference: shr does logical shift and sar does arithmetic one.
The SHR instruction clears the most significant bit (see Figure 6-7 in the Intel Architecture Software Developer’s Manual, Volume 1); the SAR instruction sets or clears the most significant bit to correspond to the sign (most significant bit) of the original value in the destination operand.
Quoted from: http://faydoc.tripod.com/cpu/shr.htm