Author Topic: Boring console game  (Read 1135 times)

Alek

  • Regular Member
  • *
  • Posts: 20
Boring console game
« on: December 10, 2018, 10:08:32 AM »
Attached is a simple and very boring number guessing game. Pretty sure it gets picked up by AV, so if you feel safer the code is posted below. I wrote briefly about my thought process behind it; mainly I write stuff like this to refresh myself and put a bit more thought into research. http://krimsky.net/articles/ibasm.php. Feel free to criticize on any of my MASM articles, I'm only about a week into MASM so go easy ;)

Also big thanks to hutch and vortex.

Code: [Select]
includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib

.386
.MODEL flat,stdcall
.STACK 4096
STD_INPUT_HANDLE EQU -10 ;https://docs.microsoft.com/en-us/windows/console/getstdhandle
STD_OUTPUT_HANDLE EQU -11
GetStdHandle PROTO nStdHandle:DWORD
WriteConsoleA PROTO hConsoleOutput:DWORD, ;https://docs.microsoft.com/en-us/windows/console/writeconsole
lpBuffer:PTR BYTE,
nNumberOfCharsToWrite:DWORD,
lpNumberOfCharsWritten:PTR DWORD,
lpReserved:DWORD
ReadConsoleA PROTO hConsoleInput:DWORD, ;https://docs.microsoft.com/en-us/windows/console/readconsole
   lpBuffer2:PTR BYTE,
   nNumberOfCharsToRead:DWORD,
   lpNumberOfCharsRead:PTR DWORD,
   pInputControl:PTR BYTE

ExitProcess PROTO dwExitCode:DWORD

extern rand:NEAR
extern time:NEAR
extern srand:NEAR
extern _getch:NEAR

.data
game_randomNumber dd ?
charsWritten dd ?
msg_enternumber db "Guess a number between 0 and 9: ",0;33
msg_win db "Congratulations, your number matches the random!",13,10 ;50
msg_lose db "Sorry, your number doesn't match the random!",13,10 ;46
;lpBufferStorage db BUFFER_SIZE dup(?)
consoleHandleOutput dd ?
consoleHandleInput dd ?

.code
main PROC C
LOCAL buffer[128]:BYTE              

push STD_OUTPUT_HANDLE
call GetStdHandle
mov consoleHandleOutput, eax

push STD_INPUT_HANDLE
call GetStdHandle
mov consoleHandleInput, eax

main_game:
push 0
call time
push eax
call srand                       ;srand(time(NULL))
call rand
xor edx, edx                     ;clear edx
mov ebx, 10
div ebx                          ;remainder is stored in edx, result in eax
mov game_randomNumber, edx       ;rand() % 10

retry_label:
INVOKE WriteConsoleA, consoleHandleOutput, offset msg_enterNumber, 33, offset charsWritten, 0
INVOKE ReadConsoleA, consoleHandleInput, ADDR buffer, 128, offset charsWritten, 0

cmp charsWritten, 3 ;1 character + /r/n
jne retry_label

lea edx, buffer ;load the address of the buffer into edx
xor eax, eax ;clear eax
    mov al, [edx] ;dereference value at edx, move it into the lower 8 bit section of eax
;this ensures we only move over one byte
sub eax, 48
cmp eax, 0
jb retry_label
cmp eax, 9
ja retry_label

cmp eax, game_randomNumber
je win_label

INVOKE WriteConsoleA, consoleHandleOutput, offset msg_lose, 46, offset charsWritten, 0
jmp main_game

win_label:
INVOKE WriteConsoleA, consoleHandleOutput, offset msg_win, 50, offset charsWritten, 0
call _getch
INVOKE ExitProcess, 0

main ENDP
END

felipe

  • Member
  • *****
  • Posts: 1249
  • Eagles are just great!
Re: Boring console game
« Reply #1 on: December 10, 2018, 12:07:45 PM »
i will try it. I don't know if defining the stack size is a good idea...:idea:
Felipe.

felipe

  • Member
  • *****
  • Posts: 1249
  • Eagles are just great!
Re: Boring console game
« Reply #2 on: December 10, 2018, 12:12:30 PM »
I don't want to be rude, but it seems like you used a c++ compiler... :idea:
Felipe.

felipe

  • Member
  • *****
  • Posts: 1249
  • Eagles are just great!
Re: Boring console game
« Reply #3 on: December 10, 2018, 12:33:57 PM »
Well, now looking the code you posted above, seems pretty obvious: the entry point for the program is not there and you use c (cdecl) calling convention for that 'procedure'...:shock: Is the game good?  :icon_mrgreen:
Felipe.

Alek

  • Regular Member
  • *
  • Posts: 20
Re: Boring console game
« Reply #4 on: December 10, 2018, 01:48:07 PM »
I don't want to be rude, but it seems like you used a c++ compiler... :idea:

VS 2017 :s

Can you explain a bit on the problem with the entry?

AW

  • Member
  • *****
  • Posts: 2322
  • Let's Make ASM Great Again!
Re: Boring console game
« Reply #5 on: December 10, 2018, 09:09:12 PM »
At first, looking at the size, I thought you had made it with Masm Basic.  :badgrin:
You can reduce dramatically the size by:
1) Usingt the masm32 supplied msvcrt.lib instead of the 4 bloatware libraries.
2) Set entry point to main in Linker\Advanced to circumvent mainCRTStartup.
3) Disable SAFESEH

In the end with manifest the release version .exe will be around 4KB.

TimoVJL

  • Member
  • ***
  • Posts: 438
Re: Boring console game
« Reply #6 on: December 10, 2018, 10:08:21 PM »
Using mainCRTStartup as proc name in console programs helps too.
Code: [Select]
.code
mainCRTStartup PROC C
...
mainCRTStartup ENDP
END
And linker option -nocoffgrpinfo drops a some other useless crap too.
We should have a msvcrtos.lib or something similar to express the OS version of msvcrt.dll
May the source be with you

Alek

  • Regular Member
  • *
  • Posts: 20
Re: Boring console game
« Reply #7 on: December 11, 2018, 05:07:25 AM »
At first, looking at the size, I thought you had made it with Masm Basic.  :badgrin:
You can reduce dramatically the size by:
1) Usingt the masm32 supplied msvcrt.lib instead of the 4 bloatware libraries.
2) Set entry point to main in Linker\Advanced to circumvent mainCRTStartup.
3) Disable SAFESEH

In the end with manifest the release version .exe will be around 4KB.

Hey ill take a look at the masm32 msvcrt.lib. SAFESEH already disabled, was the first thing ;) Also Ill set the entry, thanks both TimoVJL and AW

AW

  • Member
  • *****
  • Posts: 2322
  • Let's Make ASM Great Again!
Re: Boring console game
« Reply #8 on: December 11, 2018, 06:36:14 PM »
But only libucrt.lib and the entry point make a significant difference for the size. If you use ucrt.lib instead, the size will not be much different.
However, the user is expected to have the corresponding prerequisites and redistributables. When you use the masm32 supplied msvcrt.lib you don't have that problem because msvcrt.dll is there from Windows NT onwards and works the same for the common CRT function we frequently use. Of course, you know all this, I am just posting to increase my message count.  :biggrin: