Wheel of Fortune

Dani 0 Tallied Votes 372 Views Share

This is a program I wrote for my x86 assembly class which revolves a "roulette wheel" around. Wait about a minute and it will eventually slow down to a stop. It uses Irvine32.inc which came with the textbook.

title Wheel of Fortune								(fortune.asm)

; Dani Horowitz
; CSC111 x86 Assembly Programming

; This program plays wheel of fortune

INCLUDE Irvine32.inc

;--------------------------------------------------
.stack			; begin stack segment

;--------------------------------------------------
.data			; begin data segment

	xcoord	byte	 5,	10,	15,	20,	25,	30,
					30, 30, 30, 30, 30, 30,
					30, 25, 20, 15, 10,  5,
					 5, 5,   5,  5,  5,  5
					
	ycoord	byte	 5,	 5,	 5,	 5,	 5,	 5,
					10, 15, 20, 25, 30, 35,
					40, 40, 40, 40, 40, 40,
					35, 30, 25, 20, 15, 10

	numbers			dword 0,1,2,3,4,5,6,
						    8,6,5,4,3,2,
						    1,2,3,4,5,6,
						    8,6,5,4,3,2

	wheel_slot		dword	0
	rotation_count	dword	0
	countdown		dword	1
;--------------------------------------------------
.code			; begin code segment

;--------------------------------------------------
printnumber PROC
; prints numbers[wheel_slot*4] at coordinates
; xcoord[wheel_slot], ycoord[wheel_slot]
; where wheel_slot is from 0 thru n
;--------------------------------------------------
	; ## position cursor ##
	mov		esi, OFFSET xcoord
	add		esi, wheel_slot
	mov		dl, [esi]
	mov		esi, OFFSET ycoord
	add		esi, wheel_slot
	mov		dh, [esi]
	call	Gotoxy

	; ## get value ##
	mov		esi, OFFSET numbers
	mov		eax, wheel_slot
	inc		eax
	mov		ebx, 4
	mul		ebx
	add		esi, eax
	mov		eax, [esi]
	
	; ## write value ##
	call	WriteChar
	ret
;--------------------------------------------------
printnumber ENDP
;--------------------------------------------------

;--------------------------------------------------
printwheel proc
; calls printnumber for each of the n wheel_slots
;--------------------------------------------------
	mov		wheel_slot, 0
NextNum:	
	;; ## print each number of the array once ##
	call	printnumber
	inc		wheel_slot
	cmp		wheel_slot, 24							; XX edit XX
	jl		NextNum
	ret
;--------------------------------------------------
printwheel ENDP
;--------------------------------------------------

;--------------------------------------------------
shiftleft proc
;--------------------------------------------------
	;; ## shift each number of the array left
	push	esi
	mov		eax, [esi]
	sub		esi, 4
	mov		[esi], eax
	pop		esi
	ret
;--------------------------------------------------
shiftleft ENDP
;--------------------------------------------------

;--------------------------------------------------
shiftaround proc
;--------------------------------------------------
	;; ## loop first number of array to last position
	push	esi
	mov		esi, OFFSET numbers
	mov		eax, [esi]
	add		esi, 96									;; XX edit*4 XX
	mov		[esi], eax
	pop		esi
	ret
;--------------------------------------------------
shiftaround ENDP
;--------------------------------------------------

;--------------------------------------------------
spinwheel proc
;--------------------------------------------------
	; ## find array ##
	mov		rotation_count, 0
	mov		esi, OFFSET numbers	
	add		esi, 4
	
MoveNumber:
	; ## shift the wheel one iteration
	call	shiftleft
	add		esi, 4
	inc		rotation_count
	cmp		rotation_count, 24						;; XX edit XX
	jl		MoveNumber
	call	shiftaround	
	ret
;--------------------------------------------------
spinwheel ENDP
;--------------------------------------------------

;--------------------------------------------------
printwin proc
;--------------------------------------------------
.data
	points	byte	" points", 0
.code
	; ## print winning character
	mov		dl, 18
	mov		dh, 20
	call	Gotoxy
	mov		esi, OFFSET numbers
	add		esi, 8
	mov		eax, [esi]
	call	WriteChar
	mov		ebx, eax
	mov		eax, '!'
	call	WriteChar
	; ## print winning points
	mov		dl, 15
	mov		dh, 25
	call	Gotoxy
	mov		eax, ebx
	call	WriteDec
	mov		edx, OFFSET points
	call	WriteString
	; ## reposition cursor
	mov		dl, 5
	mov		dh, 45
	call	Gotoxy
	ret
;--------------------------------------------------
printwin ENDP
;--------------------------------------------------

;--------------------------------------------------
randomval proc
;--------------------------------------------------
	mov		eax, 5				; generate random #
	call	RandomRange
	add		countdown, eax		; increase countdown
	mov		eax, countdown
	call	Delay				; pause the wheel
	ret
;--------------------------------------------------
randomval ENDP
;--------------------------------------------------

;--------------------------------------------------
main proc
;--------------------------------------------------
	call	Clrscr				; clear screen
	call	Randomize			; randomize seed
Spin:	
	call	spinwheel			; shift wheel left
	call	printwheel			; print current wheel values
	call	randomval			; wait increasing amount of time
	cmp		countdown, 350		; if too slow, stop wheel
	jl		Spin				;   otherwise, spin again
	call	printwin			; print winning character
	call	Waitmsg
	call	Clrscr
	exit	
main  endp
end main
;--------------------------------------------------

Dani AI

Generated

Nice classroom example from — compact and easy to follow. For anyone reusing this code years later, a few concrete fixes make the wheel reliable and safe: there are a couple of indexing/pointer errors and a printing detail that commonly show up in student assembler projects.

The main problems are off-by-one / element-size mistakes when indexing the dword numbers array and a boundary write when wrapping the first element to the last. Index arithmetic must account for element size (4 bytes). For example, compute the byte offset as wheel_slot * 4 instead of adding the raw slot value. A safe way to load the chosen dword is:

; address of numbers[wheel_slot]
mov eax, wheel_slot
shl eax, 2        ; eax = wheel_slot * 4
lea esi, [numbers + eax]
mov eax, [esi]    ; load numbers[wheel_slot]

When moving the first element to the last slot, write it at (SLOT_COUNT-1)*4, not at SLOT_COUNT*4 (which is one dword past the array). Example:

; place numbers[0] into numbers[SLOT_COUNT-1]
mov eax, SLOT_COUNT
dec eax
shl eax, 2        ; (SLOT_COUNT-1)*4
lea edi, [numbers + eax]
mov eax, [numbers]
mov [edi], eax

Printing note: if numbers holds numeric values 0..9, convert to ASCII before WriteChar (add '0' to AL) or use a decimal print routine. A more robust design avoids physically shifting the whole array on every tick: keep a rotation offset and compute the logical index when drawing (index = (slot + offset) mod SLOT_COUNT). This removes repeated memory moves and eliminates many boundary bugs.

Other suggestions: replace magic constants with named EQU/EQUATE values (SLOT_COUNT, ELEMENT_SIZE), verify register use with the Irvine32 docs, and step through a few rotations in a debugger to watch computed addresses. Credit to for the original program and to for the acknowledgement.

holmes008 0 Light Poster

Thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.