Was macht dieser Assembler-Code?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Ally
Beiträge: 225
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Was macht dieser Assembler-Code?

Beitrag von Ally »

Hallo zusammen,

ich habe hier ein Stückchen Assembler-Code, den ich gerne als normalen Pascal-Code hätte.
Da ich von Assembler so ziemlich überhaupt keine Ahnung habe, meine Frage an euch: kann das jemand übersetzen?

Code: Alles auswählen

  function rech(i, j: Integer): Integer;
  asm
    add eax, edx
    sub eax, $40
    cmp eax, 0
    jge @weiter
    xor eax, eax
    jmp @fertig
   @weiter:
    cmp eax, $FF
    jle @fertig
    mov eax, $FF
    @fertig:
  end;

Benutzeravatar
kupferstecher
Beiträge: 395
Registriert: Do 17. Nov 2016, 11:52

Re: Was macht dieser Assembler-Code?

Beitrag von kupferstecher »

Ohne Gewähr :wink:

Code: Alles auswählen

function rech(i, j: Integer): Integer;

  Result:= i+j;
  Result:= Result - $40;
  
  if Result <= 0
  then Result:= 0
  else
  if Result > $FF
  then Result:= $FF;
  
end;

Benutzeravatar
Ally
Beiträge: 225
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Was macht dieser Assembler-Code?

Beitrag von Ally »

Hallo kupferstecher,

vielen Dank.
Funktioniert super. :D

Gruß Roland

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

Ich hätte mal noch eine Frage dazu:

Wenn ich das in Lazarus nachvollziehen möchte, bekomme ich immer 0.

Code: Alles auswählen

  function rech(i, j: Integer): Integer;
    {$asmMode intel}
    begin
      asm
        add eax, edx
        sub eax, $40
        cmp eax, 0
        jge @weiter
        xor eax, eax
        jmp @fertig
       @weiter:
        cmp eax, $FF
        jle @fertig
        mov eax, $FF
        @fertig:
      end
    end;

    { TForm1 }

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Caption:=rech(100,28).ToString;
    end; 
Wie bekomme ich den Rückgabewert?
mov result, eax geht auch nicht.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1214
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Was macht dieser Assembler-Code?

Beitrag von fliegermichl »

Diesen Code kannst du nur für 32 Bit einsetzen.
Das Ergebnis wird normalerweise im EAX Register zurückgegeben.

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

fliegermichl hat geschrieben:
Mo 14. Nov 2022, 16:36
Diesen Code kannst du nur für 32 Bit einsetzen.
Das Ergebnis wird normalerweise im EAX Register zurückgegeben.
OK, Danke! Dass es noch 32 bit BS gibt, hatte ich gar nicht auf dem Schirm. :mrgreen:
Wie wäre dann der Code für 64bit?
So grundlegend anders kann der ja nicht sein, oder?

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

Habe mal ein bisschen rumgespielt.
So scheint es zu gehen auf 64bit Linux.
Habe allerdings kaum eine Ahnung davon und nehme auch vernichtende Kritik dankend entgegen, wenn sie dem Erkenntnisgewinn dient. :wink:

Code: Alles auswählen

function recha(i, j: Integer): Integer; assembler; register; nostackframe;
      asm
        add rsi, rdi
        sub rsi, $40
        cmp rsi, 0
        jge @weiter
        xor rsi, rsi
        jmp @fertig
       @weiter:
        cmp rsi, $FF
        jle @fertig
        mov rsi, $FF
        @fertig:
        mov result, rsi
    end;     

PascalDragon
Beiträge: 670
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Was macht dieser Assembler-Code?

Beitrag von PascalDragon »

theo hat geschrieben:
Mo 14. Nov 2022, 20:51
So scheint es zu gehen auf 64bit Linux.
Habe allerdings kaum eine Ahnung davon und nehme auch vernichtende Kritik dankend entgegen, wenn sie dem Erkenntnisgewinn dient. :wink:
Unter Win64 wird das nicht funktionieren, das Windows ein andere Calling Convention verwendet. Man kann das aber so anpassen, dass es auf beiden Platformen läuft (und ja, die Verwendung von eax statt rax in den ersten beiden Zeilen ist Absicht):

Code: Alles auswählen

function recha(i, j: Integer): Integer; assembler; register; nostackframe;
{$asmmode intel}
      asm
        mov eax, i
        add eax, j
        sub rax, $40
        cmp rax, 0
        jge @weiter
        xor rax, rax
        jmp @fertig
       @weiter:
        cmp rax, $FF
        jle @fertig
        mov rax, $FF
        @fertig:
    end;
FPC Compiler Entwickler

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1214
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Was macht dieser Assembler-Code?

Beitrag von fliegermichl »

PascalDragon hat geschrieben:
Di 15. Nov 2022, 07:35
theo hat geschrieben:
Mo 14. Nov 2022, 20:51
So scheint es zu gehen auf 64bit Linux.
Habe allerdings kaum eine Ahnung davon und nehme auch vernichtende Kritik dankend entgegen, wenn sie dem Erkenntnisgewinn dient. :wink:
Unter Win64 wird das nicht funktionieren, das Windows ein andere Calling Convention verwendet. Man kann das aber so anpassen, dass es auf beiden Platformen läuft (und ja, die Verwendung von eax statt rax in den ersten beiden Zeilen ist Absicht):

Code: Alles auswählen

function recha(i, j: Integer): Integer; assembler; register; nostackframe;
{$asmmode intel}
      asm
        mov eax, i
        add eax, j
        sub rax, $40
        cmp rax, 0
        jge @weiter
        xor rax, rax
        jmp @fertig
       @weiter:
        cmp rax, $FF
        jle @fertig
        mov rax, $FF
        @fertig:
    end;
Das kompiliert natürlich wieder nicht auf 32 Bit Targets.

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

PascalDragon hat geschrieben:
Di 15. Nov 2022, 07:35
Unter Win64 wird das nicht funktionieren, das Windows ein andere Calling Convention verwendet. Man kann das aber so anpassen, dass es auf beiden Platformen läuft (und ja, die Verwendung von eax statt rax in den ersten beiden Zeilen ist Absicht):
Danke, wieder was gelernt! :D
fliegermichl hat geschrieben:
Di 15. Nov 2022, 09:36
Das kompiliert natürlich wieder nicht auf 32 Bit Targets.
Aber so geht es auch auf 64bit (rax -> eax).
Müsste das nicht auch auf 32 bit laufen? Oder wo ist der Haken?

Code: Alles auswählen

function recha(i, j: Integer): Integer; assembler; register; nostackframe;
{$asmmode intel}
      asm
        mov eax, i
        add eax, j
        sub eax, $40
        cmp eax, 0
        jge @weiter
        xor eax, eax
        jmp @fertig
       @weiter:
        cmp eax, $FF
        jle @fertig
        mov eax, $FF
        @fertig:
    end;

Horst_h
Beiträge: 72
Registriert: Mi 20. Mär 2013, 08:57

Re: Was macht dieser Assembler-Code?

Beitrag von Horst_h »

Hallo,

wenn man die Funktion von kupferstecher mit Ausgabe des Assemblers kompiliert kommt doch schon der gleiche passende Assembler-Code raus.
Reicht da nicht ein simples inline um dann genau so schnell zu sein?
Unter 64-Bit linux fpc -O3 -al -Xs kompiliert:

Code: Alles auswählen

function rech(i, j: Integer): Integer;
begin
  Result:= i+j;
  Result:= Result - $40;

  if Result <= 0
  then Result:= 0
  else
  if Result > $FF
  then Result:= $FF;
end;
Asmstyle ATT ist das, vermute ich:

Code: Alles auswählen

.Lc1:
# Var $result located in register eax
# Var i located in register edi
# Var j located in register esi
# [ErdoesNumb.pas]
# [44] begin
# [45] Result:= i+j;
	leal	(%edi,%esi),%eax
# Var $result located in register eax
# [46] Result:= Result - $40;
	subl	$64,%eax
# Var $result located in register eax
# [48] if Result <= 0
	testl	%eax,%eax
	jnle	.Lj6
# [49] then Result:= 0
	xorl	%eax,%eax
	ret
.Lj6:
# [51] if Result > $FF
	cmpl	$255,%eax
	jng	.Lj9
# [52] then Result:= $FF;
	movl	$255,%eax
.Lj9:
# [54] end;
	ret
Gruß Horst

Benutzeravatar
Ally
Beiträge: 225
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Was macht dieser Assembler-Code?

Beitrag von Ally »

Hallo zusammen,

anbei ein kleines Testprogramm das den Pascal- und den Assembler-Code vergleicht.
Der Unterschied ist eher marginal und das bei 65535 x 65535 Durchläufen.
Ich verwende das Ganze zur Berechnung von Farbwerten in der Bildbearbeitung. Und dabei ist bei Fotos, die eine Größe von z.B. 6000 x 4000 Pixeln haben, kein Unterschied wahrnehmbar.
Dafür ist der Code plattformunabhängig.

Das hilft euch zwar nicht bei eurer Lösungssuche weiter, zeigt aber das der Free Pascal Compiler gar nicht so schlecht ist.

Gruß Roland
Dateianhänge
AssemblerTest.zip
(5.48 KiB) 18-mal heruntergeladen

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

Vielleicht braucht es auch gar spezielle keine Funktion dafür.

Code: Alles auswählen

uses Math;
..
k:=Min(Max(i+j-$40,0),$FF);

Benutzeravatar
theo
Beiträge: 9911
Registriert: Mo 11. Sep 2006, 19:01

Re: Was macht dieser Assembler-Code?

Beitrag von theo »

Hallo Ally.

Habe mal deinen Code getestet.

Assembler ist am langsamsten bei mir.
Am Schnellsten ist bei mir:

Code: Alles auswählen

Min(Max(a+b-$40,0),$FF);
Das könnte sich aber um ein Optimierungs Artefakt handeln, da wir das Resultat nicht benutzen.

Benutzeravatar
Ally
Beiträge: 225
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Was macht dieser Assembler-Code?

Beitrag von Ally »

Hallo theo,
Habe mal deinen Code getestet. Assembler ist am langsamsten bei mir.
Interessant.

Also bei mir (Win10 64Bit - Intel i5-6400 CPU) erhalte ich folgende Ergebnisse:

Assembler: 9296 milliseconds
Pascal: 9719 milliseconds
Pascal Min(Max(..)): 11859 milliseconds

Gruß Roland

Antworten