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--
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
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
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
: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.
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