2017-01-09 4 views
-2

Ich muss ein Projekt in Assemblersprache machen, und ich bin wirklich gestapelt. Ich möchte eine Zufallszahl (0-9) generieren, danach wähle ich und nummeriere, bis ich die Nummer finde. ich nicht brauchen, um etwas so kompliziert bitteAssemblersprache finde die Nummer

.MODEL SMALL 
.STACK 100H 
.DATA 

m1 DB 'The number is bigger ','$' 
m2 DB 'The number is smaller','$' 
m3 DB 'You won','$' 
m4 DB 'Choose the number ','$' 
.CODE 
MOV AX,@DATA 
MOV DS,AX 
MOV AH,09H 
MOV DX,OFFSET m4 
INT 21H 
RANDGEN:  
RANDSTART: 
    MOV AH, 00h 
    INT 1AH   

    MOV BH, 57 
    MOV AH, DL 
    CMP AH, BH  
    JA RANDSTART 

    MOV BH, 49 
    MOV AH, DL 
    CMP AH, BH 
    JB RANDSTART 


    mov ah, 2h 
    int 21h  
E1:MOV AH,01H 
INT 21H 
CMP AL,DL 
JG E2 
CMP AL,DL 
JL E3 
MOV AH,09H 
MOV DX,OFFSET m3 
INT 21H 
JMP E4 

E2:MOV AH,09H 
MOV DX,OFFSET m1 
JMP E1 

E3:MOV AH,09H 
MOV DX,OFFSET m2 
JMP E1 

E4:MOV AH,4CH 
INT 21H 
END 
+0

Welche Architektur ist das?Erkläre ausführlicher, was dies bewirkt und was du erwartest. – Rafael

+0

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" –

Antwort

1

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).

  1. 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.

  2. DL, DHDX 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.

  3. 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)).

  4. 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.

  5. 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.

Verwandte Themen