Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   ASM - PChars vergleichen (https://www.delphipraxis.net/78600-asm-pchars-vergleichen.html)

Neutral General 7. Okt 2006 17:20


ASM - PChars vergleichen
 
Ich versuche grad eine Funktion zu schreiben die überprüft ob das passwort richtig ist.. naja in der praxis wohl eher unnützlich so wies gemacht wird aber ist ja nur zum üben :mrgreen:

mit cmp geht das ja nicht.. Dann hab ich mich im Inet umgeguckt (bzw Links von Balus asm tut^^) und bin darauf gestoßen:

Zitat:

CMPS (Vergleich zweier Stringelemente)

Syntax: CMPSB, CMPSW
Beschreibung: CMPS vergleicht ein Stringelement (Byte oder Wort) aus dem, durch das Registerpaar DS:SI adressierten, Quellstring mit dem, durch das Registerpaar ES:DI adressierten, Zielstring. In Abhängigkeit vom Zustand des Richtungsflags werden das SI- und das DI-Register um 1 (Byte) oder 2 (Wort) erhöht (DF=0) oder verringert (DF=1).
Operanden: Keine
Beispiel:
CLD
LEA SI,quellstring
LEA DI,zielstring
CMPSB
Bemerkung: CMPS vergleicht die beiden Operanden, indem er wie CMP den Quelloperanden vom Zieloperanden abzieht. Auch hier wird das Ergebnis durch Setzen der Statusflags angezeigt.

Um mehr als ein Element zu vergleichen, muß dem CMPS-Befehl ein REPE bzw. ein REPNE vorangestellt und die Anzahl der maximal durchzuführenden Vergleiche im CX-Register übergeben werden. Im ersten Fall wird der Vergleich solange wiederholt, bis CX gleich null oder die beiden Elemente nicht mehr übereinstimmen. Im zweiten Fall werden die beiden Strings solange verglichen, bis CX gleich null ist oder zwei Elemente übereinstimmen.
Delphi-Quellcode:
function PW(A: PChar): Pchar;
asm
 jmp @go
 @pw: DB 'geheim',0 // Das Passwort
 @sne: DB 'ne ungleich!',0 // Result wenn falsch
 @sja: DB 'jo is richtig :)',0 // Result wenn richtig
 @go: CLD // ab hier wirds komisch^^
      mov ESI,A // lea si,a geht nicht weil lea nicht geht und weil si zu klein ist
      lea EDI,@pw // di zu klein
      cmpsb   // vergleichen
      jne @ne // kann man das mit jne machen?
      LEA EAX,@sja // Result := @sja
 RET
 @ne: LEA EAX,@sne // Result := @sne
end;
Die Fragen/Probleme stehn schon alle im Quelltext eigentlich :|

Gruß
Neutral General

Neotracer64 7. Okt 2006 17:38

Re: ASM - PChars vergleichen
 
Tausche mal CMPSB mit CMPSD aus. ;)

Neutral General 7. Okt 2006 17:43

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Neotracer64
Tausche mal CMPSB mit CMPSD aus. ;)

compiliert zwar aber ändert insgesamt irgendwie nichts :(

Dax 7. Okt 2006 17:44

Re: ASM - PChars vergleichen
 
Kleb ein REPE bzw REPNE davor ;)

Neotracer64 7. Okt 2006 17:46

Re: ASM - PChars vergleichen
 
Stimmt hab falsch gedacht.
Das sollte gehen:

Delphi-Quellcode:
jmp @go
@pw: DB 'geheim',0 // Das Passwort
@sne: DB 'ne ungleich!',0 // Result wenn falsch
@sja: DB 'jo is richtig :)',0 // Result wenn richtig
@go: CLD
      mov ESI,A
      lea EDI,@pw
      mov ecx, 6
      repe cmpsb
      jne @ne
      LEA EAX,@sja
RET
@ne: LEA EAX,@sne
Problem: geheim2 wird auch akzeptiert.

Balu der Bär 7. Okt 2006 17:49

Re: ASM - PChars vergleichen
 
[OT]
Delphi-Quellcode:
// lea si,a geht nicht weil lea nicht geht und weil si zu klein ist
Richtig erkannt, und da ich annehme das du unter Win32 programmierst wirst du immer ESI nehmen müssen. ;) [/OT]

Neutral General 7. Okt 2006 17:51

Re: ASM - PChars vergleichen
 
ok danke...

Delphi-Quellcode:
mov ecx, 6
aber wofür soll das gut sein?

Das REPE versteh ich auch noch nicht aber da guck ich auf der Seite mal nach was das bringt :)

Gruß
Neutral General

Neotracer64 7. Okt 2006 18:02

Re: ASM - PChars vergleichen
 
Du weisst ja bereits, dass jedes Zeichen einen Byte belegt.
cmpsb vergleicht immer nur ein Zeichen.
Damit mehr Zeichen vergleicht werden können schreibt man ein REPE davor.
Es wiederholt den befehl cmpsb sooft wie es in ECX steht oder solange beide Zeichenketten noch gleich (EQUAL) sind.
Und da 'geheim' 6 Zeichen lang ist, habe ich ne 6 genommen.
Und damit nicht immer das erste Zeichen von den beiden Strings verglichen wird, inkrementiert REPE auch noch autmatisch die Adressen in ESI und EDI.

Neutral General 7. Okt 2006 18:23

Re: ASM - PChars vergleichen
 
Ok danke euch allen :)

Aber warum funktioniert geheim2 auch?
Kann man das irgendwie umgehen?

Amateurprofi 7. Okt 2006 18:31

Re: ASM - PChars vergleichen
 
Neutral General,

Ich würde als Ergebnis der Funktion nicht einen PChar sondern einen Boolean Wert verwenden.
Ansonsten müßtest Du nach Rückkehr aus der Prüfroutine noch prüfen, ob der PChar auf den
Text 'jo is richtig :)' zeigt.

Ich denke der Sinn der Prüfroutine ist, zu prüfen ob das Password richtig ist, um dann entsprechend reagieren zu können, und nicht nur den Text auszugeben.
Und ESI, EDI sollen nicht verändert werden.
So sollte es funktionieren (habs nicht geprüft !)

Delphi-Quellcode:
function PW(A: PChar):Boolean;
asm
      jmp  @go
@pw: DB 'geheim',0  // Das Passwort
@go: push esi     // Register retten, dürfen nicht verändert werden
      push edi
      mov  esi,eax // Adresse A
      lea  edi,@pw // Adresse PW
      cld           // 'Suchrichtung' vorwärts
      mov  ecx,7    // 7 Zeichen (einschl. 0 sind zu prüfen)
      repe cmpsb   // vergleicht solange, bis entweder ECX Zeichen geprüft sind, oder Ungleichheit festgestellt wurde
      sete al      // setzt result dann=1 (true), wenn ZF=1 ist
      pop  edi
      pop  esi
end;

Neutral General 7. Okt 2006 18:33

Re: ASM - PChars vergleichen
 
Ok danke... wollte es auch eigentlich mit Boolean machen aber da ich noch nicht so viel Ahnung von Booleans in ASM hab (eigentlich gar keine^^) aber dafür von PChars, hab ichs erstmal so gemacht :mrgreen: Also im Ernstfall würd ich ja für sowas auch nie im Leben en PChar oder nen String nehmen :lol:

Wobei es nett wäre wenn du die neu hinzugefügten Zeilen erklären würdest :shock: :wiejetzt:
Ach ja du musst bei bei dem Code jne durch je ersetzen ;)^^

3_of_8 7. Okt 2006 19:10

Re: ASM - PChars vergleichen
 
Ein Boolean ist nichts anderes als ein Byte. Nur dass er normalerweise nur $00 oder $FF enthält.

Amateurprofi 7. Okt 2006 19:24

Re: ASM - PChars vergleichen
 
nein, das jne war für den Fall gedacht daß repe cmpsb mit ZF=0 beendet wird. Das dann folgende cmp sollte prüfen, ob das letzte geprüfte Zeichen im zu prüfenden String das Ende-Byte war. Da hab ich mich durch vorherige Kommentare aufs Glatteis locken lassen.

Ich habe meinen Beitrag noch mal überarbeitet.

so wie es jetzt im Beitrag steht sollte es funktionieren.
repe cmpsb vergleicht solange bis Ungleichheit festgestellt wird, maximal aber 7 Zeichen (einschließlich Nullbyte am Ende der Strings). Wenn also nach Abarbeitung dieses Befehlt (besser der Befehlskombination) ZF=1 ist, dann wurden 7 Zeichen überprüft und alle Zeichen waren identisch. ZF kann nur in folgenden Fällen = 0 sein.
1) A ist länger als PW. Dann ergibt der Vergleich Nullbyte aus PW vs. Zeichen aus A ein false.
2) A ist kürzer als PW. Dann ergibt der Vergleich Zeichen aus PW vs. Nullbyte aus A ein false.
3) A und PW sind gleichlang, aber der Vergleich eines der Zeichen aus A und PW ergibt false.

Amateurprofi 7. Okt 2006 19:26

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von 3_of_8
Ein Boolean ist nichts anderes als ein Byte. Nur dass er normalerweise nur $00 oder $FF enthält.

Nein, $00 für False, $01 für True.

Muetze1 7. Okt 2006 22:40

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Amateurprofi
Zitat:

Zitat von 3_of_8
Ein Boolean ist nichts anderes als ein Byte. Nur dass er normalerweise nur $00 oder $FF enthält.

Nein, $00 für False, $01 für True.

Sollte und nicht ist!

False = $00, True <> $00

Und nur so, kann man ordentlich arbeiten. Es gibt genug Dinge in der VCL die nicht eine $01 bei True zurück geben! Siehe auch die ständigen Hinweise zum = True Vergleich in If Abfragen.

Dax 7. Okt 2006 22:59

Re: ASM - PChars vergleichen
 
Dann müsste Delphi aber doch bei sowas wie "not a" das ganze direkt in "not a" als Maschinencode umsetzen und nicht "xor a, 1" :gruebel: Wo käm man da hin, wenn "(not true) <> false" :mrgreen:

Neutral General 8. Okt 2006 10:07

Re: ASM - PChars vergleichen
 
Delphi-Quellcode:
sete al      // setzt result dann=1 (true), wenn ZF=1 ist
Die Zeile versteh ich von der Syntax her irgendwie nicht ganz...
Sete heißt doch bestimmt "Set if Equal" oder? AL ist ein register... aber was hat AL mit ZF zu tun (ZF = Undefinierter Bezeichner) und warum setzt es al auf 1 wenn ZF=1 ist... wo in dieser Zeile erkennt man

Delphi-Quellcode:
if ZF=1 then
 ...
?

AL ist ja der Register um Booleans zurückzugeben, bzw um Booleans zu schreiben zu lesen weil SizeOf(Boolean) = 1 = AL ne ?

Gruß
Neutral General

Balu der Bär 8. Okt 2006 10:11

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Neutral General
Sete heißt doch bestimmt "Set if Equal" oder? AL ist ein register... aber was hat AL mit ZF zu tun (ZF = Undefinierter Bezeichner) und warum setzt es al auf 1 wenn ZF=1 ist...

Set if equal ist richtig. Mit ZF ist wohl das Zero-Flag gemeint.

3_of_8 8. Okt 2006 10:16

Re: ASM - PChars vergleichen
 
cmp subtrahiert die beiden Operanden.

Sinnvollerweise wird dann das Sign- und Zero-Flag gesetzt bzw. nicht gesetzt.

Dann entsprechen folgende Operatoren folgenden Flags:
<: SF=1
<=: SF=1 oder ZF=1
=: ZF=1
>=: SF=0
>: SF=0 und ZF=0
<>: ZF=0

Neutral General 8. Okt 2006 10:18

Re: ASM - PChars vergleichen
 
ahhh :idea: :mrgreen:

Ok ich glaube ich habs verstanden. Nur noch eine Frage: SF = ? :)

Balu der Bär 8. Okt 2006 10:38

Re: ASM - PChars vergleichen
 
Sign-Flag.

himitsu 8. Okt 2006 10:48

Re: ASM - PChars vergleichen
 
Liste der Anhänge anzeigen (Anzahl: 2)
is zwar nicht fertig und noch lange nicht perfekt, aber etwas kann man dennoch erkennen ._.

Amateurprofi 8. Okt 2006 14:20

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Muetze1
Zitat:

Zitat von Amateurprofi
Zitat:

Zitat von 3_of_8
Ein Boolean ist nichts anderes als ein Byte. Nur dass er normalerweise nur $00 oder $FF enthält.

Nein, $00 für False, $01 für True.

Sollte und nicht ist!

False = $00, True <> $00

Und nur so, kann man ordentlich arbeiten. Es gibt genug Dinge in der VCL die nicht eine $01 bei True zurück geben! Siehe auch die ständigen Hinweise zum = True Vergleich in If Abfragen.

Thomas,
das kann schon sein daß Funktionen bei unsauberer Programmierung für True etwas anderes als $01 zurückgeben,
aber das war hier nicht gefragt.
Die Frage war, was ein Boolean Wert ist, und unter Delphi ist für Boolean-Werte definiert 0=False und 1=True.
Die Tatsache, daß intern bei der Prüfung auf 0 geprüft wird und alles, was nicht 0 ist als True erkannt wird ändert nichts an dieser Definition. Es ist ja z.B. auch klar, daß 2 * 2 = 4 ist, und wenn jemand eine Multiplikations-Funktion so programmiert hat, daß sie für 2 * 2 als Resulttat 27 zurückgibt, dann ändert das auch nichts daran, daß 2 * 2 = 4 ist und bleibt.
Außerdem, wenn schon von unsauberer Programmierung die Rede ist : Es ist ja nicht ausgeschlossen, daß jemand eine Routine schreibt, in der er prüft ob ein als Boolean definierter Wert = 1 ist, und dann alles, was nicht 1 ist, als False interpretiert und dann ist Deine Aussage "und nur so kann man ordentlich arbeiten" nicht viel wert.

Amateurprofi 8. Okt 2006 14:38

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Balu der Bär
Zitat:

Zitat von Neutral General
Sete heißt doch bestimmt "Set if Equal" oder? AL ist ein register... aber was hat AL mit ZF zu tun (ZF = Undefinierter Bezeichner) und warum setzt es al auf 1 wenn ZF=1 ist...

Set if equal ist richtig. Mit ZF ist wohl das Zero-Flag gemeint.

Ja, das ist gemeint.
Und die Benennung ZF ist nicht meine Erfindung sondern das Zero-Flag wird nun mal mit ZF bezeichnet.

@NeutralGeneral
Zitat:

Die Zeile versteh ich von der Syntax her irgendwie nicht ganz...
Sete heißt doch bestimmt "Set if Equal" oder? AL ist ein register... aber was hat AL mit ZF zu tun (ZF = Undefinierter Bezeichner) und warum setzt es al auf 1 wenn ZF=1 ist... wo in dieser Zeile erkennt man
sete al setzt al=1, wenn ZF=1 ist und setzt al=0 wenn ZF=0 ist.

hier ein Auszug aus Intel's Instruction Set Reference.
kann man bei Intel als PDF-File (ca. 7.6 MB) downloaden. (einfach zu suchen aber sehr schwer zu finden)

SETcc—Set Byte on Condition
Description
Set the destination operand to 0 or 1 depending on the settings of the status flags (CF, SF, OF,
ZF, and PF) in the EFLAGS register. The destination operand points to a byte register or a byte
in memory. The condition code suffix (cc) indicates the condition being tested for.
The terms “above” and “below” are associated with the CF flag and refer to the relationship
between two unsigned integer values. The terms “greater” and “less” are associated with the SF
and OF flags and refer to the relationship between two signed integer values.
Opcode Instruction Description
0F 97 SETA r/m8 Set byte if above (CF=0 and ZF=0)
0F 93 SETAE r/m8 Set byte if above or equal (CF=0)
0F 92 SETB r/m8 Set byte if below (CF=1)
0F 96 SETBE r/m8 Set byte if below or equal (CF=1 or ZF=1)
0F 92 SETC r/m8 Set if carry (CF=1)
0F 94 SETE r/m8 Set byte if equal (ZF=1)
0F 9F SETG r/m8 Set byte if greater (ZF=0 and SF=OF)
0F 9D SETGE r/m8 Set byte if greater or equal (SF=OF)
0F 9C SETL r/m8 Set byte if less (SF<>OF)
0F 9E SETLE r/m8 Set byte if less or equal (ZF=1 or SF<>OF)
0F 96 SETNA r/m8 Set byte if not above (CF=1 or ZF=1)
0F 92 SETNAE r/m8 Set byte if not above or equal (CF=1)
0F 93 SETNB r/m8 Set byte if not below (CF=0)
0F 97 SETNBE r/m8 Set byte if not below or equal (CF=0 and ZF=0)
0F 93 SETNC r/m8 Set byte if not carry (CF=0)
0F 95 SETNE r/m8 Set byte if not equal (ZF=0)
0F 9E SETNG r/m8 Set byte if not greater (ZF=1 or SF<>OF)
0F 9C SETNGE r/m8 Set if not greater or equal (SF<>OF)
0F 9D SETNL r/m8 Set byte if not less (SF=OF)
0F 9F SETNLE r/m8 Set byte if not less or equal (ZF=0 and SF=OF)
0F 91 SETNO r/m8 Set byte if not overflow (OF=0)
0F 9B SETNP r/m8 Set byte if not parity (PF=0)
0F 99 SETNS r/m8 Set byte if not sign (SF=0)
0F 95 SETNZ r/m8 Set byte if not zero (ZF=0)
0F 90 SETO r/m8 Set byte if overflow (OF=1)
0F 9A SETP r/m8 Set byte if parity (PF=1)
0F 9A SETPE r/m8 Set byte if parity even (PF=1)
0F 9B SETPO r/m8 Set byte if parity odd (PF=0)
0F 98 SETS r/m8 Set byte if sign (SF=1)
0F 94 SETZ r/m8 Set byte if zero (ZF=1)

Amateurprofi 8. Okt 2006 15:11

Re: ASM - PChars vergleichen
 
Nachtrag zu vorherigem Beitrag.

Hier können Interessierte die Intel Manual downloaden.

Intel Specs

himitsu 8. Okt 2006 16:03

Re: ASM - PChars vergleichen
 
Nochmal zu den boolischen Typen:

oben die Konstanten
und unten die Auswertung

Code:
Definition - Boolean:
True = $01
False = $00

<>$00 - True
 =$00 - False



Definition - ByteBool:
True = $FF
False = $00

<>$00 - True
 =$00 - False



Definition - LongBool:
True = $FFFFFFFF
False = $00000000

<>0 - True
 =0 - False

Muetze1 8. Okt 2006 17:31

Re: ASM - PChars vergleichen
 
Zitat:

Zitat von Amateurprofi
das kann schon sein daß Funktionen bei unsauberer Programmierung für True etwas anderes als $01 zurückgeben,
aber das war hier nicht gefragt.

Nun gut, dann haben wir also festgestellt, dass Borland selber unsauber programmiert nach deiner Ansicht. Das Problem auf das ich hinweisen wollte ist, dass er dieses nicht so starr lernen sollte, schliesslich gibt es VCL Routinen welche bei True nicht 1 zurück geben. Und wenn er jetzt nur den "sauberen" Weg von dir lernt und immer fest dahingehend programmiert, dann kann er damit später auch Probleme bekommen. Pauschal zu sagen $01 ist true und wenn nicht ist es schlecht programmiert ist eine schlechte Lösung.

Er wurde ja nun darauf hingewiesen und gut ist.

himitsu 8. Okt 2006 18:35

Re: ASM - PChars vergleichen
 
Und wenn man sich das MSDN/PSDK durchließt, dann heißt es oftmal "wenn Result ungleich 0" und "Result = 0".
Und nich "Result = 1", wenn der Typ BOOL/LongBool ist.

Amateurprofi 8. Okt 2006 21:51

Re: ASM - PChars vergleichen
 
@Muetze1,

Irgendwie habe ich das Gefühl, Du willst mich nicht verstehen.

Die Diskussion (oder sollte ich schreiben 'die Debatte'?) begann mit einem Beitrag 3_Of_8s in dem er schrieb
Zitat:

Ein Boolean ist nichts anderes als ein Byte. Nur dass er normalerweise nur $00 oder $FF enthält.
und das hatte ich kommentiert mit
Zitat:

Nein, $00 für False, $01 für True.
Mit keiner Silbe, weder von 3_Of_8 noch von mir, wurde auch nur ansatzweise erwähnt, man müsse einen Boolean daraufhin prüfen, ob er = 1 ist. Es wurde auch nicht über ByteBool, WordBool oder LongBool geschrieben, sondern ausschließlich darüber, welche Werte eine BOOLEAN-Variable NORMALERWEISE enthält. 3_Of_8 schrieb "normalerweise nur $00 oder $FF, und nur das "oder $FF" wurde von mir kommentiert.

Nun, spätestens nach himitsus Beitrag wissen wir, wie ein Boolean definiert ist
Zitat:

Definition - Boolean:
True = $01
False = $00
Und, Muetze1, was das lernen betrifft :
Ich will niemanden lehren, wie etwas gemacht wird. Jedoch, wenn es so wäre, dann hielte ich es für besser, zu lehren, daß man (es geht hier um Funktionen die in Assembler geschrieben sind) für False den Wert $00 und für True $01 (und nicht irgendeinen Wert der <> 0 ist) zurückgeben sollte.

Um die geschätzten anderen User nicht weiter mit dieser sinnlosen Debatte einzubringenanderdurch durcheinanderzubringen, und weil es inzwischen offtopic wird, sollten wir es jetzt dabei belassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:53 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