![]() |
for Schleife in ASM
Liste der Anhänge anzeigen (Anzahl: 1)
Nehmen wir mal folgenden Code:
Delphi-Quellcode:
Egal was er macht, es ist jedenfalls eine Schleife, die wegen der Optimierung rückwärts läuft.
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); Der produzierte ASM Code sieht aus, wie im Anhang (CPU Fenster). da steht jetzt:
Code:
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?
dec edx
jnz -$08 |
Re: for Schleife ein ASM
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) |
Re: for Schleife ein ASM
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. :mrgreen:
|
Re: for Schleife ein ASM
Nachtrag:
Zitat:
|
Re: for Schleife ein ASM
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 ![]() |
Re: for Schleife in ASM
Ich habe es etwas umformuliert:
Zitat:
|
Re: for Schleife in ASM
Jo, so lässt es sich einfach und verständlich in einem Zuge lesen. Ist nicht mehr so verwirrend wie zuvor. :thumb:
|
Re: for Schleife in ASM
|
Re: for Schleife in ASM
Doch noch was, da ich nicht genauen Artikel kenne, als Hinweis:
Zitat:
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... |
Re: for Schleife in ASM
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:
|
Re: for Schleife in ASM
Wenn Leute deine Erklärung lesen und schauen wollen wie er springt, dann suchen sie das JNZ -$08 und das steht am Offset 0x00402567 (siehe Anhang, dein Bild verschandelt, bezugnehmend auf oberen blauen Rahmen). Wenn man nun von dieser Adresse die gesprungenen 8 Bytes abzieht, dann kommt man aber auf eine falsche Adresse, und zwar auf 0x0040255F. An der Stelle steht man in mitten einer Instruktion und der Leser versteht die Welt nicht mehr. Daher vllt. darauf hinweisen, dass der Offset des relativen Sprungs auf die Adresse 0x00402569 (siehe Anhang, bezugnehmend auf unteren blauen Kasten) addiert (durch das Vorzeichen des Sprung-Offsets von -8 verringert sich die Adresse) und man erhält die von dir beschriebene Adresse 0x00402561 und damit die richtige Position.
Nun klarer? Das mit dem Instruktion Zeiger brauchste nicht erwähnen, weise nur darauf hin, dass die Leser bitte die 8 Bytes nicht von 0x00402567 abziehen (wo der Sprungbefehl laut Screenshot steht) sondern von der Adresse 0x00402569. /EDIT: Jetzt hast du es erneut umformuliert und es ist ok. Aber ansonsten, vllt. findest du eine klein wenig einfachere Beschreibung, wenn du den Begriff des Instruktionszeigers erst gar nicht einführst und einfach nur auf die richtige Adresse zum subtrahieren hinweist, wie du es ja grundsätzlich schon tust. Da der Begriff des Instruktionszeigers nie erklärt oder eingeführt wird, verwirrt er die Leute mehr, da sie keine Informationen für diesen neuen Begriff bekommen... (Man merkt, dass ich mal Chefredakteur war, oder? *g* (keine Angst, nur eine Schülerzeitung)) |
Re: for Schleife in ASM
Jetzt aber:
Zitat:
|
Re: for Schleife in ASM
:thumb: Super, kurz, knapp, verständlich.
(Falls nun noch einer nachfragt warum die andere Adresse, kannst du ihm es jederzeit erklären...) Und Gute Nacht (ich sollte schon seit min. 2 Stunden im Bett liegen...) |
Re: for Schleife in ASM
Zitat:
|
Re: for Schleife in ASM
Zitat:
Delphi-Quellcode:
Denn mit dieser Zeile bewegt sich das Array vorwärts, womit die Abarbeitung der Schleife trotz der rückwärtslaufenden Zählvariable, vorwärts geht.
add eax,$04
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:57 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 by Thomas Breitkreuz