我已经创建了一个强力球抽奖模拟,它应该检查用户选择的号码与一组随机生成的号码,并告诉用户他们是否赢得了任何东西(如下所示)。x1c 0d1x
用户是否知道强力球的号码并不重要;该程序应该对照随机生成的输入来检查用户的输入。
我试图使用宏(我必须使用),但我不断收到以下错误:
由于这是我第一次使用宏,我并不完全理解如何使用它们,所以欢迎解释如何正确地将数组作为输入(但不是必需的)。然而,如果有人能想到一种方法来大大简化我的代码,我将欣喜若狂。我的代码如下所示。
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
1条答案
按热度按时间pu3pd22g1#
消息1
通过调用宏
mCheckNumbers MACRO wballs:REQ, rball:REQ
的mCheckNumbers OFFSET uWtBalls,uRedBall
,对行cmp rball,redball
中的 * rball * 进行参数替换将产生以下行:这是一条不可编码的指令,因为两个操作数都引用内存。您收到了有关此指令的"invalid instruction operand"(无效指令操作数)错误。
为了消除大量的跳跃,我将 * redMatch * 变量预加载为零。如果数字不匹配,我将直接分支到 * getResults *。
消息2
通过调用宏
mCheckNumbers MACRO wballs:REQ, rball:REQ
的mCheckNumbers OFFSET uWtBalls,uRedBall
,对行mov ecx,LENGTHOF wballs
中的 * wballs * 进行参数替换将产生以下行此操作数没有意义!您收到了"表达式中的语法错误"错误。
将宏调用更改为:
和宏本身中的代码转换为:
checkout 这些逻辑错误
因为这些数组很短,所以在匹配的情况下提前退出并不重要,而且因为不存在重复的数字,所以不存在对 * countWMatches * 变量进行多次递增的风险。
我建议在下一个嵌套循环中使用不同的寄存器作为计数器:
为什么这部分代码有一个条件跳转到 * quit *?难道你不想显示 * loseIII * 消息"你完全没有匹配!你输了!"
但是,如果有人能想出一种方法来大大简化我的代码,我会欣喜若狂。
一旦你的程序开始运行,你可以在the CodeReview forum上提交它以供审查。我相信它将有可能比我今天写的更简单。