Recent

Author Topic: shl and rangecheck  (Read 11787 times)

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: shl and rangecheck
« Reply #15 on: September 05, 2012, 06:18:54 pm »
Quote
The one weird thing is that when using longwords, you cannot shl $80000000 times
What is weird? The test or the result ;D

On i386 the shift number is limited to 256. The code generated is
Code: [Select]
b801000000               mov    $0x1,%eax
b900000080               mov    $0x80000000,%ecx
d3e0                     shl    %cl,%eax
cl is the lower byte of $80000000 which is $00. So the result is the same as 1 shl 0. What is the runtime error you are getting?

eny

  • Hero Member
  • *****
  • Posts: 1648
Re: shl and rangecheck
« Reply #16 on: September 05, 2012, 07:36:48 pm »
Quote
The one weird thing is that when using longwords, you cannot shl $80000000 times
What is weird? The test or the result ;D
The generated assembler code  8-)
Even though the number is limited by the (8-bit) size of CL, the generated code checks for an overflow on the 2nd operand.
The generated assembler for my fragment above (all longwords) is:
Code: [Select]
ufrmmain1.pas:67                  x := 1;
0042570C c745f401000000           movl   $0x1,-0xc(%ebp)
ufrmmain1.pas:68                  y := $7FFFFFFF;
00425713 c745f0ffffff7f           movl   $0x7fffffff,-0x10(%ebp)
ufrmmain1.pas:69                  z := x shl y; // Works
0042571A 8b45f0                   mov    -0x10(%ebp),%eax
0042571D 3dffffff7f               cmp    $0x7fffffff,%eax
00425722 7605                     jbe    0x425729 <TFRMMAIN1__BUTTON2CLICK+41>
00425724 e80774feff               call   0x40cb30 <fpc_rangeerror>
00425729 8b45f4                   mov    -0xc(%ebp),%eax
0042572C 8b4df0                   mov    -0x10(%ebp),%ecx
0042572F d3e0                     shl    %cl,%eax
00425731 8945ec                   mov    %eax,-0x14(%ebp)
ufrmmain1.pas:71                  x := 1;
00425734 c745f401000000           movl   $0x1,-0xc(%ebp)
ufrmmain1.pas:72                  y := $80000000;
0042573B c745f000000080           movl   $0x80000000,-0x10(%ebp)
ufrmmain1.pas:73                  z := x shl y; // Runtime error ;)
00425742 8b45f0                   mov    -0x10(%ebp),%eax
00425745 3dffffff7f               cmp    $0x7fffffff,%eax
0042574A 7605                     jbe    0x425751 <TFRMMAIN1__BUTTON2CLICK+81>
0042574C e8df73feff               call   0x40cb30 <fpc_rangeerror>
00425751 8b45f4                   mov    -0xc(%ebp),%eax
00425754 8b4df0                   mov    -0x10(%ebp),%ecx
00425757 d3e0                     shl    %cl,%eax
00425759 8945ec                   mov    %eax,-0x14(%ebp)
So having 7FF etc in works, but 800 etc. doesn't because of the range checking.
All posts based on: Win10 (Win64); Lazarus 3_4  (x64) 25-05-2024 (unless specified otherwise...)

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: shl and rangecheck
« Reply #17 on: September 05, 2012, 08:30:27 pm »
The generated assembler code  8-)
That is indeed very weird. All variables longword and still the second operand is checked against $7fffffff. When y is defined as a longint there is no check any more which indicates shl expects a longint as second parameter. According to the Delphi help "Note that the value of y is interpreted modulo the size of the type of x", meaning that it doesn't make any difference whether the second operand is an longint or longword. 1 shl -1 is $80000000 just as 1 shl 31 or 1 shl $ffffffff. Sounds like a bug. One I can live with though ;)

eny

  • Hero Member
  • *****
  • Posts: 1648
Re: shl and rangecheck
« Reply #18 on: September 05, 2012, 09:00:41 pm »
One I can live with though ;)
Same here  :D
Lesson learned is the 1 that is interpreted as a signed integer. Useful to know.
All posts based on: Win10 (Win64); Lazarus 3_4  (x64) 25-05-2024 (unless specified otherwise...)

Knipfty

  • Full Member
  • ***
  • Posts: 232
Re: shl and rangecheck
« Reply #19 on: September 05, 2012, 09:14:01 pm »
Agreed!  I just made changes in a couple of procedures to make sure that the typecast gets done properly to avoid any issues down the road.

Great thread!

Knipfty
64-bit Lazarus 2.2.0 FPC 3.2.2, 64-bit Win 11

 

TinyPortal © 2005-2018