首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >x86程序集-- Powerball模拟器--需要帮助正确调用宏,使用数组并简化不必要的长代码。

x86程序集-- Powerball模拟器--需要帮助正确调用宏,使用数组并简化不必要的长代码。
EN

Stack Overflow用户
提问于 2022-11-14 20:17:58
回答 1查看 18关注 0票数 -1

我创建了一个Powerball绘图模拟,它应该根据一组随机生成的数字检查用户选择的数字,并告诉用户他们是否赢得了什么(如下所示)。

用户是否知道Powerball的号码并不重要;程序应该检查用户的输入和随机生成的输入。

我正在尝试使用宏(需要使用宏),但我一直收到以下错误:

由于这是我第一次使用宏,我不完全理解如何使用它们,因此欢迎解释如何正确地将数组作为输入(但并不重要)。但是,如果有人能想出一种方法来大大简化我的代码,我会欣喜若狂的。我的代码如下所示。

代码语言:javascript
复制
TITLE Powerball Drawing Simulation, Version 1   (PowerballDraw.asm)
; at end try to change Powerball numbers to their proper colors


; This program takes four numbers and
; checks them against a simulated Powerball
; draw.

INCLUDE Irvine32.inc
INCLUDE Macros.inc

.data
; Powerball numbers drawn
whiteBalls  DWORD 5 dup(0)  ; declare an array of 5 elements
redBall     DWORD ?         ; create a red number ball

; user numbers entered
uWtBalls DWORD 5 dup(0)     ; declare an array of 5 elements
uRedBall DWORD ?            ; create a red number ball

.code
;-------------------------------------------------------
mCheckNumbers MACRO wballs:REQ, rball:REQ
;
; Macro for checking user-selected numbers
;   against the system-generated Powerball
;   draw
; Receives: wballs, the array of user-selected
;   numbers; rballs, the red Powerball selected.
; Returns: String stating how much the user won.
;-------------------------------------------------------
.data
countWMatches   DWORD 0     ;; number of user-selected white numbers that 
                            ;;      match Powerball draw 
redMatch        DWORD ?     ;; value changes if user entry matches red ball

;; output strings (amount won)
pI      BYTE    "You have matched all 5 of the white balls and the red ball! You've won the Grand Prize!",0
pII     BYTE    "You have matched all 5 of the white balls but not the red ball. Your ticket wins $1 Million!",0
pIII    BYTE    "You have matched 4 of the white balls and the red ball. Your ticket wins $50,000!",0 
pIV     BYTE    "You have matched 4 of the white balls but not the red ball. Your ticket wins $100!",0
pV      BYTE    "You have matched 3 of the white balls and the red ball. Your ticket wins $100!",0
pVI     BYTE    "You have matched 3 of the white balls but not the red ball. Your ticket wins $7.",0
pVII    BYTE    "You have matched 2 of the white balls and the red ball. Your ticket wins $7.",0
pVIII   BYTE    "You have matched 1 of the white balls and the red ball. Your ticket wins $4.",0
pIX     BYTE    "You have matched the red ball. Your ticket wins $4.",0

;; output strings (user lost)
loseI   BYTE    "You have matched 2 of the white balls but not the red ball. You lose!",0
loseII  BYTE    "You have matched 1 of the white balls but not the red ball. You lose!",0
loseIII BYTE    "You matched absolutely nothing! You lost!",0

.code
    ;; check to see if any user selection for white match Powerball draw
    mov  edi,wballs                 ;; move wballs pointer into EDI
    mov  ecx,LENGTHOF wballs        ;; get length of wballs array
    checkWhite:
        push ecx                        ;; save outer loop count
        mov  eax,[edi]                  ;; store [EDI] in EAX for comparisons
        mov  esi,OFFSET whiteBalls      ;; move whiteBalls pointer into ESI
        mov  ecx,LENGTHOF whiteBalls    ;; get length of whiteBalls
        findMatch:
            cmp  [esi],eax              ;; compare EAX and current array value [ESI]
            jne  next                   ;; if [ESI] not equal to EAX, jump to next
            jmp  bigNext                ;; else jump to bigNext
        next:
            add  esi,4                  ;; increment, move to next memory location (whiteBalls)
            loop findMatch              ;; inner loop
    bigNext:
        pop  ecx                    ;; retrieve outer loop count
        add  countWMatches,1        ;; add 1 to countWMatches
        add  edi,4                  ;; increment, move to next memory location (wballs)
        cmp  ecx,0                  ;; compare ECX to 0
        je   quit                   ;; if ECX == 0, jump to quit
        jmp  checkWhite             ;; else jump back to checkWhite
    ;; check to see if user selection for red matches red Powerball from draw
    checkRed:
        cmp  rball,redBall          ;; compare rball and redBall
        je   markRed                ;; if rball == redBall, jump to markRed
        jmp  notEqual               ;; else jump to not equal
    markRed:
        mov  redMatch,1             ;; move 1 into redMatch
        jmp  getResults             ;; jump to getResults
    notEqual:
        mov  redMatch,0             ;; move 0 into redMatch
        jmp  getResults             ;; jump to getResults
    ;; find results for comparisons/Powerball draw
    getResults:
        cmp  countWMatches,5        ;; compare countWMatches to 5
        je   match5                 ;; if equal, jump to match5
        cmp  countWMatches,4        ;; else, compare countWMatches to 4
        je   match4                 ;; if equal, jump to match4
        cmp  countWMatches,3        ;; else, compare countWMatches to 3
        je   match3                 ;; if equal, jump to match3
        cmp  countWMatches,2        ;; else, compare countWMatches to 2
        je   match2                 ;; if equal, jump to match2
        cmp  countWMatches,1        ;; else, compare countWMatches to 1
        je   match1                 ;; if equal, jump to match1
        jmp  match0                 ;; else jump to match0
    match5:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeI                 ;; if equal, jump to Grand Prize (prizeI)
        jmp  prizeII                ;; else jump to $1 Million prize (prizeII)
    match4:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeIII               ;; if equal, jump to $50,000 prize (prizeIII)
        jmp  prizeIV                ;; else jump to first $100 prize (prizeIV)
    match3:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeV                 ;; if equal, jump to second $100 prize (prizeV)
        jmp  prizeVI                ;; else jump to first $7 prize (prizeVI)
    match2:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeVII               ;; if equal, jump to second $7 prize (prizeVII)
        jmp  LOSE1                  ;; else jump to LOSE1
    match1:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeVIII              ;; if equal, jump to first $4 prize (prizeVIII)
        jmp  LOSE2                  ;; else jump to LOSE2
    match0:
        cmp  redMatch,1             ;; compare redMatch to 1
        je   prizeIX                ;; if equal, jump to second $4 prize (prizeIX)
        jmp  LOSE3                  ;; else jump to LOSE3
    ;; display results for Powerball draw (winner)
    prizeI:
        ;; Grand Prize
        mov  edx,OFFSET pI          ;; move pI string into EDX
        call WriteString            ;; display pI string
        jmp  quit                   ;; jump to quit
    prizeII:    
        ;; $1 Million
        mov  edx,OFFSET pII         ;; move pII string into EDX
        call WriteString            ;; display pII string
        jmp  quit                   ;; jump to quit
    prizeIII:
        ;; $50,000
        mov  edx,OFFSET pIII        ;; move pIII string into EDX
        call WriteString            ;; display pIII string
        jmp  quit                   ;; jump to quit
    prizeIV:
        ;; $100
        mov  edx,OFFSET pIV         ;; move pIV string into EDX
        call WriteString            ;; display pIV string
        jmp quit                    ;; jump to quit
    prizeV:
        ;; $100
        mov  edx,OFFSET pV          ;; move pV string into EDX
        call WriteString            ;; display pV string
        jmp  quit                   ;; jump to quit
    prizeVI:
        ;; $7
        mov  edx,OFFSET pVI         ;; move pVI string into EDX
        call WriteString            ;; display pVI string
        jmp  quit                   ;; jump to quit
    prizeVII:
        ;; $7
        mov  edx,OFFSET pVII        ;; move pVII string into EDX
        call WriteString            ;; display pVII string
        jmp  quit                   ;; jump to quit
    prizeVIII:
        ;; $4
        mov  edx,OFFSET pVIII       ;; move pVIII string into EDX
        call WriteString            ;; display pVIII string
        jmp  quit                   ;; jump to quit
    prizeIX:
        ;; $4
        mov  edx,OFFSET pIX         ;; move pIX string into EDX
        call WriteString            ;; display pIX string
        jmp  quit                   ;; jump to quit
    ;; display results for Powerball draw (loser!)
    LOSE1:
        mov  edx,OFFSET loseI       ;; move loseI string into EDX
        call WriteString            ;; display loseI string
        jmp  quit                   ;; jump to quit
    LOSE2:
        mov  edx,OFFSET loseII      ;; move loseII string into EDX
        call WriteString            ;; display loseII string
        jmp  quit                   ;; jump to quit
    LOSE3:
        mov  edx,OFFSET loseIII     ;; move loseIII string into EDX
        call WriteString            ;; display loseIII string
        jmp  quit                   ;; jump to quit
    quit:
        call Crlf                   ;; jump to next line
        ret
ENDM

; main procedure
main PROC
    ; begin by filling Powerball draw with random numbers
    call drawNewPowerball   ; draw new set of Powerball numbers and populate 
                            ;   whiteBalls Powerball array + get value for red
                            ;   Powerball
    call Crlf               ; jump to next line
    call newUserEntry       ; have user enter their choice of Powerball values
    call Crlf               ; jump to next line
    call Crlf               ; jump to next line
    mCheckNumbers OFFSET uWtBalls,uRedBall  
                            ; check user-selected numbers against 
                            ;   Powerball draw
    exit                    ; exit program
main ENDP
;-------------------------------------------------------
drawNewPowerball PROC
;
; Procedure for resetting and redrawing
;   Powerball numbers.
; Receives: nothing
; Returns: nothing
;-------------------------------------------------------
.data
drawingResultsWt    BYTE    "Powerball drawing results: White balls ",0
adsp                BYTE    " ",0
drawingResultRed    BYTE    ", Red ball ",0

.code
    ; redraw red Powerball value
    mov  eax,26                     ; range of 0 to 25 for RandomRange
    call RandomRange                ; get random number between 0 and 25
    add  eax,1                      ; add 1 to result
    mov  redBall,eax                ; move EAX into redBall
    ; prepare to replace values in whiteBalls array
    mov  edi,OFFSET whiteBalls      ; move whiteBalls pointer into EDI
    mov  ecx,5                      ; length of whiteBalls array
    ; redraw all white Powerball values
    redraw:
        mov  eax,69                     ; range of 0 to 68 for RandomRange
        call RandomRange                ; get random number between 0 and 68
        add  eax,1                      ; add 1 to result
        mov  [edi],eax                  ; move EAX into whiteBalls array
        add  edi,4                      ; increment, move to next memory location   
    ; check to see if there are any duplicate values
    mov  edi,OFFSET whiteBalls+4    ; move second array location into EDI
    mov  ecx,4                      ; length of whiteBalls array-1
    check:
        mov  ebx,[edi-4]                ; move [EDI-4] into EBX
        cmp  ebx,[edi]                  ; check to see if EBX and [EDI] 
                                        ;   are equal
        je   rd2                        ; EBX is equal to [EDI], replace
                                        ;   selected value
        jmp  next                       ; else go to next position
    rd2:
        add  ecx,1                      ; add 1 to ECX
        mov  eax,69                     ; range of 0 to 68 for RandomRange
        call RandomRange                ; get random number between 0 and 68
        add  eax,1                      ; add 1 to result
        mov  [edi],eax                  ; replace value stored at current
                                        ;   pointer location with EAX
        jmp  check                      ; return to check
    next:
        add  edi,4                      ; add 4 to EDI to move to next location
                                        ;   in the array
        jmp  check                      ; return to check
    quit:
        ; show Powerball drawing results
        mov  edx,OFFSET drawingResultsWt
        call WriteString            ; display drawingResultsWt string
        mov  edi,OFFSET whiteBalls  ; move whiteBalls pointer back into EDI
        mov  ecx,4
        wB:
            mov  eax,[edi]              ; move current value into EAX
            call WriteInt               ; display value
            mov  edx,OFFSET adsp
            call WriteString            ; display space after number
            add  edi,4                  ; increment, move to next memory location
        mov  edi,OFFSET whiteBalls  ; move whiteBalls pointer back into EDI
        mov  eax,[edi+16]           ; get value at end of whiteBalls
        call WriteInt               ; display value
        mov  edx,OFFSET drawingResultRed
        call WriteString            ; display drawingResultRed string
        mov  eax,redBall
        call WriteInt               ; display redBall value
        call Crlf                   ; jump to next line
        ret
drawNewPowerball ENDP
;-------------------------------------------------------
newUserEntry PROC
;
; Procedure for user selecting a new set 
;   of Powerball numbers.
; Receives: user input
; Returns: nothing
;-------------------------------------------------------
.data
firstNumber     BYTE    "Please enter your first white number: ",0
secondNumber    BYTE    "Please enter your second white number: ",0
thirdNumber     BYTE    "Please enter your third white number: ",0
fourthNumber    BYTE    "Please enter your fourth white number: ",0
fifthNumber     BYTE    "Please enter your fifth white number: ",0
redNumber       BYTE    "Please enter your red number: ",0

.code
    mov  edi,OFFSET uWtBalls        ; move uWtBalls pointer into EDI
    uno:
        mov  edx,OFFSET firstNumber     ; move firstNumber string into EDX
        call WriteString                ; display firstNumber
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   uno                        ; if EAX is equal to zero, return to 
                                        ;   beginning of loop
        cmp  eax,69                     ; compare EAX to 69
        ja   uno                        ; if EAX is greater than 69, return to
                                        ;   beginning of loop
        mov  [edi],eax                  ; store EAX at pointer location
        add  edi,4                      ; go to the next pointer location
    dos:
        mov  edx,OFFSET secondNumber    ; move secondNumber string into EDX
        call WriteString                ; display secondNumber
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   dos                        ; if EAX is equal to zero, return to 
                                        ;   beginning of loop
        cmp  eax,69                     ; compare EAX to 69
        ja   dos                        ; if EAX is greater than 69, return to
                                        ;   beginning of loop
        mov  [edi],eax                  ; store EAX at pointer location
        mov  ebx,[edi-4]                ; copy previous pointer location into EBX
        cmp  ebx,[edi]                  ; compare EBX and [EDI]
        je   dos                        ; if EBX == [EDI] repeat dos loop
        jmp  tres                       ; else proceed to tres loop
    tres:
        add  edi,4                      ; go to next pointer location
        mov  edx,OFFSET thirdNumber     ; move thirdNumber string into EDX 
        call WriteString                ; display thirdNumber string
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   tres                       ; if EAX is equal to zero, return to 
                                        ;   beginning of loop
        cmp  eax,69                     ; compare EAX to 69
        ja   tres                       ; if EAX is greater than 69, return to
                                        ;   beginning of loop
        mov  [edi],eax                  ; store EAX at pointer location
        mov  ebx,[edi-4]                ; copy previous pointer location into EBX
        cmp  ebx,[edi]                  ; compare EBX and [EDI]
        je   tres                       ; if EBX == [EDI] repeat tres loop
        jmp  cuatro                     ; else proceed to cuatro loop
    cuatro:
        add  edi,4                      ; go to next pointer location
        mov  edx,OFFSET fourthNumber    ; move fourthNumber string into EDX
        call WriteString                ; display fourthNumber string
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   cuatro                     ; if EAX is equal to zero, return to 
                                        ;   beginning of loop
        cmp  eax,69                     ; compare EAX to 69
        ja   cuatro                     ; if EAX is greater than 69, return to
                                        ;   beginning of loop
        mov  [edi],eax                  ; store EAX at pointer location
        mov  ebx,[edi-4]                ; copy previous pointer location into EBX
        cmp  ebx,[edi]                  ; compare EBX and [EDI]
        je   cuatro                     ; if EBX == [EDI] repeat cuatro loop
        jmp  cinco                      ; else proceed to cinco loop
    cinco:
        add  edi,4                      ; go to next pointer location
        mov  edx,OFFSET fifthNumber     ; move fifthNumber string into EDX
        call WriteString                ; display fifthNumber string
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   cinco                      ; if EAX is equal to zero, return to 
                                        ;   beginning of loop
        cmp  eax,69                     ; compare EAX to 69
        ja   cinco                      ; if EAX is greater than 69, return to
                                        ;   beginning of loop
        mov  [edi],eax                  ; store EAX at pointer location
        mov  ebx,[edi-4]                ; copy previous pointer location into EBX
        cmp  ebx,[edi]                  ; compare EBX and [EDI]
        je   cinco                      ; if EBX == [EDI] repeat loop
        jmp  quit                       ; else continue to quit loop
    quit:
        mov  edx,OFFSET redNumber       ; move redNumber string into EDX
        call WriteString                ; display redNumber string
        call ReadInt                    ; read in the number the user entered
                                        ;   and store it in EAX
        cmp  eax,0                      ; compare EAX to 0
        je   quit                       ; if EAX is equal to zero, return to
                                        ;   beginning of loop
        cmp  eax,26                     ; compare EAX to 26
        ja   quit                       ; if EAX is greater than 26, return to 
                                        ;   beginning of loop
        mov  uRedBall,eax               ; else move EAX into uRedBall
        ret
newUserEntry ENDP
END main
EN

回答 1

Stack Overflow用户

发布于 2022-11-15 23:52:21

电文1

使用宏mCheckNumbers OFFSET uWtBalls,uRedBall的调用mCheckNumbers MACRO wballs:REQ, rball:REQcmp rball,redball行中rball的参数替换将生成行。

代码语言:javascript
复制
cmp uRedBall, redBall

这是一个不可编码的指令,因为两个操作数都指向内存.为此,您收到了“无效指令操作数”错误。

代码语言:javascript
复制
checkRed:
    mov  redMatch, 0
    mov  eax, rball
    cmp  eax, redBall
    jne  getResults       ; notEqual
    mov  redMatch, 1
getResults:

为了消除很多这种情况,我预先加载了零的redMatch变量。如果数字不匹配,我将分支到getResults,而无需再多加考虑。

电文2

使用宏mCheckNumbers OFFSET uWtBalls,uRedBall的调用mCheckNumbers MACRO wballs:REQ, rball:REQmov ecx,LENGTHOF wballs行中wball的参数替换将生成行。

代码语言:javascript
复制
mov  ecx,LENGTHOF OFFSET uWtBalls

这个操作数没有意义!为此您收到了“表达式中的语法错误”错误。

是否将宏调用更改为:

代码语言:javascript
复制
mCheckNumbers uWtBalls, uRedBall

并将宏本身中的代码转换为:

代码语言:javascript
复制
mov  edi, OFFSET wballs
mov  ecx, LENGTHOF wballs

检查这些逻辑错误

  • 您的checkWhite嵌套循环总是会增加countWMatches变量,因为要么跳到bigNext (在真正匹配的情况下),要么跳入bigNext (如果没有匹配)。

因为这些数组太短了,所以在匹配的情况下,提前退出并不重要。而且,由于不存在重复的数字,所以countWMatches变量不存在多次增量的风险。

我建议使用不同寄存器作为计数器的下一个嵌套循环:

代码语言:javascript
复制
    mov  edi, OFFSET wballs
    mov  edx, LENGTHOF wballs
checkWhite:
    mov  esi, OFFSET whiteBalls
    mov  ecx, LENGTHOF whiteBalls
findMatch:
    lodsd
    cmp  eax, [edi]
    jne  next
    add  countWMatches, 1
next:
    dec  ecx
    jnz  findMatch
    add  edi, 4
    dec  edx
    jnz  checkWhite
checkRed:

为什么代码的这一部分有条件跳转要退出?难道你不想显示loseIII消息“你完全没有匹配!你输了!”。

但是,如果有人能想出一种方法来大大简化我的代码,我会欣喜若狂的。

一旦你的程序开始工作,你就可以在the CodeReview forum上提交它供评审。我相信比我今天写的更能简化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74437357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档