2017-11-14 14 views
0

어셈블리는 재미있는 학습 언어입니다. 나는 여전히 개선의 여지가 많다. 나는 임의의 주사위 롤을 x 번 사용자 입력을 기반으로해야하는 간단한 크랩 게임을 만들기 위해 노력하고 있습니다. 나는 다음과 같은 코드를 가지고있다 :x86 Irvine 어셈블리 jmp + cmp 및 조건부 루프 - 크랩 게임

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 

그래서 예제와 설명에서 충분히 간단 해 보인다. 주사위를 굴릴 때 if 문처럼 작동하도록 cmp/je를 사용하고 있습니다. 아이디어는 승리 또는 손실 또는 점수가 증가하고 모든 것을 인쇄하는 것입니다. 그것은 cmp/je 부분없이 잘 동작합니다. 나는 무작위 주사위 굴림을 인쇄 할 수 있지만 일단 cmp/je하려고하면 이상한 동결과 때로는 충돌이 발생합니다. 어셈블리를 더 잘 코딩하는 법을 배우려고합니다. 왜 내가 이것이 그렇게 생각하는 방식으로 작동하지 않는지 이해할 수 있도록 도와 주시겠습니까? 나는 만약 dpiOne + dice의 합계가 포함 된 eax 레지스터를 다른 함수들과 그 함수들로 뛰어 넘어야한다고 생각했다. edi는 win, lose 또는 mark를 나타내는 문자열을 출력하는 동안 카운터가되어야한다. . 따라서 예를 들면 다음과 같습니다.

Enter integer: 5 
2 + 3 Mark 
1 + 5 Mark 
5 + 6 You win! 
5 + 1 Mark 
2 + 6 Mark 
Wins: 1 Losses: 0 Marks: 4 

나는 코드에 문제가있는 것이므로 아직 마지막 부분을 얻지 못했습니다. 어떤 도움을 주셔서 감사합니다. 나는 잃어 버렸어, 고마워.

이 내가 지금지고있어 실제 결과 추가하는 것을 잊었다 :

Enter integer: 5 

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

일부 변수는 사용되지 않는 것으로 알고 있습니다. 무시하십시오. – Alex

+0

나는 규칙 (tldr)을 이해하지 못했지만 배열의 모든 구성원이 아닌 값 7, 2 및 4 만 비교합니다. 이게 의도 된거야? – Tommylee2k

+0

첫 번째'randomRange'는 0-4 범위의 값만 출력합니다. ('mov eax, 5' ahead) – Ped7g

답변

0

현재 버전은 기능 :

먼저 임의의 호출이 0-4 전용입니다.

cmp eax, win : win "배열"에서 값 7에 대해 eax를 비교합니다, 당신은 MASM 구문을 사용하므로이 인텔 문법에 cmp eax,[mem32]입니다. 그러면 je wins은 코드에서 wins:의 결과 7로 점프하고 쓸모없는 포인터 물건을 수행하고 ecx을 2로 재설정하고 메시지를 표시하고 메인 롤 루프로 돌아갑니다.

마찬가지로 잃음/표시 "배열"의 경우 첫 번째 요소 (잃음 2, 표시 4)가 테스트되고 같으면 쓸모없는 물건과 함께 lose/mark 메시지가 표시되고 ecx을 다시 설정하고 똑바로 점프합니다 다시 롤링.

loop이 실행 된 다른 값 (3, 5, 6, 8, 9, 10, 11 (임의 버그로 인해 12 개가 누락 됨)에 대해서만 전체 루프를 ecx 카운트 다운합니다.

CPU의 "에뮬레이션"이 제한되어 있고 속도가 ~ 2Hz에 불과하기 때문에 디버거에서이 동작을 쉽게 볼 수 있습니다 (내 머리 부분에서 실수를 범한 경우에도 내 설명과의 불일치를 확인해야합니다).), 지시 사항을 한 단계 건너 뛰고 각 단계마다 기계 상태를 검사 할 수 있습니다. 디버거없이 어셈블리를 프로그래밍하는 것은 눈을 가린 로봇을 조립하려는 것과 같습니다. 하지만 100 배는 더 어렵 기 때문에 어셈블리 학습을 계속하기 전에 디버거를 효과적으로 사용하는 방법을 배우는 데 많은 투자를하십시오.코드에 대한


어떤 조언 : 전체

당신이 조금을 복잡하게하는, 내가 (대신 win/lose/mark 배열의) 데이터 테이블을 정의하는 것, 그렇지 않으면 이런 짓을 했을까 :

;    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 

코드에서 두 번째 던지기가 표시되고 eax 번째 던지기에서 결과를 다음과 같이 선택할 수 있습니다.

; 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 

불행히도 win/... 배열의 값에 대해 cmp을 연습하고 싶다면이 사실을 완전히 피할 수 있으므로 교육적인 가치는 거의 없습니다. 디버거를 먼저 사용하는 법을 배운 후에 코드를 실제로 검사 할 수 있도록 별도로 배열 테스트를 작성해야합니다.

+0

와우 나는 이것을 약간 소화해야 할 것이다. 고마워. 불행히도 나는 cmd 프롬프트에서 이것을 실행하고 디버거를 사치스럽게 생각하지는 않는다. 지금 Visual Studio에서 이것을 사용하는 법을 배워야 할 것입니다. :) 나는 이것을 게시 한 후 전체 어레이를 비교하지 않고 루프/카운터를 만들어 배열을 만들거나 cmp eax, 7/cmp eax, 11을 시도 할 필요가 있다는 것을 알았습니다. 그리고 이것이 작동하는 것 같았습니다. 첫 번째 롤에 대해,하지만 충돌보다. 정말이 가정교사가 필요합니다. 불행하게도 어쨌든이 물건을 알고있는 사람을 찾을 수는 없습니다. – Alex

+0

마음에 들지 않으시면 롤 인쇄의 가치가 얼마나 떨어지는 지 설명하십시오. movax, [totalScore + 4] – Alex

+0

@Alex'totalScore'에 대한 나의 정의를 확인하십시오. 3x DWORD 0입니다. 따라서 첫 번째 DWORD는'totalScore + 0'에 있고, 두 번째는'totalScore + 4'이고 세 번째는'totalScore + 8'입니다. 이제 예제에서 나는 ebx = 0/1/2가 win/lose/mark 인'inc dword ptr [totalScore + ebx * 4]'를 통해 이들 값을 증가 시키므로 손실은 totalScore + 4 주소의 메모리에서 계산됩니다 '(DWORD로, addres의 totalScore + 7까지 4 바이트가 영향을받습니다). ... Visual Studio는 또한 콘솔 실행 파일을 디버깅 할 수 있습니다. – Ped7g