Sign in to follow this  
assainator

assembly guess game

Recommended Posts

heey all, i tried to learn assembly and after a few tries, it got the hang of it. i created a static guess game (with static i mean that the number is hardcoded, and can't be changed) i used MASM a screenshot (tough it is not pretty source:
;some programm declarations
  .486
  .model flat, stdcall
  option casemap :none

;===============standard headers=============
  include \masm32\include\windows.inc
  include \masm32\macros\macros.asm

;===============minimal headers===============
  include \masm32\include\masm32.inc
  include \masm32\include\user32.inc
  include \masm32\include\gdi32.inc
  include \masm32\include\kernel32.inc
  
;============minimal libarys===============
  includelib \masm32\lib\masm32.lib
  includelib \masm32\lib\user32.lib
  includelib \masm32\lib\gdi32.lib
  includelib \masm32\lib\kernel32.lib

.code             ;here the code starts

start:            ;the entry point of the programm
  
  call main       ;call the main PROCedure
  
  exit            ;exit process

main proc
  LOCAL int1:DWORD
  LOCAL str1:DWORD
  print chr$("where gonna play a game -->;;; guess the number!!!", 13, 10)
  
  game:
    print chr$(" ",13,10)
    mov str1, input("please enter a positive number below 20: ") ;ask for input
    mov int1, sval(str1)     ;convert from string to unsigned int
    
    cmp int1, 6       ;compare the "int1" number with "6"
    je equel          ;if comparisation was equell jump to "equel"
    jg greater        ;if comparisation was greater jump to "greater"
    jl lesser         ;if comparisation was lesser jump to "lesser"
  
  equel:
    print chr$("    CORRECT!!!!",13,10)
    jmp done
    
  greater:
    print chr$("    Your guess was to high", 13, 10)
    jmp game
  
  lesser:
    print chr$("    Your guess was to low", 13, 10)
    jmp game
  
  done:
    ret
  
main endp

end start




assainator [Edited by - assainator on September 14, 2009 5:12:54 AM]

Share this post


Link to post
Share on other sites
thanks, and yes, it is real fun.
what i also like is the fact that the executebles are FAR smaller than that of a C++ one.
i created a C++ version of the same thing, and it was 30kb, while the assembly one is 3 kb.

assainator

Share this post


Link to post
Share on other sites
Sigh... you kids have it too easy these days. Where are your int 21's, desired strings manually inserted into memory, character terminated strings? *rolls eyes*

Still nice work though, a lot of people don't bother to learn assembly language anymore :(

Share this post


Link to post
Share on other sites
Nice =)


Pong!:

.486
.model flat, stdcall
option casemap: none

; Libs
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

; Extern library functions
RegisterClassExW PROTO :DWORD
UnregisterClassW PROTO :DWORD,:DWORD
LoadIconW PROTO :DWORD,:DWORD
LoadCursorW PROTO :DWORD,:DWORD
GetModuleHandleW PROTO :DWORD

DefWindowProcW PROTO :DWORD,:DWORD,:DWORD,:DWORD

CreateWindowExW PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ShowWindow PROTO :DWORD,:DWORD
SetWindowLongW PROTO :DWORD,:DWORD,:DWORD
GetWindowLongW PROTO :DWORD,:DWORD
AdjustWindowRectEx PROTO :DWORD,:DWORD,:DWORD,:DWORD
GetClientRect PROTO :DWORD,:DWORD

GetMessageW PROTO :DWORD,:DWORD,:DWORD,:DWORD
TranslateMessage PROTO :DWORD
DispatchMessageW PROTO :DWORD
PostQuitMessage PROTO :DWORD

GetLastError PROTO

GetDC PROTO :DWORD
ReleaseDC PROTO :DWORD,:DWORD
StretchDIBits PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD

VirtualAlloc PROTO :DWORD,:DWORD,:DWORD,:DWORD
VirtualFree PROTO :DWORD,:DWORD,:DWORD

SetTimer PROTO :DWORD,:DWORD,:DWORD,:DWORD


.code

start:

; WinMain
main PROC
push ebp
mov ebp, esp

; Reserve some stack space
sub esp, 516

; Keep key-states at [ebp-512]
mov ecx, 256
zeroKeys:
mov byte ptr [ebp+ecx-512], 0
loop zeroKeys

; Allocate the backbuffer
push 04h
push 03000h
push 640*480*4
push 0
call VirtualAlloc
mov dword ptr [ebp-92], eax

; Window/Class name at [ebp-128]
mov word ptr [ebp-128], 'P'
mov word ptr [ebp-126], 'o'
mov word ptr [ebp-124], 'n'
mov word ptr [ebp-122], 'g'
mov word ptr [ebp-120], '!'
mov word ptr [ebp-118], 0

; Register window-class
mov dword ptr [ebp-48], 48

mov dword ptr [ebp-44], 0

mov dword ptr [ebp-40], OFFSET my_WndProc

mov dword ptr [ebp-36], 0
mov dword ptr [ebp-32], 0

push 0
call GetModuleHandleW
mov dword ptr [ebp-28], eax

push 07f00h
push 0
call LoadIconW
mov dword ptr [ebp-24], eax

push 07f00h
push 0
call LoadCursorW
mov dword ptr [ebp-20], eax

mov dword ptr [ebp-16], 5+1

mov dword ptr [ebp-12], 0

lea eax, [ebp-128]
mov dword ptr [ebp-8], eax

mov dword ptr [ebp-4], 0

lea eax, [ebp-48]
push eax
call RegisterClassExW

; Adjust window rect to fit backbuffer
mov dword ptr [ebp-110], 0
mov dword ptr [ebp-106], 0
mov dword ptr [ebp-102], 640
mov dword ptr [ebp-98], 480
push 0
push 0
push 02cf0000h
lea eax, [ebp-110]
push eax
call AdjustWindowRectEx

; Create window (pass key-states array as lpParam)
lea eax, [ebp-512]
push eax
push dword ptr [ebp-28]
push 0
push 0
mov eax, dword ptr [ebp-98]
sub eax, dword ptr [ebp-106]
push eax
mov eax, dword ptr [ebp-102]
sub eax, dword ptr [ebp-110]
push eax
push 080000000h
push 080000000h
push 02cf0000h
push dword ptr [ebp-8]
push dword ptr [ebp-8]
push 0
call CreateWindowExW
mov dword ptr [ebp-110], eax

; Get DC
push eax
call GetDC
mov dword ptr [ebp-106], eax

; Create timer for game-frames
push 0
push 0
push 0
push 0
call SetTimer
mov dword ptr [ebp-88], eax

; Show the window
push 05h
push dword ptr [ebp-110]
call ShowWindow

; Keep game-state at [ebp-250]
mov dword ptr [ebp-250], 240
mov dword ptr [ebp-246], 220
mov dword ptr [ebp-242], 320
mov dword ptr [ebp-238], 240
mov dword ptr [ebp-234], -3
mov dword ptr [ebp-230], 1
mov dword ptr [ebp-226], 0
mov dword ptr [ebp-222], 0

; Main window loop
mainLoop:
; Wait for message
push 0
push 0
push 0
lea eax, [ebp-76]
push eax
call GetMessageW

cmp eax, 0
jz endQuit
cmp eax, -1
jz endErr

; Check if it's our game-frame timer
cmp dword ptr [ebp-72], 0113h
jne handleMessage
mov eax, dword ptr [ebp-88]
cmp dword ptr [ebp-68], eax
jne handleMessage

; Handle game-frame

; Handle keys
cmp byte ptr [ebp-512+38], 0
je skipUpKey
add dword ptr [ebp-250], 3
skipUpKey:
cmp byte ptr [ebp-512+40], 0
je skipDownKey
sub dword ptr [ebp-250], 3
skipDownKey:

; Handle/Draw game
lea eax, [ebp-250]
push eax
push 480
push 640
push dword ptr [ebp-92]
call my_gameFrame
add esp, 16

; BITMAPINFO
mov dword ptr [ebp-200+0], 40
mov dword ptr [ebp-200+4], 640
mov dword ptr [ebp-200+8], 480
mov word ptr [ebp-200+12], 1
mov word ptr [ebp-200+14], 32
mov dword ptr [ebp-200+16], 0
mov dword ptr [ebp-200+20], 0
mov dword ptr [ebp-200+24], 0
mov dword ptr [ebp-200+28], 0
mov dword ptr [ebp-200+32], 0
mov dword ptr [ebp-200+36], 0
mov dword ptr [ebp-200+40], 0

; Get window rect
lea eax, [ebp-150]
push eax
push dword ptr [ebp-110]
call GetClientRect

; StretchDIBits
push 0cc0020h
push 0
lea eax, [ebp-200]
push eax
push dword ptr [ebp-92]
push 480
push 640
push 0
push 0
push dword ptr [ebp-138]
push dword ptr [ebp-142]
push 0
push 0
push dword ptr [ebp-106]
call StretchDIBits

jmp mainLoop

; Dispatch message if it's not game-frame timer
handleMessage:
lea eax, [ebp-76]
push eax
call TranslateMessage

lea eax, [ebp-76]
push eax
call DispatchMessageW

jmp mainLoop

; Clean up after loop ended
endErr:
mov dword ptr [ebp-68], 0

endQuit:

; Release DC
push dword ptr [ebp-106]
push dword ptr [ebp-110]
call ReleaseDC

; Unregister the window-class
push dword ptr [ebp-28]
push dword ptr [ebp-8]
call UnregisterClassW

; Free back-buffer
push 08000h
push 0
push dword ptr [ebp-92]
call VirtualFree

; Exit-code
mov eax, dword ptr [ebp-68]

; Exit
mov esp, ebp
pop ebp
ret
main ENDP


; WndProc for main window
my_WndProc PROC
push ebp
mov ebp, esp

; WM_DESTROY
cmp dword ptr [ebp+12], 02h
jne notDestroy
push 0
call PostQuitMessage
jmp defFunc
notDestroy:

; WM_CREATE
cmp dword ptr [ebp+12], 01h
jne notCreate
; Store the key-states array as GWL_USERDATA
mov eax, dword ptr [ebp+20]
push dword ptr [eax]
push 0ffffffebh
push dword ptr [ebp+8]
call SetWindowLongW
xor eax, eax
jmp endFunc
notCreate:

; WM_KEYDOWN
cmp dword ptr [ebp+12], 0100h
jne notKeydown
push 0ffffffebh
push dword ptr [ebp+8]
call GetWindowLongW
mov ecx, dword ptr [ebp+16]
and ecx, 0ffh
mov byte ptr [eax+ecx], 1
jmp defFunc
notKeydown:

; WM_KEYUP
cmp dword ptr [ebp+12], 0101h
jne notKeyup
push 0ffffffebh
push dword ptr [ebp+8]
call GetWindowLongW
mov ecx, dword ptr [ebp+16]
and ecx, 0ffh
mov byte ptr [eax+ecx], 0
jmp defFunc
notKeyup:

; Default
defFunc:
push dword ptr [ebp+20]
push dword ptr [ebp+16]
push dword ptr [ebp+12]
push dword ptr [ebp+8]
call DefWindowProcW

; Exit WndProc
endFunc:
mov esp, ebp
pop ebp
ret
my_WndProc ENDP


; Handle/Draw game
my_gameFrame PROC
push ebp
mov ebp, esp

; Save registers
push edi
push esi
push ebx

; Clear back-buffer
mov edi, dword ptr [ebp+8]
mov ecx, dword ptr [ebp+12]
mov eax, dword ptr [ebp+16]
mul ecx
mov ecx, eax
shl ecx, 2
xor eax, eax
rep stosb

; Get game-state ptr in esi
mov esi, dword ptr [ebp+20]

; Move ball
mov eax, dword ptr [esi+16]
add dword ptr [esi+8], eax
mov eax, dword ptr [esi+20]
add dword ptr [esi+12], eax

; Bounce left
mov eax, dword ptr [esi+8]
cmp eax, 5
jg skipBounceLeft
mov dword ptr [esi+8], 5
neg dword ptr [esi+16]
; Score
inc dword ptr [esi+28]
and dword ptr [esi+28], 0ffh
skipBounceLeft:

; Bounce right
mov eax, dword ptr [esi+8]
mov ecx, dword ptr [ebp+12]
sub ecx, 5
cmp eax, ecx
jl skipBounceRight
mov dword ptr [esi+8], ecx
neg dword ptr [esi+16]
; Score
inc dword ptr [esi+24]
and dword ptr [esi+24], 0ffh
skipBounceRight:

; Bounce bottom
mov eax, dword ptr [esi+12]
cmp eax, 5
jg skipBounceBottom
mov dword ptr [esi+12], 5
neg dword ptr [esi+20]
skipBounceBottom:

; Bounce top
mov eax, dword ptr [esi+12]
mov ecx, dword ptr [ebp+16]
sub ecx, 5
cmp eax, ecx
jl skipBounceTop
mov dword ptr [esi+12], ecx
neg dword ptr [esi+20]
skipBounceTop:

; Bounce left paddle
mov eax, dword ptr [esi+12]
sub eax, dword ptr [esi]
cmp eax, 45
jg skipBounceLeftPaddle
cmp eax, -45
jl skipBounceLeftPaddle
mov ecx, eax

cmp dword ptr [esi+16], 0
jnl skipBounceLeftPaddleForward
mov eax, dword ptr [esi+8]
sub eax, 55
jnle skipBounceLeftPaddleForward
cmp eax, -10
jng skipBounceLeftPaddleForward
neg dword ptr [esi+16]
sar ecx, 3
mov dword ptr [esi+20], ecx
skipBounceLeftPaddleForward:

cmp dword ptr [esi+16], 0
jng skipBounceLeftPaddle
mov eax, dword ptr [esi+8]
sub eax, 35
jnge skipBounceLeftPaddle
cmp eax, 10
jnl skipBounceLeftPaddle
neg dword ptr [esi+16]

skipBounceLeftPaddle:

; Bounce right paddle
mov eax, dword ptr [esi+12]
sub eax, dword ptr [esi+4]
cmp eax, 45
jg skipBounceRightPaddle
cmp eax, -45
jl skipBounceRightPaddle
mov ecx, eax

cmp dword ptr [esi+16], 0
jng skipBounceRightPaddleForward
mov eax, dword ptr [esi+8]
sub eax, dword ptr [ebp+12]
add eax, 55
cmp eax, 0
jnge skipBounceRightPaddleForward
cmp eax, 10
jnl skipBounceRightPaddleForward
neg dword ptr [esi+16]
sar ecx, 3
mov dword ptr [esi+20], ecx
skipBounceRightPaddleForward:

cmp dword ptr [esi+16], 0
jnl skipBounceRightPaddle
mov eax, dword ptr [esi+8]
sub eax, dword ptr [ebp+12]
add eax, 35
cmp eax, 0
jnle skipBounceRightPaddle
cmp eax, -10
jng skipBounceRightPaddle
neg dword ptr [esi+16]

skipBounceRightPaddle:

; Advanced Pong AI (ASM-optimized)
mov eax, dword ptr [esi+12]
sub eax, dword ptr [esi+4]
cmp eax, 3
jng checkBelow
mov eax, 3
checkBelow:
cmp eax, -3
jnl aiAdd
mov eax, -3
aiAdd:
add dword ptr [esi+4], eax

; Clamp left paddle to within screen
mov eax, dword ptr [esi]
cmp eax, 45
jge skipFixLeftPaddleBottom
mov eax, 45
skipFixLeftPaddleBottom:
mov ecx, dword ptr [ebp+16]
sub ecx, 45
cmp eax, ecx
jle skipFixLeftPaddleTop
mov eax, ecx
skipFixLeftPaddleTop:
mov dword ptr [esi], eax

; Clamp right paddle to within screen
mov eax, dword ptr [esi+4]
cmp eax, 45
jge skipFixRightPaddleBottom
mov eax, 45
skipFixRightPaddleBottom:
mov ecx, dword ptr [ebp+16]
sub ecx, 45
cmp eax, ecx
jle skipFixRightPaddleTop
mov eax, ecx
skipFixRightPaddleTop:
mov dword ptr [esi+4], eax

; Draw left paddle
mov eax, dword ptr [esi]
sub eax, 40
mov ebx, dword ptr [ebp+12]
mul ebx
add eax, 40

mov edx, 80
mov edi, dword ptr [ebp+8]
drawLeftPaddle:
mov ecx, 10
drawLeftPaddleLine:
mov dword ptr [edi+eax*4], 0ffffffffh
inc eax
loop drawLeftPaddleLine
sub eax, 10
add eax, ebx

dec edx
jnz drawLeftPaddle

; Draw right paddle
mov eax, dword ptr [esi+4]
sub eax, 40
mov ebx, dword ptr [ebp+12]
mul ebx
add eax, ebx
sub eax, 10
sub eax, 40

mov edx, 80
mov edi, dword ptr [ebp+8]
drawRightPaddle:
mov ecx, 10
drawRightPaddleLine:
mov dword ptr [edi+eax*4], 0ffffffffh
inc eax
loop drawRightPaddleLine
sub eax, 10
add eax, ebx

dec edx
jnz drawRightPaddle

; Draw ball
mov eax, dword ptr [esi+12]
sub eax, 5
mov ebx, dword ptr [ebp+12]
mul ebx
add eax, dword ptr [esi+8]
sub eax, 5

mov edx, 10
mov edi, dword ptr [ebp+8]
drawBall:
mov ecx, 10
drawBallLine:
mov dword ptr [edi+eax*4], 0ffffffffh
inc eax
loop drawBallLine
sub eax, 10
add eax, ebx

dec edx
jnz drawBall

; Draw left score
push 20
push 16
mov eax, dword ptr [ebp+12]
shr eax, 2
push eax
push dword ptr [ebp+16]
push dword ptr [ebp+12]
push dword ptr [ebp+8]
push dword ptr [esi+24]
call my_drawBinary
add esp, 28

; Draw right score
push -20
push 16
mov eax, dword ptr [ebp+12]
mov ecx, eax
shr eax, 2
sub ecx, eax
sub ecx, 10
push ecx
push dword ptr [ebp+16]
push dword ptr [ebp+12]
push dword ptr [ebp+8]
push dword ptr [esi+28]
call my_drawBinary
add esp, 28

; Restore registers
pop ebx
pop esi
pop edi

; Exit function
mov esp, ebp
pop ebp
ret
my_gameFrame ENDP


; Draw binary number
my_drawBinary PROC
push ebp
mov ebp, esp

; Save registers
push edi
push esi
push ebx

mov ebx, dword ptr [ebp+8]
mov esi, dword ptr [ebp+24]

;and ebx, 0ffh

drawBit:
push dword ptr [ebp+28]
push esi
push dword ptr [ebp+20]
push dword ptr [ebp+16]
push dword ptr [ebp+12]
push ebx
call my_drawBinDigit
add esp, 24

shr ebx, 1
add esi, dword ptr [ebp+32]

cmp ebx, 0
jne drawBit

; Restore registers
pop ebx
pop esi
pop edi

; Exit function
mov esp, ebp
pop ebp
ret
my_drawBinary ENDP


; Draw binary digit
my_drawBinDigit PROC
push ebp
mov ebp, esp

; Save registers
push edi
push esi
push ebx

mov edi, dword ptr [ebp+12]

; Check which digit at LSB
mov eax, dword ptr [ebp+8]
and eax, 01h
jnz drawDigit1

; Digit 0
mov ebx, dword ptr [ebp+16]
mov eax, 18
mul ebx
mov ecx, eax

mov eax, dword ptr [ebp+28]
mul ebx
add eax, dword ptr [ebp+24]

mov edx, ecx

mov ecx, 8
hlines0:
add eax, ecx
mov dword ptr [edi+eax*4+4], 0ffffffffh
add eax, ebx
mov dword ptr [edi+eax*4+4], 0ffffffffh
sub eax, ebx
sub eax, ecx

add eax, edx

add eax, ecx
mov dword ptr [edi+eax*4+4], 0ffffffffh
add eax, ebx
mov dword ptr [edi+eax*4+4], 0ffffffffh
sub eax, ebx
sub eax, ecx

sub eax, edx

loop hlines0

add eax, ebx
add eax, ebx

mov ecx, 16
vlines0:
mov dword ptr [edi+eax*4], 0ffffffffh
mov dword ptr [edi+eax*4+4], 0ffffffffh
mov dword ptr [edi+eax*4+40], 0ffffffffh
mov dword ptr [edi+eax*4+4+40], 0ffffffffh
add eax, ebx
loop vlines0
jmp digitDone

; Digit 1
drawDigit1:
mov ebx, dword ptr [ebp+16]
mov eax, dword ptr [ebp+28]
mul ebx
add eax, dword ptr [ebp+24]
add eax, 5

mov ecx, 20
vline1:
mov dword ptr [edi+eax*4], 0ffffffffh
mov dword ptr [edi+eax*4+4], 0ffffffffh
add eax, ebx
loop vline1
sub eax, ebx
mov dword ptr [edi+eax*4-4], 0ffffffffh
mov dword ptr [edi+eax*4-8], 0ffffffffh
sub eax, ebx
mov dword ptr [edi+eax*4-4], 0ffffffffh
mov dword ptr [edi+eax*4-8], 0ffffffffh
jmp digitDone

digitDone:

; Restore registers
pop ebx
pop esi
pop edi

; Exit function
mov esp, ebp
pop ebp
ret
my_drawBinDigit ENDP


END start

Share this post


Link to post
Share on other sites
Sign in to follow this