News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

OPENSOURCE textgame 'luck' full source inside

Started by Foulone, February 26, 2005, 02:29:19 PM

Previous topic - Next topic

Foulone

Hi, This is an experiment to encourage contributions from all.

Find below my first assembler program, I would like to complete the program with all the items in the todo list complete.

All contributions/suggestions/improvements/optimizations welcome.

; ***************
; ** TO DO LIST **
; ***************

1) Introduce random number generator, maybe storing the seed in the registry
2) check for 'y' | 'Y' key being pressed at the end of a game
3) have a 10 name highscore table stored in the registry, if you qualify you can enter your score
4) Have 10 tiers or ranking with messages, ie if you score <5 "Excellent job, your one of the best" <10"Better than average, keep trying" etc...
5) display the 10 highscores at the end of the game


; *************
; ** LUCK.ASM **
; *************

.486                                      ; create 32 bit code
.model flat, stdcall                  ; 32 bit memory model
option casemap :none                  ; case sensitive
;--------------------------------------------------------------------------------
include \masm32\include\windows.inc    ; always first
include \masm32\macros\macros.asm      ; MASM support macros
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\kernel32.inc
;--------------------------------------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\kernel32.lib
;--------------------------------------------------------------------------------
.data ; data seg
magic_num dw 100
num_guess dw 0
str1 dd 0                        ; a string handle for the input data
;--------------------------------------------------------------------------------
.code                        ; Tell MASM where the code starts
start:                                       ; The CODE entry point to the program
    print   chr$("Test your luck, guess the number:",13,10,13,10)
mov num_guess,0
loop1:
inc num_guess
mov str1, input(" ",3eh,": ") ; 3eh =">" chracter
    mov eax,sval(str1)        ; convert the result to a signed integer
    cmp magic_num, ax
    je correct
    jl smaller
    print chr$(13,10,"too small",13,10)
    jmp loop1
smaller:
    print chr$(13,10,"too big",13,10)
    jmp loop1
correct:
    print chr$(13,10,"Rank: ")
xor ecx,ecx
mov cx,num_guess
    print str$(ecx)
    print chr$(" out of 100",13,10)
    mov    str1, input(13,10,13,10,"The game is over, Play again (y/n)")
    exit
end start                        ; Tell MASM where the program ends


I just added the code /code tags in square brackes to make your code easier to read. hutch--

Foulone

Found a random number routine and got ollydbg up and running (looks like a mighty fine debugger!).

I have incorporated this code into the project, but the code displayed looks invalid in ollydbg.
Can anyone shed any light on this?

; - Source code -

random proc

   mov eax, rseed
   mov ecx, 23
   mul ecx
   add eax, 7
   and eax, 0FFFFFFFFh
   ror eax, 1
   xor eax, rseed
   mov rseed, eax
   mov ecx, range
   xor edx, edx
   div ecx
   mov eax, edx
   ret

random endp

; - Ollydbg code -

0040110E > $ A1 08404000    MOV EAX,DWORD PTR DS:[rseed]
00401113   . B9 17000000    MOV ECX,17
00401118   . F7E1           MUL ECX
0040111A   . 83C0 07        ADD EAX,7
0040111D   . 83E0 FF        AND EAX,FFFFFFFF
00401120   . D1C8           ROR EAX,1
00401122     33             DB 33                                    ;  CHAR '3'                      <--- WHAT HAS HAPPENED  HERE ?????
00401123     05             DB 05
00401124 > . 08404000       DD OFFSET Luck.rseed
00401128   . A3 08404000    MOV DWORD PTR DS:[rseed],EAX
0040112D   . 8B0D 0C404000  MOV ECX,DWORD PTR DS:[range]
00401133   . 33D2           XOR EDX,EDX
00401135   . F7F1           DIV ECX
00401137   . 8BC2           MOV EAX,EDX
00401139   . C3             RETN


hutch--

Hi,

Nice clear example but I have 2 nags for you. Unless you have good reason to use the two DW sized variables, make them DD (DWORD) as it will effect a larger project where speed matters.

The other is a comment you made alongside the .DATA directive. Segments belong back in the segmented DOS era and we are thankfully past that era. A 32 bit PE file is divided into SECTIONS by the file format so initialised data is in the .DATA section, not segment.

Keep up the good work.  :U
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Foulone

#3
Thanks for the input hutch--

any more comments?

; ***************
; ** TO DO LIST **
; ***************

1) Introduce random number generator, maybe storing the seed in the registry
** Done, no need to store number in registry, just get a new seed!

2) check for 'y' | 'Y' key being pressed at the end of a game
3) have a 10 name highscore table stored in the registry, if you qualify you can enter your score
4) Have 10 tiers or ranking with messages, ie if you score <5 "Excellent job, your one of the best" <10"Better than average, keep trying" etc...
5) display the 10 highscores at the end of the game


; Code:

.486                                      ; create 32 bit code
.model flat, stdcall                  ; 32 bit memory model
option casemap :none                  ; case sensitive
;--------------------------------------------------------------------------------
include \masm32\include\windows.inc    ; always first
include \masm32\macros\macros.asm      ; MASM support macros
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\kernel32.inc
;--------------------------------------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\kernel32.lib
;--------------------------------------------------------------------------------
max_range = 100 ; Max range for random numbers

.data? ; DATA (uninitialised)  section
magic_num dd ? ; the number we are trying to guess
num_guess dd ? ; number of guess's
str1 dd ?                      ; a string handle for the input data
ran_seed dd ? ; Random number seed
ran_range dd ? ; Random number range

.data ; DATA (initialised) section
luck1_str db "Your luck is in today, go and buy a lottery ticket!",0
luck10_str db "Looking like a grim day for you my friend, stay indoors!",0

;--------------------------------------------------------------------------------
.code                        ; CODE section
start:                                       ; Entry point to the program
call init_random
mov [ran_range],max_range
call random
inc eax ; I want the number to be from 1 to max_range (not 0 to max_range-1)
mov [magic_num],eax
mov [num_guess],0
    print   chr$("Test your luck, guess the number:",13,10,13,10)
loop1:
inc [num_guess]
mov str1, input(" ",3eh,": ") ; 3eh =">" chracter
    mov eax,sval(str1)        ; convert the result to a signed integer
    cmp [magic_num],eax
    je correct
    jl smaller
    print chr$(13,10,"too small",13,10)
    jmp loop1
smaller:
    print chr$(13,10,"too big",13,10)
    jmp loop1
correct:
    print chr$(13,10,"Rank: ")
mov ecx,[num_guess]
    print str$(ecx)
    print chr$(" out of 100",13,10)
    mov    str1, input(13,10,13,10,"The game is over, Play again (y/n)")
    exit

random proc
; Returns a random number
; ENTRY: ran_range = dd range value
; EXIT:  ax = random number within range (0 to ran_range-1)
; TRASH: eax,ecx,edx

mov eax, [ran_seed]
mov ecx, 23
mul ecx
add eax, 7
ror eax, 1
xor eax, [ran_seed]
mov [ran_seed], eax
mov ecx, [ran_range]
xor edx, edx
div ecx
mov eax, edx
ret

random endp

init_random proc
; Init random number seed (ran_seed)
; TRASH: all

INVOKE GetTickCount
mov [ran_seed],eax
ret

init_random endp

end start                        ; End of code


hutch--

 :bg

Quote
any more comments?

YES, use te code tags around your examples as it makes it a lot easier to read.

Use square brackets, precede the code block with the word  "code"  in square brackets and terminate the block with the "/code" in square brackets.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

Foulone

#5
Could somebody have a look at the marked portion of code below please and suggest a more efficient way of doing it?

cheers

; ***************
; ** TO DO LIST **
; ***************

1) Introduce random number generator, maybe storing the seed in the registry
** Done, no need to store number in registry, just get a new seed!

2) check for 'y' | 'Y' key being pressed at the end of a game
** Done

3) have a 10 name highscore table stored in the registry, if you qualify you can enter your score
4) Have 10 tiers or ranking with messages, ie if you score <5 "Excellent job, your one of the best" <10"Better than average, keep trying" etc...
5) display the 10 highscores at the end of the game


.486                                      ; create 32 bit code
.model flat, stdcall                  ; 32 bit memory model
option casemap :none                  ; case sensitive
;--------------------------------------------------------------------------------
include \masm32\include\windows.inc    ; always first
include \masm32\macros\macros.asm      ; MASM support macros
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\kernel32.inc
;--------------------------------------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\kernel32.lib
;--------------------------------------------------------------------------------
max_range = 100 ; Max range for random numbers

.data? ; DATA (uninitialised)  section
magic_num dd ? ; the number we are trying to guess
num_guess dd ? ; number of guess's
str1 dd ?                      ; a string handle for the input data
ran_seed dd ? ; Random number seed
ran_range dd ? ; Random number range

.data ; DATA (initialised) section
luck1_str db "Your luck is in today, go and buy a lottery ticket!",0
luck10_str db "Looking like a grim day for you my friend, stay indoors!",0
y_string db "yY"
;--------------------------------------------------------------------------------
.code                        ; CODE section

start:                                       ; Entry point to the program
call init_random
restart:
mov [ran_range],max_range
call random
inc eax ; I want the number to be from 1 to max_range (not 0 to max_range-1)
mov [magic_num],eax
mov [num_guess],0
    print   chr$(13,10,13,10,"Test your luck, guess the number from ",28h,"1 to ")
mov ecx,max_range
print str$(ecx)
    print   chr$(29h,13,10,13,10)
loop1:
inc [num_guess]
mov str1, input(" ",3eh,": ") ; 3eh =">" chracter
    mov eax,sval(str1)        ; convert the result to a signed integer
    cmp [magic_num],eax

; cmp eax,eax                                                 ; ** Uncomment so loop falls through

    je correct
    jl smaller
    print chr$(13,10,"too small",13,10)
    jmp loop1
smaller:
    print chr$(13,10,"too big",13,10)
    jmp loop1
correct:
    print chr$(13,10,"Rank: ")
mov ecx,[num_guess]
    print str$(ecx)
    print chr$(" out of 100",13,10)
    mov    str1,input(13,10,13,10,"The game is over, Play again (y/n)")

; **** CAN THIS BE OPTIMIZED ****

mov esi,str1
lea edi,y_string
cmpsb
je restart
inc edi
cmpsb
je restart
    exit

; ******************************

; movzx eax, byte ptr[str1]
; cmp eax, "Y"
; jz restart
; cmp eax, "y"
; jz restart
; exit


random proc
; Returns a random number
; ENTRY: ran_range = dd range value
; EXIT:  eax = random number within range (0 to ran_range-1)
; TRASH: eax,ecx,edx

mov eax, [ran_seed]
mov ecx, 23
mul ecx
add eax, 7
ror eax, 1
xor eax, [ran_seed]
mov [ran_seed], eax
mov ecx, [ran_range]
xor edx, edx
div ecx
mov eax, edx
ret

random endp

init_random proc
; Init random number seed (ran_seed)
; TRASH: all

INVOKE GetTickCount
mov [ran_seed],eax
ret

init_random endp

end start                        ; End of code