Es ist absolut wichtig, dass Sie lernen, wie man einige Debugger zu bedienen und beobachten Sie, was Ihr Code tut.
, bis Sie einen Debugger finden und lernen, wie es zu benutzen, Stopp-Programmierung in Assembler, gibt es keinen Punkt fortsetzen, werden Sie nur Ihre Zeit verschwenden, und auch andere, wenn Sie jedes triviales Problem bringen werden Überlauf zu stapeln oder ein anderes Forum.
Sie sollten diese "Internet" -Ding nur verwenden, wenn Sie "stecken", indem Sie bestimmte Sache nicht verstehen. Was bedeutet, dass Sie vor einem kurzen Code gut beschreiben können, was der CPU-Status ist, was er nach der Ausführung ist, was Sie erwartet haben und warum und wie er sich von Ihren Erwartungen unterscheidet. Dann können die Leute Ihnen erklären, warum Ihre Erwartungen falsch sind.
Aber wenn Sie auch Anleitung Anleitung verwenden, um Ihre Erwartungen über bestimmte Anweisungen zu überprüfen, können Sie 90% dieser Fehler in sehr kurzer Zeit selbst beheben.
Einige Dinge, die Sie lernen sollten (und lesen Sie Ihre Quelle mit frischen Augen erneut, um diese zu verwenden, um Fehler in Ihrem Code zu finden).
CPU-Register sind "Super Globals", wer auch immer letzten Wert in Register geschrieben hat, ist dieser Wert drin. Wenn Sie für einige Zeit einen Wert beibehalten möchten, stellen Sie entweder sicher, dass das Register nicht durch den nächsten Teil des Codes geändert wird, oder speichern Sie den Wert irgendwo im [Stapel] Speicher. Oder kopieren Sie (mov
) es in ein Register, das nicht im nächsten Teil des Codes verwendet wird, wenn Sie das brauchen, wo der Wert im Moment ist.
DL
, DH
DX
und sind alle gleich Register der CPU, nur unterschiedliche Teile (Bitgruppen) davon. DX
= DH
* 256 + DL
, oder wenn Sie es als Binärzahlen anzeigen, dann DL
ist niedriger 8 Bits von DX
, und DH
ist oberen 8 Bits. DX
ist natürlich 8 + 8 = 16 Bits. Drittes Bit in DH
ist somit auch elften Bit von DX
gleichzeitig, es ist physikalisch das gleiche Bit.
Flags sind auch nur ein numerischer Wert in Register (F
), die nur von einigen Anweisungen betroffen ist. Wenn Sie Anleitungen Nachschlagewerk über Jcc
(Sprung von Bedingungscode) Anweisungen Familie lesen, werden Sie lernen, diejenigen haben keinen Einfluss auf Wert von F
(Flags), so dass in diesem Fall:
CMP AL,DL
JG E2
CMP AL,DL
JL E3
Das zweite CMP
nichts tun neu, schon der erste hat Fahnen gesetzt. Und der Wert im Register ist da, bis es durch eine Anweisung geändert wird, wird es nicht "einfach so" verdampfen. Durch die Verwendung von redundanten Anweisungen in solch einem super kurzen Stück Code zeigen Sie entweder mangelndes Verständnis oder verschwenderische Vorgehensweise (redundante Anweisungen verschwenden CPU-Zyklen, was in den 1980ern sehr kostspielig war und in trivialen Fällen wie diesem würde es dies tun Verdienen Sie viel Rimme und Spott ...wie ich es hier mache (die Stirnrunzeln Teil sicherlich, nicht sicher über Spott, es ist schwer zu Arschloch heute wie Leute gehen fragen um Rat in diesem Stadium der Fähigkeit normalerweise, in den 1980er Jahren wäre dies wie bitten um öffentlich zu beschämt werden dafür, dass du zumindest die Grundlagen nicht selbst erfassst, aber jetzt sollte es in Ordnung sein)).
schließlich über Ihren Zufallsgenerator:
INT 1AH
MOV BH, 57
MOV AH, DL
CMP AH, BH
JA RANDSTART
MOV BH, 49
MOV AH, DL
CMP AH, BH
JB RANDSTART
Dies wiederum viele CPU-Zyklen zu verschwenden, und mehrere Versorgungsleitungen zu verschwenden, und insgesamt ist es sein unangemessen kryptisch, so die Quelle ist nicht leicht zu lesen und befolgen . Betrachten Sie diese alternative Art und Weise von der gleichen Sache:
INT 1AH
; cx:dx is 32 bit clock "time" in (1/18.21)s since boot
; I will use the least significant 8 bits of it (DL) as random ASCII digit
CMP DL, '9'
JA RANDSTART
CMP DL, '0' ; your original code compares with '1'!
JB RANDSTART
; so your original code will produce only 1-9 ASCII digits
Das ist das Gleiche (plus fix 0-9 statt 1-9 Ziffern zurückzukehren). Beachten Sie, wie jetzt die Quelle Ihnen die Geschichte "erzählt" "vergleichen Sie mit ASCII-Ziffer '9'
, wenn oben, neue zufällige tun. Dann vergleichen mit ASCII-Ziffer '0'
, wenn unten, neue zufällig zu tun.", jeder erfahrene x86 ASM Programmierer wird das fast fließend und sofort verstehen.
und noch etwas über diesen "zufälligen" Generator. DL
ist 8-Bit-Register, so kann es einen Wert von 0 bis 2 -1 haben (wenn Sie diese 8 Bits als vorzeichenlose Ganzzahl präsentieren). Aber Sie gehen nur weiter, wenn '0' <= DL <= '9'
, das sind 10 "legale" Werte von DL
. Wenn die Uhr das ASCII-Zeichen ':'
(58
im Dezimalformat) zurückgibt, dauert es ungefähr 14 Sekunden, bis die DL
alle Werte 58-255
und dann 0-47
durchlaufen wird. Das ist eine Art sehr langsamer Zufallsgenerator (auch nicht sehr zufällig).
etwas Um es durch naive Art und Weise zu verbessern, können Sie dies zum Beispiel tun:
INT 1AH
; cx:dx is 32 bit clock "time" in (1/18.21)s since boot
AND DL,15 ; keep only bottom 4 bits (0-15) value in DL
; (cheaply, AND is very fast bitwise operation)
CMP DL,9 ; it's 9 this time, not '9' (57).
JA RANDSTART ; values 10-15 will restart random
; will keep restarting for 6/18.21 = ~0.33 of second
; at most, puny human can wait that short while
; remaining legal values 0-9 will be converted to ASCII digit
ADD DL,'0'
; here DL is some "random" value from '0' to '9'
; unfortunately the value '0' will be somewhat preferred over others
Wenn Sie vollständig diese verstehen und wieder lesen Ihre Quelle, sollten Sie in der Lage sein, alle zu finden deine Fehler. Oder noch besser: Verwenden Sie den Debugger, um mit eigenen Augen zu sehen, was jeder Befehl macht und was mit dem CPU-Zustand nach jedem von ihnen geschieht.
Auch wenn Sie diese verstehen, wird Ihre nächste Quelle lesbarer, kürzer und leichter zu entziffern sein, sowohl für Sie als auch für andere Leser. Wenn Sie Ihren aktuellen Code einigen erfahrenen ASM-Programmierern präsentieren, werden sie weiterhin sagen: "Jeder muss es irgendwie lernen, es ist OK für den Anfang", aber der andere Teil des Geistes wird auch schreien "Töte es, töte es vorher es legt Eier. " Durch einige grundlegenden Refactoring, Entfernen der grundlegenden Verschwendung von Ihrer Quelle wie Duplikate/etc und die Verwendung von geeigneten Konstanten oder Jcc
Aliase folgende Semantik: Sie werden Ihre Fragen leichter zu lesen und zu beantworten (plus die Antwort wird sehr wahrscheinlich auf den Punkt nur, viel unnützes Geplapper auslassend).
Da Ihr Code keinen Speicher verwendet, sollte es sehr einfach sein, die wichtigen Teile des CPU-Zustands zu verfolgen, indem Sie Registeransicht und folgende Werte in Registern betrachten, die für Sie in bestimmten Teilen des Codes wichtig sind (Das Verfolgen von Werten in größeren Speicherblöcken ist etwas mühsamer, aber natürlich machbar, wenn ein solcher Bedarf auftreten würde, ermöglicht es der Debugger auch, den Speicherinhalt anzuzeigen).
Und falls ich es nicht bereits erwähnt habe, ist es absolut notwendig, dass Sie lernen, einige Debugger zu verwenden.
Welche Architektur ist das?Erkläre ausführlicher, was dies bewirkt und was du erwartest. – Rafael
Ich möchte eine Zufallszahl generieren und dann Zahlen wählen, bis ich diese Nummer finden werde. Aber wenn ich eine Nummer wähle, zeigt mein Programm immer "Ihre Nummer ist kleiner" –