AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Assembler-Rätsel

Ein Thema von Maekkelrajter · begonnen am 29. Feb 2020 · letzter Beitrag vom 8. Apr 2020
Antwort Antwort
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#1

AW: Assembler-Rätsel

  Alt 7. Apr 2020, 12:52
Hallo,

mittlerweile habe ich das gelöst, indem ich den hier gefundenen Original PosEx-Code von Aleksandr Sharahov ein wenig modifiziert habe. Die Änderungen umfassen zusätzlichen Code zur Prüfung des neuen Parameters 'Limit' und die Änderung des 'Notausganges' ab dem Label @NIL. Dort ersetze ich das 'ret' durch einen Sprung zum Funktions-Ende, um den vom Compiler generierten Austritts-Code zu benutzen, der den zusätzlichen Parameter berücksichtigt.

Delphi-Quellcode:
function PosInLimits(const SubStr, Str: RawByteString; Offset: Integer = 1; limit: Integer = 0): Integer;
asm
       test eax, eax
       jz @Nil
       test edx, edx
       jz @Nil
       dec ecx
       jl @Nil

       push esi
       push ebx

       mov esi, [edx-4] //Length(Str)

//*************************************************************** Zusätzlicher Code

       mov ebx, limit // limit holen
       test ebx, ebx // Limit = 0?
       jz @IgnoreLimit // limit ignorieren
       cmp ebx, esi // limit >= Length(Str)?
       jge @IgnoreLimit // limit ignorieren
       mov esi, ebx // limit übernehmen anstelle von Length(Str)
@IgnoreLimit:

// ************************************************************** Ende zusätzlicher Code

       mov ebx, [eax-4] //Length(Substr)
       sub esi, ecx //effective length of Str (= length(str) - offset)
       add edx, ecx //addr of the first AnsiChar at starting position
       cmp esi, ebx
       jl @Past //jump if EffectiveLength(Str)<Length(Substr)
       test ebx, ebx
       jle @Past //jump if Length(Substr)<=0

       add esp, -12
       add ebx, -1 //Length(Substr)-1
       add esi, edx //addr of the terminator
       add edx, ebx //addr of the last AnsiChar at starting position
       mov [esp+8], esi //save addr of the terminator
       add eax, ebx //addr of the last AnsiChar of Substr
       sub ecx, edx //-@Str[Length(Substr)]
       neg ebx //-(Length(Substr)-1)
       mov [esp+4], ecx //save -@Str[Length(Substr)]
       mov [esp], ebx //save -(Length(Substr)-1)
       movzx ecx, byte ptr [eax] //the last AnsiChar of Substr

@Loop:
       cmp cl, [edx]
       jz @Test0
@AfterTest0:
       cmp cl, [edx+1]
       jz @TestT
@AfterTestT:
       add edx, 4
       cmp edx, [esp+8]
       jb @Continue
@EndLoop:
       add edx, -2
       cmp edx, [esp+8]
       jb @Loop
@Exit:
       add esp, 12
@Past:
       pop ebx
       pop esi
@Nil:
       xor eax, eax
       jmp @done // *************************** Modifiziert

@Continue:
       cmp cl, [edx-2]
       jz @Test2
       cmp cl, [edx-1]
       jnz @Loop
@Test1:
       add edx, 1
@Test2:
       add edx, -2
@Test0:
       add edx, -1
@TestT:
       mov esi, [esp]
       test esi, esi
       jz @Found
@AnsiString:
       movzx ebx, word ptr [esi+eax]
       cmp bx, word ptr [esi+edx+1]
       jnz @AfterTestT
       cmp esi, -2
       jge @Found
       movzx ebx, word ptr [esi+eax+2]
       cmp bx, word ptr [esi+edx+3]
       jnz @AfterTestT
       add esi, 4
       jl @AnsiString
@Found:
       mov eax, [esp+4]
       add edx, 2

       cmp edx, [esp+8]
       ja @Exit

       add esp, 12
       add eax, edx
       pop ebx
       pop esi
@done:
end;
Das Ganze funktioniert anscheinend wie gewünscht. Leider bin ich nicht der große Assembler-Meister, so dass mich die Sorge umtreibt, dass ich doch irgendetwas übersehen habe, was mir irgendwann auf die Füße fällt. Vielleicht könnte irgendein hier mitlesender Assembler-Experte mal einen Blick darauf werfen.
Außerdem eine grundsätzliche Frage: Unter welchen Bedingungen darf ich den Sharahov - Code überhaupt in meinem Programm verwenden? Da ich nicht vorhabe, das Programm oder gar die Quellcodes weiterzugeben, könnte mir das eigentlich völlig wurscht sein. Aber es interessiert mich eben, und die Informationen, die über die verschiedenen Lizenzmodelle im Netz zu finden sind, lassen mich eher ratlos zurück. Kann mir das mal jemand kurz & knackig erläutern?

Gruß LP
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.039 Beiträge
 
Delphi 12 Athens
 
#2

AW: Assembler-Rätsel

  Alt 7. Apr 2020, 20:06
Schreib doch einfach Mal ein paar Unit Tests dafür, dann wirst du schon ein Gefühl dafür bekommen ob das soweit alles abdeckt. DUnit/DUnit2 sind deine Freunde...
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.360 Beiträge
 
Delphi 12 Athens
 
#3

AW: Assembler-Rätsel

  Alt 7. Apr 2020, 23:47
Bin auch grade bissl raus, aus'm ASM.
Es gibt ja ein paar Register, die man sichern muss, bzw. da man nicht verändern darf.

Wobei mir grade nicht einfällt wofür EBX war, (glaub Fehlerbehandlung, Stackverwaltung oder so)
im Windows x86 ... für x64 und andere Plattformen bissl anders.

Dank Multiplatform versuch ich wieder möglichst viel in Pascal zu machen, vor allem da eine meiner letzten Assenbler-Optimierungen auf modernen Intel-CPU gegen deren Optimierung arbeitete und mein hochoptimiertes Assembler wesentlich langsamer war, als das was Delphi aus dem Pascal machte.


Hier gibt's auch noch bissl was in der OH zu finden.
http://docwiki.embarcadero.com/RADSt...bly_Code_Index
Zitat von aus Verwendung des integrierten Assemblers:
In einer asm-Anweisung muss der Inhalt der Register EDI, ESI, ESP, EBP und EBX erhalten bleiben
Auch dazu, was Delphi in den Pascal-Funktionen am Anfang einfügt und wann/warum.
Zitat von aus Assembler-Prozeduren und -Funktionen:
Code:
PUSH  EBP        ;Present if Locals <> 0 or Params <> 0
MOV   EBP,ESP        ;Present if Locals <> 0 or Params <> 0
SUB   ESP,Locals     ;Present if Locals <> 0
; &#8230;
MOV   ESP,EBP        ;Present if Locals <> 0
POP   EBP        ;Present if Locals <> 0 or Params <> 0
RET   Params         ;Always present
Aber mit Conditional-Expressions kommt man IMHO sowieso oft besser.
Zitat:
Delphi-Quellcode:
asm
  ...
end;
{$ELSE !CPUX86}
  {MESSAGE Fatal 'not implemented'}
{$ENDIF !CPUX86}
{$ENDIF !PUREPASCAL}
Delphi-Quellcode:
{$IF Defined(PUREPASCAL)}
begin
  ...
end;
{$ELSEIF Defined(CPUX86)}
asm
  ...
end;
{$ELSE}
  {MESSAGE Fatal 'not implemented'}
{$IFEND}
Hier kann man auch schöner Verschachteln und Zusammenfassen, ohne wirklich in X Ebenen zu verschachteln, wie z.B. {$IF Defined(AAA) OR Defined(BBB)} .
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 8. Apr 2020 um 00:00 Uhr)
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#4

AW: Assembler-Rätsel

  Alt 8. Apr 2020, 00:44
Vor langer, langer Zeit habe ich im Zuge meiner Lehre damals auch mit Assembler programmieren müssen. Das war auf eineM 8008 (kann auch ein anderer gewesen sein), und das ganze mit einem Programmierkoffer (hatte 4 KB Speicher, 8 LEDs, 8 Schalter, 8stellige 7-Segment-Anzeige und einen Hexa-Nummernblock). Zuhause habe ich dann auf meinem C64 noch einige Sachen in Assembler gemacht, nur so aus Spaß.
Das war allerdings noch recht einfach, weil man nahezu alles direkt Addressieren konnte, Bildschirmspeicher, RAM etc.
Danach habe ich mich nie wieder damit beschäftigt.

Mittlerweile hat sich natürlich viel verändert, und mit meinem damaligen Basiswissen kann ich heute nicht mehr viel anfangen, selbst wenn ich meine Unterlagen aus der Lehre wieder ausgrabe.

Daher meine Frage: könnt ihr gute Dokus, Tutorials oder Bücher empfehlen, um sich in dieses Thema wieder etwas einzuarbeiten, wo auch auf die Besonderheiten, die gegenüber der früheren Architektur, heute unter Windows eingegangen wird. Ich will damit natürlich jetzt nicht groß was machen, aber es würde mich schon interessieren in dem Bereich mein Wissen etwas aufzufrischen, und auch mal auszuprobieren, ob ich das heute noch verstehen würde. Wie gesagt, ist halt schon ewig her.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#5

AW: Assembler-Rätsel

  Alt 8. Apr 2020, 05:48
@Maekkelrajter: Du solltest den Fall limit<0 noch abfangen.

@Hobbycoder: Nichts für ungut, aber hättest Du nicht ein eigenes Thema aufmachen können?
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#6

AW: Assembler-Rätsel

  Alt 8. Apr 2020, 15:36
@Maekkelrajter: Du solltest den Fall limit<0 noch abfangen.
Darauf hatte ich verzichtet, da weiter unten im Code der Vergleich des Substr mit dem zu durchsuchenden Teilstring durchgeführt wird:

Delphi-Quellcode:
      
       mov ebx, [eax-4] //Length(Substr)
       sub esi, ecx //effective length of Str (= length(str) - offset)
       add edx, ecx //addr of the first AnsiChar at starting position
       cmp esi, ebx
       jl @Past //jump if EffectiveLength(Str)<Length(Substr)
       
       [...]
@Past:
       pop ebx
       pop esi
@Nil:
       xor eax, eax
       jmp @done
Falls 'EffectiveLength(Str) < Length(Substr)', was bei negativem 'Limit' der Fall wäre, erfolgt der Ausstieg mit Result =0.
Die von dir vorgeschlagene Variante hätte zur Folge, dass auch bei allen Limit-Werten < 0 der limit-Wert einfach ignoriert wird und die Suche dennoch durchgeführt wird.
Deshalb habe ich das ganze Design noch einmal überarbeitet. Die Vorbelegung der Parameter wurde entfernt, ebenso die Null-Prüfung von 'Limit'. Alle Limit-Werte, die kleiner oder gleich Offset sind führen jetzt zu einem Ende mit Result = 0, ebenso wenn Offset kleiner 1 ist.
Für den geplanten speziellen Einsatz dieser Funktion ist das so völlig ausreichend:
Delphi-Quellcode:
      

function PosInLimits(const SubStr, Str: RawByteString; Offset,Limit:Integer): Integer;
asm
       test eax, eax
       jz @Nil
       test edx, edx
       jz @Nil
       dec ecx
       jl @Nil

       push esi
       push ebx

       mov esi, [edx-4] //Length(Str)

       mov ebx, limit // limit holen
       cmp ebx, esi // limit >= Length(Str)?
       jge @IgnoreLimit // limit ignorieren
       mov esi, ebx // limit übernehmen anstelle von Length(Str)
@IgnoreLimit:

       mov ebx, [eax-4] //Length(Substr)
       sub esi, ecx //effective length of Str (= length(str) - offset)
       add edx, ecx //addr of the first AnsiChar at starting position
       cmp esi, ebx
       jl @Past //jump if EffectiveLength(Str)<Length(Substr)

       [usw.]
Trotzdem Danke für den Hinweis!

Gruß LP
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:34 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz