Forum > General

x64 assembly routine - size of integer parameter is ignored

(1/4) > >>

ncs-sniper:
Hello all!
Today, I have finally updated Lazarus to new version (2.2.2, FPC 3.2.2) - I was using Laz 2.0.8 (FPC 3.0.4) - and tried to compile some of my code to see what is broken 8).

I have found that the x64 compiler simply ignores size of integer parameters in assembly. Let's have following code:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$MODE ObjFPC}{$ASMMODE Intel}...procedure Foo(Value: Byte); register; assembler;asm  MOVZX   EDX,  Valueend;  In x86, this is correctly compiled as

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---0fb6d0  movzbl %al,%edx... but in x64, the compiler just throws error:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Error: Asm: [movzx reg32,reg32] invalid combination of opcode and operands
Ok, I can work around it - for example not using parameter names and writing the registers directly (which is annoying as they differ in windows and linux). But it gets worse, because this:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure Foo(Value: Byte); register; assembler;asm  MOV   DL,  Valueend;... is in x64 compiled as:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---89ca  mov    %ecx,%edxwhich is imho totally wrong, and no error or warning is issued. If you expect higher 24bits of EDX to be preserved (they should be), you are in for a nasty surprise. The same happens whether you use Intel or ATT syntax.

This was not hapenning in FPC 3.0.4 that I was using before, there it produces:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---88ca  mov    %cl,%dl
Am I wrong here, am I missing something, or is this a bug? And is it known? If this is to be expected, can someone point me to some documentation describing this?

Note - I am not able to go and try newer FPC versions.

marcov:
FPC trunk compiles it fine to    movzbl   %cl,%edx on win64. (AT&T style)

ncs-sniper:
Yes, trunk compiles it correctly, but still - 3.2.2 is bundled with current Lazarus, so I gues it is (one of) the most widespread version. And if this is confirmed (I have tried three instalations myself, all manifest this error), then it is, at least for me, a serious bug - it can break completely valid asm code that was previously working. Seriously, it changes width of the explicitly requested register without issuing warning or even a note.
So, can anyone confirm this behaviour? And does anyone know any workaround, save for rewriting all assembly that uses parameters via their names?

Thaddy:
1. The 3.2.2 fixes branch might also work (current)
2. If not, ask for a back-port to fixes from trunk on the bug tracker
3. Otherwise be patient or use trunk.

This is the usual order. Back-ports to a release are very, very rare.

WooBean:
@ncs-sniper
Proposed workarround for 64bit code (if you want to save unchanged large blocks of asm code with using named parameters):


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---{$IFDEF CPUX86_64} procedure Foo(Value: Byte); register;begin  asm   MOVZX   EDX,  Value;  end;end;{$ELSE}procedure Foo(Value: Byte); register; assembler;asm  MOVZX   EDX,  Valueend; {$ENDIF} 
BTW see doc at https://www.freepascal.org/docs-html/ref/refsu89.html#x210-23400014.9.18 which is not much promissing for the future.

Navigation

[0] Message Index

[#] Next page

Go to full version