Recent

Author Topic: Inline assembly issue  (Read 1277 times)

Aik_T

  • New Member
  • *
  • Posts: 24
Re: Inline assembly issue
« Reply #15 on: November 07, 2024, 06:45:55 am »
Assuming targeting X86_64 and using the systemV ABI then the parameters are passed in XMM0 and XMM1. You can then just do an SSE division and leave (result is in XMM0). If you really do want to use the FPU then you must copy the parameters to locals. And the rest is just like in the previous answer.
On windows that might be different.
Thank you! I found such a variant in Daniel Kusswurm's book, but I was wondering how it works in a more classic version. Anyway, that's helpful, thanks

Aik_T

  • New Member
  • *
  • Posts: 24
Re: Inline assembly issue
« Reply #16 on: November 07, 2024, 07:24:37 am »
Thanks everyone!
The only thing is that you can't pass numbers directly to the function:
Code: Pascal  [Select][+][-]
  1. Division(10, 2);
You need to pass variables
Code: Pascal  [Select][+][-]
  1. Division(A, B);
Thanks everyone for helping

srvaldez

  • Full Member
  • ***
  • Posts: 114
Re: Inline assembly issue
« Reply #17 on: November 07, 2024, 01:31:10 pm »
Aik_T
the following works on Windows x86 and x64
Code: Pascal  [Select][+][-]
  1.     program Project1;
  2.     {$asmmode intel}
  3.     {$MODE OBJFPC}{$H+}
  4.  
  5.     function Division( a, b:Single): Single; assembler;
  6.     {$ifdef CPU64}
  7.     var
  8.         x, y: Single;
  9.     {$endif}
  10.     asm
  11.         {$ifdef CPU32}
  12.             fld   dword ptr [a]
  13.             Fdiv  dword ptr [b]
  14.             Fstp  dword ptr [Result]
  15.         {$else}
  16.             movss x, xmm0
  17.             movss y, xmm1
  18.             fld   dword ptr [x]
  19.             fdiv  dword ptr [y]
  20.             Fstp  dword ptr [Result]
  21.         {$endif}
  22.     end;
  23.  
  24.     var
  25.         x, y:Single;
  26.     begin
  27.         x:=10;
  28.         y:=5;
  29.         writeln(Division(x, y));
  30.         writeln(Division(25, 5));
  31.         write('Press Return ');ReadLn;
  32.     end.
  33.  

srvaldez

  • Full Member
  • ***
  • Posts: 114
Re: Inline assembly issue
« Reply #18 on: November 07, 2024, 04:15:00 pm »
integer cube root code borrowed from Mparith
Code: Pascal  [Select][+][-]
  1.     program Project1;
  2.     {$asmmode intel}
  3.     {$MODE OBJFPC}{$H+}
  4.  
  5. // code borrowed from Mparith https://forum.lazarus.freepascal.org/index.php/topic,68447.msg528998.html#msg528998
  6. // file mp_base.bas, lines 1754 .. 1808
  7. // conditional compilation added by srvaldez
  8.  
  9.     {For VPC, D2/D3; cardinal is only 31 bit}
  10.     {---------------------------------------------------------------------------}
  11.     function icbrt32(a: longint): longint;
  12.     {-Return the integer cube root sign(a)*floor(|a|^(1/3))}
  13.     var
  14.     x: longint;
  15.     begin
  16.     {Ref: http://www.hackersdelight.org/hdcodetxt/icbrt.c.txt}
  17.  
  18.     {Note: There will be RTEs for large a if Range!? checking (not obverflow)}
  19.     {is done, e.g. in debug mode. Here a 32-bit BASM port of the Pascal code:}
  20.     x := abs(a);
  21.     if x>7 then begin
  22.       {y=ebx, y2=esi, s=cx, b=edi, x=eax}
  23.       asm
  24.         {$if defined(Win32)}
  25.             push edi
  26.             push esi
  27.             push ebx
  28.         {$elseif defined(Win64)}
  29.             push rdi
  30.             push rsi
  31.             push rbx
  32.         {$endif}
  33.             mov  eax,[x]
  34.             xor  ebx,ebx       {y  := 0}
  35.             xor  esi,esi       {y2 := 0}
  36.             mov  cx,30         {s  := 30}
  37.       @@1:  shl  esi,2         {y2 := y2 shl 2}
  38.             add  ebx,ebx
  39.             mov  edx,ebx
  40.             add  edx,esi       {edx:= y2+y}
  41.             mov  edi,edx
  42.             add  edi,edi
  43.             add  edi,edx       {edi:= 3*(y2+y)}
  44.             inc  edi
  45.             shl  edi,cl        {b  := 3*(y2 + y) + 1) shl s}
  46.             cmp  edi,eax
  47.             ja   @@2
  48.             sub  eax,edi       {x  := x - b}
  49.             add  esi,ebx
  50.             inc  ebx           {y  := y + 1}
  51.             add  esi,ebx       {y2 := y2 + y + (y+1)}
  52.       @@2:  sub  cx,3
  53.             jnl  @@1
  54.             mov  [x],ebx
  55.         {$if defined(Win32)}
  56.             pop  ebx
  57.             pop  esi
  58.             pop  edi
  59.         {$elseif defined(Win64)}
  60.             pop  rbx
  61.             pop  rsi
  62.             pop  rdi
  63.         {$endif}
  64.       end;
  65.       if a<0 then icbrt32 := -x
  66.       else icbrt32 := x;
  67.     end
  68.     else begin
  69.       { -7 <= a <= 7, ie icbrt = -1,0,1}
  70.       if a>0 then icbrt32 := 1
  71.       else if a<0 then icbrt32 := -1
  72.       else icbrt32 := 0;
  73.     end;
  74.     end;
  75.  
  76. // test the integer cube root function
  77.     var
  78.         n, r:longint;
  79.     begin
  80.         n:=27;
  81.         r:=icbrt32(n);
  82.         writeln('the cube root of ', n, ' = ', r);
  83.         writeln('the cube root of 8 = ', icbrt32(8));
  84.     end.
  85.  

Aik_T

  • New Member
  • *
  • Posts: 24
Re: Inline assembly issue
« Reply #19 on: November 07, 2024, 08:55:11 pm »
Aik_T
the following works on Windows x86 and x64
Code: Pascal  [Select][+][-]
  1.     program Project1;
  2.     {$asmmode intel}
  3.     {$MODE OBJFPC}{$H+}
  4.  
  5.     function Division( a, b:Single): Single; assembler;
  6.     {$ifdef CPU64}
  7.     var
  8.         x, y: Single;
  9.     {$endif}
  10.     asm
  11.         {$ifdef CPU32}
  12.             fld   dword ptr [a]
  13.             Fdiv  dword ptr [b]
  14.             Fstp  dword ptr [Result]
  15.         {$else}
  16.             movss x, xmm0
  17.             movss y, xmm1
  18.             fld   dword ptr [x]
  19.             fdiv  dword ptr [y]
  20.             Fstp  dword ptr [Result]
  21.         {$endif}
  22.     end;
  23.  
  24.     var
  25.         x, y:Single;
  26.     begin
  27.         x:=10;
  28.         y:=5;
  29.         writeln(Division(x, y));
  30.         writeln(Division(25, 5));
  31.         write('Press Return ');ReadLn;
  32.     end.
  33.  
It works! Thanks!

 

TinyPortal © 2005-2018