AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

for Schleife in ASM

Ein Thema von Luckie · begonnen am 13. Jul 2006 · letzter Beitrag vom 13. Jul 2006
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

for Schleife in ASM

  Alt 13. Jul 2006, 00:45
Nehmen wir mal folgenden Code:
Delphi-Quellcode:
var
  ar : array[0..5] of integer = (0, 1, 2, 3, 4, 5);

  i, r : integer;
begin
  r := 0;
  for i := 0 to 5 do
  begin
    inc(r, ar[i]);
  end;
  Writeln(r);
Egal was er macht, es ist jedenfalls eine Schleife, die wegen der Optimierung rückwärts läuft.

Der produzierte ASM Code sieht aus, wie im Anhang (CPU Fenster).

da steht jetzt:
Code:
dec edx
jnz -$08
jnz bedeutet, "Spring, wenn das Zero Flag nicht null ist." Aber das Zero Flag ist die ganze Zeit null. Kann man auch im Screenshot sehen. Erst wenn edx mit der Zählvariablen 0 erreicht hat, wird das Zero Flag auf 1 gesetzt und er springt nicht mehr. Der Code verhält sich also genau gegenteilig wie er eigentlich sollte. Oder habe ich da jetzt ein Verständnisproblem?
Miniaturansicht angehängter Grafiken
for_backwards_135.jpg  
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#2

Re: for Schleife ein ASM

  Alt 13. Jul 2006, 00:51
JNZ = jump if not ZF

Die bedeutet, springe, wenn das Zero Flag (ZF) im Flags register nicht gesetzt ist. Wenn also ZF = 0, dann ist es nicht gesetzt. Es geht hier nicht um die 0 oder 1 welches ZF annehmen kann, sondern das Z steht für das Zero Flag. Und dieses ist nunmal 1, wenn eine vorherige mathematische Operation eine 0 ergeben hat. Mit anderen Worten: So lange EDX nicht 0 erreicht hat (was das ZF setzen würde), springe relativ 8 Bytes zurück (springe wenn ZF nicht gesetzt, jump if not ZF)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

Re: for Schleife ein ASM

  Alt 13. Jul 2006, 00:54
Hm. Dann habe ich das doch nur falsch verstanden. In meinem ASM Buch ist das aber auch etwas blöd erklärt. Puh ich dachte schon meine CPU wäre kaputt.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#4

Re: for Schleife ein ASM

  Alt 13. Jul 2006, 01:01
Nachtrag:
Zitat:
An dieser Stelle wird die Zählvariable dekrementiert mit dec. dec hat die Eigenschaft, dass wenn das dekrementierte Register null wird das Zero Flag (ZF) zusetzen. Dies wird ausgenutzt, um mittels des Sprungbefehls jnz ("springe, wenn das Zero Flag (ZF) im Flags register nicht gesetzt ist") zu entscheiden, ob gesprungen werden muss oder nicht. Ist das Zero Flag nicht gesetzt (null), wird gesprungem und zwar in diesem Fall an eine Adresse 8 Byte zurück: $-08, was Adresse 00402561 wäre, und wie man sieht, ist das unser Schleifenrumpf. Ansonsten wird nicht gesprungen und im Code weitergemacht.

Und das, die Überprüfung eines Flags im Flagregister, ist einfachher und schneller als das Vergleichen zweier Register auf Gleichheit / Ungleichheit. Und das müsste man machen, wenn die Schleife vorwärts läuft, denn dann muss man ja die Zählvariable immer mit dem Endwert vergleichen, was bedeuten würde, dass man er mit dem ASM-Befehl cmp zwei Register vergleicht und erst dann ein Flag im Flagregister auswerten kann.
Stimmt der Text so?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#5

Re: for Schleife ein ASM

  Alt 13. Jul 2006, 01:13
Ok, ansonsten nochwas:

jz = jump zero
jnz = jump not zero

Springe, wenn 0
Springe, wenn nicht 0

So kann man es sich vllt. auch leichter merken. Grundlegend hat es dein Assemblerbuch dann aber wirklich schlecht übersetzt (?) bzw. erklärt.

/EDIT: Ja, der Text stimmt so. Du hast nur einmal "register" klein geschrieben (wie zitiert). Ansonsten stimmt es so. Es klingt etwas verwirrend und man muss es zweimal lesen. Wenn das ein Tutorial werden soll, dann müsste man den ersten Teil vllt. nochmal anders formulieren um ihn zu entschärfen, weil beim ersten lesen verwirrt einen diese umgekehrte Logik recht stark.

Ansonsten noch ein Tipp: Als Argument kann man auch gleich nochmal die Opcodegrösse für CMP mit JE/JNE im Vergleich zu JNZ anführen. Ansonsten wäre auch noch allgemein anzumerken, dass sehr viele Operationen die Flags beeinflussen und viele Operationen vor allem das ZF mit setzen bzw. löschen. Dazu gibt es in den Unterlagen von Intel und AMD gute Tabellen. So z.B. bei AMD im Dokument #24594 AMD64 Architecture Programmer's Manual, Volume 3, General-Purpose and System Instructions auf Seite 178 (Dokument Seite 146) die Dokumentation der bedingten Sprünge und im Anhang E (Appendix E) findest du eine Tabelle wo aufgelistet wird, welches Flag im EFLAGS Register von welcher Instruktion beeinflusst wird (Seite 517, Dokument Seite 485).
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

Re: for Schleife in ASM

  Alt 13. Jul 2006, 01:17
Ich habe es etwas umformuliert:
Zitat:
An dieser Stelle wird die Zählvariable dekrementiert mit dec. dec hat die Eigenschaft, dass wenn das dekrementierte Register null wird das Zero Flag (ZF) zusetzen. Dies wird ausgenutzt, um mittels des Sprungbefehls jnz ("springe, wenn das Zero Flag (ZF) im Flagsregister nicht gesetzt ist") zu entscheiden, ob gesprungen werden muss oder nicht. Ist das Zero Flag nicht gesetzt (null), wird gesprungen und zwar in diesem Fall an eine Adresse 8 Byte zurück: $-08, was Adresse 00402561 wäre, und wie man sieht, ist das unser Schleifenrumpf. Ansonsten wird nicht gesprungen und im Code weitergemacht.

Und das, die Überprüfung eines Flags im Flagregister, ist einfacher und damit schneller als das Vergleichen zweier Register auf Gleichheit / Ungleichheit. Und das müsste man machen, wenn die Schleife vorwärts läuft. In diesem Fall muss man die Zählvariable immer mit dem Endwert vergleichen, was bedeuten würde, dass man er mit dem ASM-Befehl cmp zwei Register vergleicht und erst dann ein Flag im Flagregister auswerten kann.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#7

Re: for Schleife in ASM

  Alt 13. Jul 2006, 01:19
Jo, so lässt es sich einfach und verständlich in einem Zuge lesen. Ist nicht mehr so verwirrend wie zuvor.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#8

Re: for Schleife in ASM

  Alt 13. Jul 2006, 01:20
OK, dann kommt es jetzt auf meine HP.

http://www.michael-puff.de/Developer...ackwards.shtml
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: for Schleife in ASM

  Alt 13. Jul 2006, 01:26
Doch noch was, da ich nicht genauen Artikel kenne, als Hinweis:

Zitat von Luckie:
... wird gesprungen und zwar in diesem Fall an eine Adresse 8 Byte zurück: $-08, was Adresse 00402561 wäre, und wie man sieht, ist das unser Schleifenrumpf.
Die Instruktion steht an Adresse 0x00402567 und du springst 0x08 Bytes zurück und kommst auf 0x00402561 anstatt laut "Adam Riese" auf 0x0040255F. Daher die Frage ob du vorher schon darauf eingegangen bist, dass der Instruktion Pointer genutzt wird beim Sprung um die 8 Bytes ab zu ziehen und da er die Instruktion gerade abarbeitet, steht dieser schon auf der nächsten, also 0x00402569 und somit zieht er von dieser 8 Bytes ab.

Ich denke dass kann bei einer einzeln hier so gefallenen Äusserung ohne Erklärung zu Verwirrungen führen, da viele einfach die Instruktion suchen und von dem Offset subtrahieren, welcher links an dieser steht...

/EDIT: Was im Artikel nicht geklärt wird, bzw. worauf nicht hingewiesen wird...
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#10

Re: for Schleife in ASM

  Alt 13. Jul 2006, 01:31
Wie bitte? Das habe ich jetzt, galube ich, nicht ganz verstanden. Es wird nicht acht Byte vom Offset zurückgesprumgen, sondern acht Byte vom Instruktionszeiger? Ist das gemeint?

Ich habe es jetzt so
Zitat:
in diesem Fall 8 Byte zurück: -$08, was Adresse $00402561 beim Instruktionszeiger entspricht, da der Instruktionszeiger schon bei $00402569 steht, und wie man sieht, ist das unser Schleifenrumpf
umformuliert.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 13:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz