2017-11-14 5 views
0

Assembly ist eine lustige Sprache zu lernen. Ich habe noch viel Raum für Verbesserungen. Ich versuche, ein einfaches Würfelspiel zu machen, das zufällige Würfel x Male basierend auf Benutzereingabe würfeln soll. Ich habe den Code wie folgt:x86 Irvine Assembly JMP + CMP und bedingte Schleifen - Craps Spiel

TITLE Program Template   (main.asm) 

INCLUDE Irvine32.inc 

.data 
diceOne      DWORD ? 
diceTwo      DWORD ? 
win       DWORD 7, 11 
lose      DWORD 2, 3, 12 
mark      DWORD 4, 5, 6, 8, 9, 10 
markCounter     DWORD ? 
userInput     BYTE 'Enter integer: ', 0 
numRolls     DWORD ? 
printWon     BYTE 'Won: ', 0 
wonCounter     DWORD ? 
printWin     BYTE ' You win!', 0 
printLost     BYTE 'Lost: ', 0 
lostCounter     DWORD ? 
printLose     BYTE ' You lose!', 0 
printTotal     BYTE 'Total: ', 0 
space      DWORD ' ', 0 
printPlus     BYTE ' + ', 0 
printMark     BYTE ' Mark ', 0 

.code 
main PROC 
    call randomize      ; set random seed 
    mov ecx, 6       ; counter set to 6 
    mov edx, offset userInput   ; print string 
    call writeString 
    call readInt      ; read input 
    mov numRolls, eax     ; store input in variable 
    mov ecx, numRolls     
    mov eax, 0 
    mov edi, offset win 

    call gamesRolled 





    exit 
main ENDP 
;number of games rolled based on user input 
gamesRolled PROC uses eax ecx 

DICEROLLS: 
    call crlf 
           ;diceOne roll 
    mov eax, 5     ;move value into eax to pass as parameter for randomrange 
    call randomRange   ;randomrange stored in eax 0-5 
    inc eax 
    mov diceOne, eax   ;mov the value of randomrange into variable 
    call writeDec  
    push edx     ;push edx off stack to print space 
    mov edx, OFFSET printPlus 
    call writeString 
    pop edx 
           ;diceTwo roll 
    mov eax, 6 
    call randomRange 
    inc eax 
    mov diceTwo, eax 
    call writeDec 


    add eax, diceOne   ; add diceOne roll to diceTwo roll 
    cmp eax, win    ; comp eax value to win 
    je wins 
    cmp eax, lose 
    je losses 
    cmp eax, mark 
    je marks 
    LOOP DICEROLLS 

    ret 
gamesRolled ENDP 

wins PROC uses edi ecx 
    mov edi, offset win 
    mov ecx, lengthof win 
    cmp eax, [edi] 
    add edi, type win 
    push edx 
    mov edx, offset printWin 
    call writeString 
    pop edx 
    jmp gamesRolled 
    ret 

wins ENDP 

losses PROC uses edi ecx 
    mov edi, offset lose 
    mov ecx, lengthof lose 
    cmp eax, [edi] 
    add edi, type lose 
    push edx 
    mov edx, offset printLose 
    call writeString 
    pop edx 
    jmp gamesRolled 
    ret 
losses ENDP 

marks PROC uses edi ecx 
    mov edi, offset lose 
    mov ecx, lengthof lose 
    cmp eax, [edi] 
    add edi, type lose 

    push edx 
    mov edx, offset printMark 
    call writeString  
    pop edx 
    jmp gamesRolled 
    ret 
marks ENDP 




END main 

So scheint es einfach genug aus den Beispielen und Erklärungen, die ich gesehen habe. Ich benutze den Cmp/Je, um wie ein if-Statement zu arbeiten, während ich die Würfel rollen lasse. Die Idee ist, die Gewinne oder Verluste oder Marken zu erhöhen und alles auszudrucken. Es funktioniert gut ohne den CMP/Je Teil. Ich bin zwar in der Lage, zufällige Würfelröllchen zu drucken, aber sobald ich anfange, cmp/je zu versuchen, bekomme ich ein seltsames Einfrieren und manchmal einen Absturz. Ich versuche zu lernen, wie man besser in Assembler programmiert. Würden Sie mir bitte helfen, zu verstehen, warum das nicht so funktioniert, wie ich es mir vorgestellt habe? Ich dachte mir, wenn ich das EAX-Register, das die Summe von diceOne + diceTwo enthält, als die anderen Funktionen springen würde und in diesen Funktionen sollte edi wie ein Zähler sein, der während des Druckens einer Zeichenfolge, die einen Gewinn, Verlust oder Markierung angibt, zählt . So zum Beispiel:

Ich habe nicht zum letzten Teil noch, da ich Probleme mit dem Code habe, wie es ist. Schätze jede Hilfe damit. Ich bin ratlos, danke.

vergessen hat, ist dies ein tatsächliches Ergebnis hinzuzufügen, ich bin jetzt immer:

Enter integer: 5 

3 + 2 
3 + 5 
2 + 5 You win! 
3 + 6 
5 + 5^C 
+0

Ich weiß, dass einige der Variablen nicht verwendet werden, bitte ignorieren Sie diese. – Alex

+0

Ich habe die Regel (Tldr) nicht verstanden, aber was ich sehe, vergleichen Sie nur mit den Werten 7, 2 und 4, nicht mit allen Mitgliedern des Arrays. ist das beabsichtigt? – Tommylee2k

+0

Zuerst 'call randomRange' wird Werte nur im 0-4 Bereich (' mov eax, 5' voraus) – Ped7g

Antwort

0

Was die aktuelle Version tut:

erster Zufall Anruf 0-4 nur.

cmp eax, win: Verwenden Sie MASM Syntax, so ist dies cmp eax,[mem32] in Intel-Syntax wird eax gegen Wert 7 von win "Array" vergleichen. Dann wird je wins für Ergebnis 7 bei Code um wins: springen und das wird man ein paar unbrauchbare Zeiger Zeug tun, ecx auf 2 zurücksetzen, Nachricht anzeigen und zurück zum Haupt-Roll-Loop springen.

In ähnlicher Weise für verlieren/markieren "Arrays", das erste Element (2 für verlieren, 4 für Markierung) getestet wird, und wenn gleich, wird die lose/mark Nachricht mit einigen nutzlosen Sachen angezeigt, ecx zurückgesetzt und gerade zurück zum Rollen.

Nur für die anderen Werte (3, 5, 6, 8, 9, 10, 11 (und fehlende 12 aufgrund eines zufälligen Fehlers)) wird die loop ausgeführt, in ecx die gesamten Schleifen zählen.

Sie sollten dieses Verhalten im Debugger leicht sehen (und sogar irgendeine Diskrepanz zu meiner Beschreibung finden, wenn ich einen Fehler in meinem Kopf machte, weil meine "Emulation" der CPU ein bisschen begrenzt ist und nur ungefähr ~ 2Hz in der Geschwindigkeit), wenn Sie die Anweisungen einzeln durchlaufen und nach jedem Schritt den Maschinenzustand überprüfen. Das Programmieren in Assembly ohne Debugger ist wie der Versuch, Roboter mit verbundenen Augen zusammenzubauen. Sie können, aber es ist wie 100x schwieriger, also investieren Sie stark in das Lernen, wie Sie den Debugger effektiv nutzen, bevor Sie mit dem Assembly-Lernen fortfahren.


Einige Ratschläge über Code:

Insgesamt sind Sie ein wenig kompliziert wird es, ich würde das sonst tun, ich in Daten, die die Tabelle (anstelle der win/lose/mark Arrays) definieren würde:

;    2L 3L 4M 5M 6M 7W 8M 9M 10M 11W 12L 
outcome BYTE 1, 1, 2, 2, 2, 0, 2, 2, 2, 0, 1 
outcomeMsgs: 
    DWORD OFFSET printWin, OFFSET printLose, OFFSET printMark 
totalScore DWORD 0, 0, 0 ; wins/losses/marks 

Dann im Code nach dem zweiten Wurf wird angezeigt und Sie haben in eax die Summe von Würfen, können Sie das Ergebnis als das Pick:

; decide what is the outcome of throws 
    movzx ebx,byte ptr [outcome + eax - 2] 
     ; ebx = 0/1/2 = win/lose/mark 
    ; display outcome message 
    mov  edx,[outcomeMsgs + ebx*4] 
    call writeString 
    ; add to total score 
    inc  dword ptr [totalScore + ebx*4] 
    ; do ecx-many rolls 
    dec  ecx 
    jnz  DICEROLLS 
    ; ending sequence 
    ; for example, display total losses 
    mov  edx,OFFSET printLost 
    call writeString 
    mov  eax,[totalScore+4] 
    call writeDec 
    ret 

Leider, wenn Sie das cmp gegen Werte von win/... Arrays ausüben wollten, ist dies vollständig zu vermeiden, so von geringem Bildungswert. Sie sollten wahrscheinlich separat versuchen, diesen Array-Test zu schreiben, nur um mehr Fähigkeiten zu bekommen ... nachdem Sie lernen, zuerst Debugger zu verwenden, so können Sie tatsächlich überprüfen, was der Code wirklich tut.

+0

Wow, ich werde das für ein bisschen verdauen müssen, vielen Dank. Leider führe ich dies in cmd prompt und bekomme nicht den Luxus von Debugger. Ich werde lernen müssen, wie man das im Visual Studio benutzt, und das ist jetzt eine Priorität :). Ich realisierte nach dem Posten, dass ich nicht das gesamte Array vergleichen würde und ich würde entweder eine Schleife/Zähler machen, um durch das Array zu gehen, oder ich würde nur versuchen, eax, 7/cmp eax, 11 und dies schien zu funktionieren für die erste Rolle, aber dann würde es zusammenbrechen. Ich brauche wirklich einen Tutor dafür, leider kann ich niemanden finden, der wirklich diese Sachen sowieso kennt, danke – Alex

+0

wenn Sie nichts dagegen hätten, bitte erklären Sie, wie ist das Ausdrucken der Wert der Rollen verloren mov eax, [totalScore + 4] – Alex

+0

@Alex Überprüfen Sie meine Definition von 'totalScore' .. es ist 3x DWORD 0. So ist das erste DWORD bei Adresse' totalScore + 0', zweite ist bei 'totalScore + 4' und dritte bei' totalScore + 8'. In meinem Beispiel hebe ich diese Werte an, indem ich 'inc dword ptr [totalScore + ebx * 4] 'mit ebx = 0/1/2 als win/lose/markiere, so dass die Verluste im Speicher bei der Adresse' totalScore + 4 gezählt werden '(Als DWORD sind 4 Bytes bis zu den Adressen 'totalScore + 7' betroffen). ... Visual Studio kann auch ausführbare Dateien der Konsole debuggen. – Ped7g