Entwickler-Ecke

Algorithmen, Optimierung und Assembler - inlineasm-loop problem


MagicRain - Do 23.07.09 00:43
Titel: inlineasm-loop problem
Hallo Leute ich habe leider ein problem hier mal mein code....so exception hab ich killed aber nun ..:S

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.Button1Click(Sender: TObject);
var
  A, i ,buff : Integer;
  text : String;
begin
  A := 0;
  buff := 0;
  //=======================================
  text := edit1.Text;
//=======================================
  for i := 1 to Length(text) do
    A := Ord(text[i]);
  asm
    MOV EAX, A
    add eax,eax
    mov buff, EAX
  end;
//=======================================
  Edit2.Text := IntToStr(buff);
end;


Mein fehler....
Also er packt das add nicht in den loop ka wieso....schau hier...

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
00465FE1  |.  BA 01000000   MOV EDX,1
00465FE6  |>  8B4D F4       /MOV ECX,DWORD PTR SS:[EBP-C]
00465FE9  |.  0FB74C51 FE   |MOVZX ECX,WORD PTR DS:[ECX+EDX*2-2] ;//Ord(text[i]);
00465FEE  |.  894D FC       |MOV DWORD PTR SS:[EBP-4],ECX       ;//mov buff,eax
00465FF1  |.  42            |INC EDX
00465FF2  |.  48            |DEC EAX
00465FF3  |.^ 75 F1         \JNZ SHORT 00465FE6
00465FF5  |>  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
00465FF8  |.  01C0          ADD EAX,EAX  <<<<<<<<<< da is das add ?? wtf :(


Ich hoffe jemand weiß was ich falsch gemacht habe und kann mir helfen alles klar bis dann...


HelgeLange - Do 23.07.09 00:56

weil Du den ASM Block nicht mit in die Schleife genommen hast, würde ich mal sagen. Versuch es mal mit Begin und End bei der Schleife...


MagicRain - Do 23.07.09 01:18

Danke das war es wohl fast....nur noch nicht ganz....


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.Button1Click(Sender: TObject);
var
  A, i ,buff : Integer;
  text : String;
begin
  A := 0;
  buff := 0;
  //=======================================
  text := edit1.Text;
//=======================================
  for i := 1 to Length(text) do
  begin
    A := Ord(text[i]);
    asm
      MOV EAX, A
      add eax,eax
      mov buff, EAX
    end;
  end;
//=======================================
  Edit2.Text := IntToStr(buff);
end;


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
00465FE3  |.  B9 01000000   MOV ECX,1
00465FE8  |>  8B45 F4       /MOV EAX,DWORD PTR SS:[EBP-C]
00465FEB  |.  0FB74448 FE   |MOVZX EAX,WORD PTR DS:[EAX+ECX*2-2]
00465FF0  |.  8945 FC       |MOV DWORD PTR SS:[EBP-4],EAX
00465FF3  |.  8B45 FC       |MOV EAX,DWORD PTR SS:[EBP-4]
00465FF6  |.  01C0          |ADD EAX,EAX <<<<<<<<<<<<<< müsste wohl eine zeile höher ?!?!?
00465FF8  |.  8945 F8       |MOV DWORD PTR SS:[EBP-8],EAX
00465FFB  |.  41            |INC ECX
00465FFC  |.  4A            |DEC EDX
00465FFD  |.^ 75 E9         \JNZ SHORT 00465FE8


Also was hab ich vor das sollte ich euch vlt mal sagen hehe..
ich will einfach jedes ascii char von dem text addieren also zb

Quelltext
1:
2:
3:
4:
5:
text = hallo
hallo = 68 61 6C 6C 6F 
== 68 + 61 + 6C + 6C + 6F = 210 == 528 <<< valid!

also müsste die schleife jedes zeichen einlesen Ord(text[i]) und addieren ADD EAX,EAX....


HelgeLange - Do 23.07.09 01:36

Naja, dazu musst Du aber auch den inhalt von Buff mal zum Addieren benutzen. Du schiebst ja nur den inhalt von A in EAX, addierst dann EAX zu EAX (= 2*EAX) und legst es dann in Buff ab, was den vorhergehenden Wert überschreibt...
Schrteib Dir Buff in EDX oder so und addierst dann EAX mit EDX und scheibst das dann wieder in Buff...


MagicRain - Do 23.07.09 01:53

Kannst du vlt mal ein code beispiel zeigen ich bekomme das so nicht hin...bahnhof..:(

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
  for i := 1 to Length(text) do
  begin
    A := Ord(text[i]);
    asm
      MOV EAX, A
      mov buff, EAX
      mov edx, buff
      add eax,edx
      mov buff,eax
    end;

so gehts auch net oO????? wirklich ka deswegen frag ich ja :P


HelgeLange - Do 23.07.09 02:56

Ich glaube, Du weisst garnicht, was Du wirklich machst.
Schreib es doch einfach in Delphi, wenn Du kein Assembler kannst. :P

ich schreib Dir mal, was Du machst, es ist ein Logik-Fehler...


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
for i := 1 to Length(text) do
  begin
    A := Ord(text[i]);
    asm
      MOV EAX, A            // Inhalt von A nach EAX schieben, EAX = A
      mov buff, EAX         // Inhalt von EAX nach Buff schieben, Buff = EAX = A
      mov edx, buff         // Inhalt von Buff nach EDX, EDX = EAX = A = Buff
      add eax,edx           // Addiere EDX und EAX, da EAX und EDX jeweils den Wert von A haben = 2 * A
      mov buff,eax          // nun schiebst Du den Wert von EAX nach BUff, Buff = 2 * A
    end;


uall@ogc - Do 23.07.09 07:20


Delphi-Quelltext
1:
2:
3:
buf := 0;
for i := 1 to Length(text) do
  buf := buf + Ord(text[i]);


BenBE - Do 23.07.09 07:46


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
asm
    PUSH    ESI
    XOR     EAX, EAX
    MOV     ESI, DWORD PTR [Text]
    TEST    ESI, ESI
    JZ      @@e
    MOV     ECX, DWORD PTR [ESI - 4]
@@l:
    MOVZX   EDX, BYTE PTR [ESI]
    ADD     EAX, EDX
    INC     ESI
    DEC     ECX
    JNZ     @@l
@@e:
    POP     ESI
    MOV     DWORD PTR [Buff], EAX
end;


Schleife ist gleich drin ... Aber wie die Vorredner schon sagten: Ohne ASM-Kenntnisse sollte man das nicht verwenden.


Marc. - Do 23.07.09 13:45

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
WinXp Pro
Delphi 7, Delphi 2009

Damit das Konstrukt vom user profile iconBenny Unicode-Fähig wird, musst du das ESI-Register jeweils um 2 erhöhen. Unicode verwendet nämlich pro Zeichen 8, statt wie Ansi 4 Bytes pro Char.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
@@l:
    MOVZX   EDX, BYTE PTR [ESI]
    ADD     EAX, EDX
    INC     ESI // {ADD ESI, 2} 
    DEC     ECX
    JNZ     @@l


BenBE - Do 23.07.09 14:00

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
WinXp Pro
Delphi 7, Delphi 2009

Damit das Konstrukt vom user profile iconBenny Unicode-Fähig wird, musst du das ESI-Register jeweils um 2 erhöhen.

UND man muss den MOVZX-Befehl mit WORD PTR statt BYTE PTR schreiben ...

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:
Unicode verwendet nämlich pro Zeichen 8, statt wie Ansi 4 Bytes pro Char.

Ähem!!! So redundant ist nicht mal Unicode!

user profile iconMarc. hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
@@l:
    MOVZX   EDX, WORD PTR [ESI] //Anpassen je nach Delphi-Version; ggf. mit bedingter Compilierung ...
    ADD     EAX, EDX
    ADD     ESI, SizeOf(Char)
    DEC     ECX
    JNZ     @@l


Marc. - Do 23.07.09 14:15

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Ähem!!! So redundant ist nicht mal Unicode!

Ähhhm... ich meinte natürlich je 16 und 8 Bit respektive 2 oder 1 Byte. :?

Edit: Tags repariert ...


MagicRain - Do 23.07.09 19:48

Alles klar DANKE EUCH :)


HelgeLange - Do 23.07.09 20:06

@ BenBE & Marc. : Interessant-Faktor 10+, Lernfaktor -2

Wenn ich ihm hätte die Lösung hinschreiben wollen, hätte ich das gemacht, ich wollte, dass er den Fehler selbst versteht. :evil:


Marc. - Do 23.07.09 20:27

user profile iconHelgeLange hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich ihm hätte die Lösung hinschreiben wollen, hätte ich das gemacht, ich wollte, dass er den Fehler selbst versteht. :evil:

Pardon. Nächste Mal wird wieder drauf geachtet. ;)

@user profile iconMagicRain: Kannst du die Funktionsweise des Algos auch in eigenen Worten beschreiben? :P


MagicRain - Do 23.07.09 20:44

Habe es heute Morgen dann so gelöst...das bissel schlafen tat wohl doch gut :D


uall@ogc - Do 23.07.09 22:12

Steht immer nochm im Raum warum du das unbedingt in Assembler haben willst. Meine Variante sollte genau dasselbe machen.


MagicRain - Do 23.07.09 22:15

Hat nun nichts mit dem ADD zu tun hatte nur schon viele befehler auch in Schleifen die in Assembler waren wie ROL und sowas was ich dann irgendwie in Delphi hinbekommen musste..Also alles mehr Lehrn zwecke wollte einfach lernen endlich mit Delphi+ASM zurecht zu kommen und nun klaptt es hehe. danke


Flamefire - Do 23.07.09 22:57

trotzdem: beschäftige dich erst mal intensiver mit programmieren allgemein.
solche fehler sollten nicht passieren.
und dann auch noch inline asm probieren...

BTW: das XOR EDX,EDX ist redundant--->weg damit


MagicRain - Do 23.07.09 23:45

Ach.. wenn ich das xor weg nehme läuft das app nicht weil iein shit wert in edx steckt ohne es...inlineasm rockz


BenBE - Fr 24.07.09 00:17

Kann mir sogar recht gut vorstellen, welcher Wert das ist :P Aber WARUM mischst Du ASM und normalen Source? ENTWEDER man schreibt die gesamte Routine in ASM ODER man lässt es ganz. Mischen ist das schlimmste, was man tun kann. Zumal die Register-Belegungsregeln für gemischten Source mehr als kryptisch sind.


MagicRain - Fr 24.07.09 00:20

Joa da hast du wohl recht :roll: aber was mach ich wenn ich was coden will was es in Delphi nicht gibt aber in assambler schon oO?


HelgeLange - Fr 24.07.09 03:19

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Joa da hast du wohl recht :roll: aber was mach ich wenn ich was coden will was es in Delphi nicht gibt aber in assambler schon oO?


Bei Deinem jetzigen Kenntnisstand in Delphi wirst Du noch ein paar Jahre brauchen, bis Du an solche Grenzen stösst :p No offense ...


Flamefire - Fr 24.07.09 09:35

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Ach.. wenn ich das xor weg nehme läuft das app nicht weil iein shit wert in edx steckt ohne es...inlineasm rockz


ähm...
EDX=32Bit register
du schiebst buffer rein-->32bit wert

was soll da den wert verfälschen?


MagicRain - Fr 24.07.09 11:01

Ich hatte nur eine frage bzw problem und wollte da gerne hilfe haben das ich kein Delphi pro bin weiß ich selber aber ihr konntet ja alles gleich ohne zu Lehnen nech man nicht schlecht! Mir hätte es gelangt einfach bei meinem Problem zu helfen und nicht ob es gut ist oder was auch immer :(


BenBE - Fr 24.07.09 12:35

Beim Programmieren sollte man immer auch auf den Stil achten und nicht nur, ob es funktioniert. Ob es funktioniert und korrekt ist sind zwar wichtige Punkte, bei weitem aber nicht die einzigen ...


MagicRain - Fr 24.07.09 12:55

Ja das stimmt natürlich ja ich weiß wohl was ihr meint naja ihr habt ja recht....dann haben wir es ja jetzt :D


Flamefire - Fr 24.07.09 15:25

letzte anmerkung:
user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Joa da hast du wohl recht :roll: aber was mach ich wenn ich was coden will was es in Delphi nicht gibt aber in assambler schon oO?


Wie jetzt?
Hab bisher viele Programm reverst...es gab immer ein Delphi Äquivalent


MagicRain - Fr 24.07.09 15:28

Das zeig mir mal.... :roll:


Flamefire - Fr 24.07.09 15:58

andersrum:
Du hast behauptet, es gäbe etwas in ASM das delphi nicht hat
Sprich-->eine existenz behauptung
ich behaupte alles in asm geht auch in delphi
Sprich-->AllQuantifiziert

es ist einfacher ein gegenbeispiel zu finden, als alle ASM Befehle aufzuführen

Also finde einen ASM befehl zu dem ich kein Delphi äquivalent finde!


BenBE - Fr 24.07.09 21:46

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
andersrum:
Du hast behauptet, es gäbe etwas in ASM das delphi nicht hat
Sprich-->eine existenz behauptung
ich behaupte alles in asm geht auch in delphi
Sprich-->AllQuantifiziert

k, dann schreib mir mal bitte folgende Funktionalitäten in Delphi:
- asm RDTSC end;
- asm CPUID end;
- asm RDMSR; WRMSR end;

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
es ist einfacher ein gegenbeispiel zu finden, als alle ASM Befehle aufzuführen

Also finde einen ASM befehl zu dem ich kein Delphi äquivalent finde!

Weil aller guten Dinge 3 sind:
- asm IRET end;
- asm CLI end;
- asm STI end;

Und dazu hab ich jetzt grad nicht das Handbuch "Assembler Ge-Packt", was links neben mir steht bemüht. Hätte ich das getan, wären hier sicherlich noch ein paar mehr Sachen aufgeführt ...


MagicRain - Fr 24.07.09 22:01

Tja da bin ich dann ja mal sehr gespannt oh ja :) Dann zeig mal was du kannst aber du machst das ja in paar sekunden fertig nech?


Flamefire - Fr 24.07.09 23:02

ach komm magicrain. als wüsstest du was die instruktionen machen ;-)

nein ok. RDTSC sollte meiner meinung nach irgendwie richtung QueryPerformanceCounter gehen

aber gut ich gebe zu, bei diesen instruktionen finde ich grade nichts in delphi.

Allerdings 2 dinge: z.B. IRET usw. wird vermutlich in keinem delphi programm gebraucht. denke da eher an verwendung in treibern o.ä. die man dann eh in asm schreiben wird, oder?
2) ist es möglich, dass es möglichkeiten dafür auch in delphi gibt, aber halt etwas anders. in diesem fall geht es vermutlich 1:1 nicht (müsste zu lange suchen um es sicher zu sagen) vl ist es auch so wie der TEST befehl, der ohne den folgenden Jump auch nicht in delphi zu übersetzen ist.

trotzdem bleibt dabei: ein normales programm, dass man als asm vorliegen hat, kann man zu 99% in pure Delphi übersetzen.


MagicRain - Sa 25.07.09 04:31

bla bla bla.....mach mal weiter auf dicke hose du held...ich halt mich da jetzt raus muss ich mir net geben...


elundril - Sa 25.07.09 07:16

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:

- asm RDTSC end;


Instruction RDTSC returns the TSC in EDX:EAX. => Imho Äquivalent zu GetTickCount oder?


BenBE - Sa 25.07.09 11:41

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
ach komm magicrain. als wüsstest du was die instruktionen machen ;-)

Dafür gibt's Dokumentation :P

user profile iconelundril hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:

- asm RDTSC end;

Instruction RDTSC returns the TSC in EDX:EAX. => Imho Äquivalent zu GetTickCount oder?

Nope. GetTickCount liefert einen völlig anderen Wert. Mit Zeitmessung hat's aber was zu tun ;-)

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
nein ok. RDTSC sollte meiner meinung nach irgendwie richtung QueryPerformanceCounter gehen

Was denkst Du, was QueryPerformanceCounter intern aufruft ;-)

In Delphi kannst Du somit die Funktion nur nutzen, weil sie einmal in ASM geschrieben wurde.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
aber gut ich gebe zu, bei diesen instruktionen finde ich grade nichts in delphi.

Stammen alle aus der Kernel-Mode-Programmierung. Sicherlich, das war etwas gemein, Kernel-Mode-Programmierung von ASM anzuführen, für etwas, was in Delphi nicht geht; prinzipiell (und das hat user profile iconuall@ogc gezeigt) gehen Kernel-Mode-Geschichten aber auch mit Delphi, wenn man weiß, was man tut.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
Allerdings 2 dinge: z.B. IRET usw. wird vermutlich in keinem delphi programm gebraucht. denke da eher an verwendung in treibern o.ä. die man dann eh in asm schreiben wird, oder?

Treiber werden üblicherweise in C implementiert, wobei nur da, wo's notwendig ist mal eben ein paar Zeilen mit ASM gehackt werden. Schau Dir die Sources vom Linux-Kernel an: Das ist nahezu ausschließlich C-Code.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
2) ist es möglich, dass es möglichkeiten dafür auch in delphi gibt, aber halt etwas anders.

Die uallCollection wäre eine davon. Erfordert aber ein wenig Wissen darüber, was man tut.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
in diesem fall geht es vermutlich 1:1 nicht (müsste zu lange suchen um es sicher zu sagen)

Keiner der genannten Befehle kann in Delphi übersetzt werden, da die ersten 3 Befehle auf Spezialregister der CPU zugreifen (Das TSC ist nur ein weiteres MSR - Model Specific Register). Bei den letzten 3 Befehlen handelt es sich um Befehle zur Interrupt-Steuerung - auch das ein Bereich, für den es in Delphi keine Umsetzung gibt. Vergleichbar wären hier noch Critical Sections, die jedoch intern über Sprünge in den Kernel-Mode bzw. Interrupt-Sperren implementiert sind.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
vl ist es auch so wie der TEST befehl, der ohne den folgenden Jump auch nicht in delphi zu übersetzen ist.

Der Test-Befehl ist ohne Probleme in Delphi übersetzbar: Var1-Var2. Wichtig ist hier für eine konkrete Übersetzung aber der Kontext. Und um es vorwegzunehmen: TEST geht auch ohne Sprungbefehle zu nutzen:

Delphi-Quelltext
1:
2:
3:
4:
5:
asm
    TEST EAX, EAX
    SETZ AL
    MOVZX, EAX, AL
end;


Die Übersetzung wäre in diesem Fall:

Delphi-Quelltext
1:
EAX := ord(EAX <> 0);                    

Wobei Delphi diesen Code nie generieren würde ...

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
trotzdem bleibt dabei: ein normales programm, dass man als asm vorliegen hat, kann man zu 99% in pure Delphi übersetzen.

Dagegen hat auch niemand was gesagt. Ich hab nur deinen "ASM ist echte Teilmenge von Delphi"-Ausspruch widerlegt ...

@Flamefire: Pass auf beim Klugscheißen; das könnte jemand besser beherrschen :mrgreen:


Flamefire - Sa 25.07.09 14:46

ja gut zugegeben...ich hab halt dünnschiss und du legst ne richtig fette wurst xD

Zitat:
Was denkst Du, was QueryPerformanceCounter intern aufruft ;-)

ich weiß
darum hatte ich es geschrieben.
und auch wnn in QueryPerformanceCounter intern ein asm befehl steckt: aufruf von QueryPerformanceCounter ist delphi, oder? alos gilt das ganze ;-)

dann bei dem thema gleich mal:
ich hatte TEST EAX,xxx
JE z
immer übersetzt mit if (EAX AND xxx=0) dann springe
ist es denn echt eine subtraktion?
denn:
TEST EAX,2
JE z

springt ja nicht (nur) bei EAX=2 sonder auch bei eax=3,7 usw

Zitat:
Dagegen hat auch niemand was gesagt. Ich hab nur deinen "ASM ist echte Teilmenge von Delphi"-Ausspruch widerlegt

Ich habe nicht gesagt, dass es eine echte Teilmenge ist.
Ich habe gemeint sie sind gleichwertig. Denn Alles was in Delphi geht geht auch in ASM-->Delphi ist Teilmenge von ASM
Trivialerweise wahr, da Delphi "in ASM compiliert wird"
und ich habe behauptet, dass alles was in ASM geht auch in Delphi geht: ASM ist Teilmenge von Delphi
Wäre das war gilt: ASM=Delphi

dummerweise stimmt der 2. Teil halt doch nicht.
Ich habe die CPU spezifischen Befehle nicht bedacht.


BenBE - Sa 25.07.09 15:02

Ach, es fängt ja schon bei Dingen wie IN und OUT an. TP konnte die damals auch in Pascal-Syntax; Delphi kann die nicht mehr. (In TP7 waren die einfach als Array eingemappt). Und IN\OUT hat nicht vordergründig was mit der CPU zu tun, sondern eher mit Hardware-Steuerung.


MagicRain - Sa 25.07.09 16:07

Da hab ich auch ne frage zu und zwar folgender code...

CMP EAX,10
JNZ bla:

Wenn ich sowas in einen Loop packen möchte gibt es da noch andere möglichkeiten das zu verwürklichen auzer GOTO label...end exit oder oO ? Ach und das ich noch nicht so gut in Delphi bin weiß ich selber ich komm hier her um noch was zu lernen oder das mir jemand bei meinen fehlern hilft. Bis jetzt war das auch immer der fall bis auf jetzt wo ich dafür das ich anfänger und kein PROFI bin angemacht werde. Finde ich irgendwie schade dafür sollte ein Forum eig auch da sein...können ja net alle solche PROFIS sein nech...

Mfg


BenBE - Sa 25.07.09 16:15

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Da hab ich auch ne frage zu und zwar folgender code...

CMP EAX,10
JNZ bla:

Wenn ich sowas in einen Loop packen möchte gibt es da noch andere möglichkeiten das zu verwürklichen auzer GOTO label...

Ja.

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Bis jetzt war das auch immer der fall bis auf jetzt wo ich dafür das ich anfänger und kein PROFI bin angemacht werde. Finde ich irgendwie schade dafür sollte ein Forum eig auch da sein...können ja net alle solche PROFIS sein nech...

Mfg

Der Punkt ist ein anderer: Es geht den meisten hier darum, dass man zuerst Delphi ausreichend gut beherrschen sollte, bevor man überhaupt daran denkt, ASM als ein Mittel zur Problemlösung heranzuziehen, da man zuerst wissen sollte, was man mit der Sprache tun kann, bevor man mit anderen Sprachen nachhilft. Das Mischen von Sprachen sollte dabei so selten wie möglich erfolgen, da es extrem unübersichtlich werden kann und auf Grund von Eigenheiten des Compilers meist wesentlich ineffizienter wird, als eine rein in einer der Möglichkeiten formulierten Lösung.


MagicRain - Sa 25.07.09 16:31

Das ist schon richtig B! ich mach halt ziemlich oft sachen mit ASM und ja mischen ist wohl nicht so gut das stimmt schon aber wenn ich sachen habe die ich nicht besser weiß umzusetzen sehe ich da keine möglichkeit das anders zu machen mein Delphi-Basic wissen reicht wohl aber noch nicht aus. Aber deswegen komme ich ja hier her und frage euch wenn ich ein problem habe oder nicht mehr weiter weiß um als resultat was zu lernen... :)


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Da hab ich auch ne frage zu und zwar folgender code...

CMP EAX,10
JNZ bla:

Wenn ich sowas in einen Loop packen möchte gibt es da noch andere möglichkeiten das zu verwürklichen auzer GOTO label...

Ja.
Ja und wie :P wie kommt man auf sowas ? :S ich hab echt keine ahnung...


Martok - Sa 25.07.09 17:09

user profile iconMagicRain hat folgendes geschrieben Zum zitierten Posting springen:
Da hab ich auch ne frage zu und zwar folgender code...

CMP EAX,10
JNZ bla:

Wenn ich sowas in einen Loop packen möchte gibt es da noch andere möglichkeiten das zu verwürklichen auzer GOTO label...

Ja.

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
Der Punkt ist ein anderer: Es geht den meisten hier darum, dass man zuerst Delphi ausreichend gut beherrschen sollte, bevor man überhaupt daran denkt, ASM als ein Mittel zur Problemlösung heranzuziehen, da man zuerst wissen sollte, was man mit der Sprache tun kann, bevor man mit anderen Sprachen nachhilft.

Und in diesem besonderen Fall sollte man zumindest wissen, wie das Compilat des Hochsprachencompilers aussieht.

Dan wüsstest du, dass dein Sprung da oben (je nach Context, den verrätst du ja nicht) entweder eine Schleife oder ein If ist.


MagicRain - Sa 25.07.09 17:15

War ein schlechtes Beispiel soll ein IF darstellen. Also zum Beispiel so....

Delphi-Quelltext
1:
2:
3:
IF A < 10 then
Break;
IF A < 10 then goto...;

Gibt es für sowas noch andere lösungen oder nicht? Wenn ich zum Beispiel in einem loop eine Zeiler tiefer Springen will wenn das if erfüllt sein sollte oder geht das nur mit GOTO und zum Verlassen Break..?


Flamefire - Sa 25.07.09 17:51

ok jetzt mal qualitative hilfe von mir:

1) Jump befehle:
JMP - Unbedingter Sprung. Sollte Klar sein
JNZ, JNE (is das gleiche): Sprung wenn Zero Flag nicht gesetzt, also wenn ergebnis <>0 oder Operanden <> sind
JZ,JE : s.o. nur halt bei =0; A=B
2)
wenn du sowas hast:

Quelltext
1:
2:
3:
4:
5:
6:
7:
MOV EAX,[EBP+4] //oder was auch immer in EAX berechnet wurde
CMP EAX,10
JNZ LabelX
ADD EAX,5
//mache noch was
LabelX: ADD EAX,1
//Rest der Anweisungen

Dann als erstes gucken was da gemacht wird! und mit worten beschreiben:
Z.B.:
vergleiche EAX mit $10
wenn die ungleich sind springe über einen Code
wenn er nicht springt, Addiere 5 zu EAX
egal ob übersprungen oder nicht, mache immer das ab LabelX am Ende

Und DANN kommt der Delphi teil:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
if(EAX=$10then begin//Vergleiche EAX mit $10 und überspringe Code bei UNGLEICH!
EAX:=EAX+5;
//mache noch was
end;
EAX:=EAX+1;
//rest


MagicRain - Sa 25.07.09 18:04

Ah das hab ich jetzt verstanden danke für dein Beispiel kannst ja doch hilfreich sein :P :roll:


Flamefire - Sa 25.07.09 18:16

ja stell dir vor ;-)

PS: kurz dazu ob dus wirklich verstanden hast
übersetze mal bitte das hier in Delphi:

Quelltext
1:
2:
3:
4:
5:
6:
CMP EAX,10
JE @x1
ADD EAX,2
JMP @x2
@x1:Sub EAX,1
@x2://...


oder das:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
MOV ESI,12
MOV EAX,0
TEST ESI,ESI
JE @l2
@l1: ADD EAX,EAX
CMP EAX,$FFFF
JB @l2
SUB ESI
JNZ @l1
@l2://....


sind 2 häufige konstrukte...bringt dir also was, das zu übersetzen ;-)


MagicRain - Sa 25.07.09 18:29

Verdammt jetzt will er es aber wissen :roll: :lol:
also ich denke mal so müsste das ausehen :shock:

Delphi-Quelltext
1:
2:
3:
4:
5:
If (eax=$10then begin
eax := eax+2;
end;
dec(eax);
//@x2:restmachen


uall@ogc - Sa 25.07.09 18:59

es wäre ein END ELSE Dec(...)


Flamefire - Sa 25.07.09 19:16

richtig uall...aber das erwaret man von dir ja auch ^^

aus dem grund hatte ich meine informelle beschreibung des asm codes auch so formuliert.
guck dir das noch mal an
und dann versuch dich am 2. bsp


BenBE - Sa 25.07.09 19:35


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
MOV ESI,12
MOV EAX,0
TEST ESI,ESI
JE @l2
@l1: ADD EAX,EAX
CMP EAX,$FFFF
JB @l2
SUB ESI
JNZ @l1
@l2://....


Quelltext
1:
[Fehler]example2.pas(8): Invalid Opcode                    


Für eine Delphi-Umsetzung würd ich mal sagen:

Delphi-Quelltext
1:
EAX := 0;                    


Flamefire - Sa 25.07.09 21:50

ist nicht nötig
das ding ist komplett lauffähig, zumindest in sich...
ob es etwaigen umliegenden code beeinträchtigt kann ich nicht ausschließen
der einzige fehler ist:

"SUB ESI"
Das sollte "DEC ESI" werden...

aber von mir aus kannst du MOV EAX,0 auch durch XOR EAX,EAX ersetzen ;-)


MagicRain - Sa 25.07.09 22:34

Oh ja else stimmt hab da mal was probiert...


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
        MOV EDX,$016
@Project1_0045101D:
        CMP EAX,$012
        JNZ @Project1_00451027
        ADD EAX,5
        JMP @Project1_00451032
@Project1_00451027:
        CMP EAX,$014
        JNZ @Project1_0045102F
        INC EAX
        JMP @Project1_00451032
@Project1_0045102F:
        ADD EAX,$016
@Project1_00451032:
        DEC EDX
        JNZ @Project1_0045101D
        RETN

=

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
var
a,i : Integer;
begin
for i := 1 to 22 do
begin
if(a=$12then begin
a:=a+5;
end else
if(a=$14then begin
a:=a+1;
end else
a := a + 22;
end;
end;
Cool das hab ich hoffe ich dann so weit geil thx :)


BenBE - Sa 25.07.09 23:06

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
ist nicht nötig
das ding ist komplett lauffähig, zumindest in sich...
ob es etwaigen umliegenden code beeinträchtigt kann ich nicht ausschließen
der einzige fehler ist:

"SUB ESI"
Das sollte "DEC ESI" werden...

aber von mir aus kannst du MOV EAX,0 auch durch XOR EAX,EAX ersetzen ;-)

Trotzdem ist dein Teil ein reines EAX := 0; :P 0+0 = 0 :P


Flamefire - So 26.07.09 09:38

@magicrain: ja das ist richtig!
gut gemacht! ;-)

@BenBE: Seit wann kann man in Delphi direkt auf Register zugreifen? Wenn ich im Delphi EAX:=0; schreibe sucht er doch nach einer variable mit namen EAX
im Asm teil nimmt er wirklich das register.
und es ging ja darum ASM code zu haben, den magicrain dann übersetzen kann....
sonst sind wir wieder am Anfang: Gemischter Code ;-)

BTW: Wie kommst du von XOR immer auf "+"?
2 XOR 3=1
ups...wenn dann scheint es ein minus zu sein...aber nur betragsmäßig.
und ob das immer so klappt...


BenBE - So 26.07.09 10:13

Warum ich bei dem einen Source von dir auf EAX := 0; bekomm:
Weil ich grad keine Lust hatte, die Deklaration von var EAX: DWORD; mit anzugeben :P

Ferner: Die Schleife, selbst wenn du das SUB durch DEC ersetzt, führt in ihrer Addition immer ADD, 0, 0 aus, wodurch EAX von seinem Ausgangswert nicht verändert wird. Also kann ich mir schenken, was die Schleife tut und die Schleife rausoptimieren. Ergo: Dein Code weist der Variablen effektiv obfuskirt den Wert 0 zu.

Sorry, aber ich übersetze, was Du hinschreibst ...


Flamefire - So 26.07.09 11:38

verdammt ja hast ja recht
delphi entsprechung davon ist tatsächlich EAX:=0;
hatte ich nicht verstanden was du wolltest.

ok also 2. Korrektur: MOV EAX,1
dann stimmt das ganze, es sei denn ich hab den JB in der reihenfolge noch verhaun und der bricht mir die schleife gleich am anfang ab...mach ich häufiger. kann mir einfach nicht merken wierum das nun ist.


BenBE - So 26.07.09 12:34

Okay, dann ist das ein EAX := 4096;. Alternativ könnte man auch EAX := 1 SHL 12; schreiben, was aber eh vom Compiler zu einer Konstante optimiert wird.


Flamefire - So 26.07.09 12:41

stimmt schon wieder...
ach man...

dann halt einfach MOV EAX,[ESP+4]
und jz ruhe hier ;-)


BenBE - So 26.07.09 12:48

Okay, mal ein etwas schwierigerer zum Umsetzen, geht aber in Delphi umzusetzen:


Delphi-Quelltext
1:
2:
3:
4:
function Foo: pointer;
asm
    MOV EAX, [EBP+4]
end;


(Tipp: Man muss dazu ein wenig mit den Compiler-Settings spielen und ein paar Spezialitäten der Syntax von Delphi kennen UND wissen, wie Delphi mit lokalen Variablen umgeht). Gewinner ist der, mit der kürzesten Lösung; ich poste meine auch, sobald es mindestens eine korrekte Einsendung gab. Angabe aller nötigen Compiler-Settings gehört zur Lösung!

@Flamefire: dein Auslesen von [ESP+4] ist EXTREM vom Kontext abhängig.


Flamefire - So 26.07.09 14:52

hm...allein mit dem wissen über ASM würde ich behaupten, Foo gibt mir die Rücksprungadresse der aktuellen funktion

da (in den meisten anwendungen) eine function so beginnt:

Quelltext
1:
2:
3:
4:
PUSH EBP
MOV EBP,ESP
SUB ESP,x
//...

ist EBP+4 die rücksprungadresse...
in delphi auch wenn man "stackframes" aktiviert.

umsetzung wäre z.b. so:

Delphi-Quelltext
1:
2:
3:
4:
5:
function Test(b:Cardinal):Cardinal;stdcall;
var c:Cardinal;
begin
  Result:=Cardinal(foo())-PCardinal(Cardinal(@c)+12)^;//Immer 0 ;-)
end;

also einfach ein den Wert auslesen der 12 Bytes vor der ersten Variable beginnt.


BenBE - So 26.07.09 15:14

Also, was meine Funktion angibt, ist richtig: Sie liefert die Rücksprungadresse

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
{$R-}
function Foo: Pointer;
var 
    S:array[0..0of Integer;
Begin
    S[0] := 2;
    Result := Pointer(S[S[0]]);
end;


Ganz ohne Typecasts geht's so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
{$R-}
function Foo: Pointer;
var 
    S:array[0..0of record case Boolean of false: (I: Integer;); true: (P: Pointer;); end;
Begin
    S[0].I := 2;
    Result := S[S[0].I].P;
end;


Flamefire - So 26.07.09 15:35

das ist echt trickreich, was du gemacht hast...
rangechecks sollte dann aber aus sein
und wenn die eh aus sind reicht doch auch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
{$R-}
function Foo: Pointer;
var 
    S:array[0..0of Integer;
Begin
    Result := Pointer(S[2]);
end;

oder nicht?
und wenn du da die TypeCasts nicht willst:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
{$R-}
function Foo: Pointer;
var 
    S:array[0..0of Pointer;
Begin
    Result := S[2];
end;


BenBE - So 26.07.09 15:39

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
das ist echt trickreich, was du gemacht hast...
rangechecks sollte dann aber aus sein
und wenn die eh aus sind reicht doch auch:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
{$R-}
function Foo: Pointer;
var 
    S:array[0..0of Integer;
Begin
    Result := Pointer(S[2]);
end;

oder nicht?

Nein. Weil statische Range-Checks vom Compiler IMMER ausgeführt werden. Das führt also zu einem Compiler-Fehler :P


Flamefire - So 26.07.09 17:28

ok gut, das wusste ich nicht..nja mir gefällt meins immer noch besser...
warum auf typcasts verzichten? ist dem asm ja egal...
und so brauch man die rangechecks nicht abschalten