Why does this pice of code crash?
When I try to call anything (a procedure for instance :tounge: ) it crashes (it may bee Main, ExitProcess or any other same crash), I have to have those dword in front of the calls else FASM makes a fuss (don'y know why :( ).



; Win32 console program
format PE console
entry start
use32

include '\fasm\include\kernel.inc'

section '.code' code readable executable
start:
call dword [Main]

push dword 0
call [ExitProcess]
; ########################################

Main:
push ebp
mov ebp, esp
sub esp, 2+4

push STD_OUTPUT_HANDLE
call [GetStdHandle]
mov [hStdOut], eax

push STD_INPUT_HANDLE
call [GetStdHandle]
mov [hStdIn], eax

mov edx, 32
xor ebx,ebx
push edx
push ebx
push ebx ; 0,0
call dword [ClearScreenEx]

mov esp, ebp
pop ebp
retn
;Main endp
;-----------------------------------------------------------
ClearScreenEx:
push ebp
mov ebp, esp
sub esp, 12

; some for now irrelevant code is here, thus cut out...

mov esp, ebp
pop ebp
retn
;ClearScreenEx endp
;-----------------------------------------------------------------------
StdOut: ;proc lpszText:DWORD
push ebp
mov ebp, esp
sub esp, 12

; some for now irrelevant code is here, thus cut out...

mov esp, ebp
pop ebp
ret
;StdOut endp


crlf equ 13,10
section '.data' data readable writeable
; .data section
szMMXTT db "<TEXT>",crlf,0
s_szMMXTT = ($+1)-szMMXTT
szPureAsm db "-=[<TEXT>]=-",crlf,0

Msg1 db "<TEXT> ",0
Msg2 db "<EVEN MORE TEXT>",0

szMMXs db "<TEXT>",0
szMMXns db "<TEXT>,0

section '.bss' readable writeable
; .data? section
hStdOut rd 1
hStdIn rd 1

sTick rd 1
STick rd 1

databuf rb 256 ; 256 byte
InputBuffer rb 128 ; 128 byte

dummyDD rd 1

macro library [label,string]
{ forward
local _label
dd 0,0,0,RVA _label,RVA label
common
dd 0,0,0,0,0
forward
_label db string,0 }

macro import [label,string]
{ forward
local _label
label dd RVA _label
common
dd 0
forward
_label dw 0
db string,0 }


section '.idata' import data readable writeable
; import section
library kernel, 'KERNEL32.DLL' ;,\

kernel:
import ExitProcess, 'ExitProcess',\
FillConsoleOutputCharacter, 'FillConsoleOutputCharacterA',\
GetConsoleScreenBufferInfo, 'GetConsoleScreenBufferInfo',\
GetModuleHandle, 'GetModuleHandleA',\
GetStdHandle, 'GetStdHandle',\
SetConsoleCursorPosition, 'SetConsoleCursorPosition',\
Sleep, 'Sleep',\
WriteFile, 'WriteFile'

section '.reloc' fixups data readable discardable
Posted on 2002-09-21 13:32:15 by scientica
Change
   call  dword [Main]

to call Main
and
call  dword [ClearScreenEx]

to call ClearScreenEx


Finally,

Use the provided stdcall and invoke macros. Their is a difference.

p.s. Download OllyDbg
Posted on 2002-09-22 04:02:18 by eet_1024
Ok, I've downloaded OllyDbg.

"Wow! I never knew you could use a debugger", well the truth is, the last time I tried to use an debugger was in the long-time-ago-C++-programming-time and that did scare me off (the debugger only showed an very uggly pice of disassembly of my exe, never HLL again, never ever... :) ).
Any way, I've located the source of the error:



[COLOR=darkblue]
format PE GUI
entry start
use32

include '\fasm\include\kernel.inc'
include '\fasm\include\macro\stdcall.inc'

section '.code' code readable executable[/COLOR]
start:
invoke GetModuleHandle, NULL
mov [hInstance], eax

invoke GetCommandLine
mov [lpszCommandline],eax

invoke AllocConsole [COLOR=green]; get the app a console window[/COLOR]

invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [hStdOut], eax
invoke GetStdHandle,STD_INPUT_HANDLE
mov [hStdIn], eax
invoke GetStdHandle,STD_ERROR_HANDLE
mov [hStdErr], eax

invoke SetConsoleTitle, szPTA

call Main

invoke FreeConsole [COLOR=green]; Destroy the console[/COLOR]
invoke ExitProcess,0
[COLOR=green]; ###################################[/COLOR]
Main:
push ebp
mov ebp, esp
sub esp, 2+4

mov edx, 32
xor ebx,ebx
push edx
push ebx
push ebx [COLOR=green]; 0,0[/COLOR]
call ClearScreenEx

mov esp, ebp
pop ebp
retn

[COLOR=green];---------------------------------------------------------------------------------------------[/COLOR]
ClearScreenEx:
push ebp
mov ebp, esp
sub esp, 12

char equ DWORD [ebp+16]
endPos equ DWORD [ebp+12]
startPos equ DWORD [ebp+8]
sbi_dwSize equ DWORD [ebp-30] [COLOR=green];sbi.dwSize COORD (dd)[/COLOR]
sbi_dwSize_X equ WORD [ebp-30]
sbi_dwSize_Y equ WORD [ebp-28]
sbi_dwCursorPosition equ DWORD [ebp-26] [COLOR=green];sbi.dwCursorPosition COORD (dd)[/COLOR]
sbi_dwCursorPosition_X equ WORD [ebp-26]
sbi_dwCursorPosition_Y equ WORD [ebp-24]
sbi_wAttributes equ DWORD [ebp-22] [COLOR=green];sbi.wAttributes WORD (dw)[/COLOR]
sbi_srWindow equ DWORD [ebp-20] [COLOR=green];sbi.srWindow SMALL_RECT (4*dw)[/COLOR]
sbi_srWindow_Left equ WORD [ebp-20]
sbi_srWindow_Top equ WORD [ebp-18]
sbi_srWindow_Right equ WORD [ebp-16]
sbi_srWindow_Bottom equ WORD [ebp-14]
sbi_dwMaximumWindowSize equ DWORD [ebp-12] [COLOR=green];sbi.dwMaximumWindowSize COORD (dd)[/COLOR]
CharsOnScreen equ DWORD [ebp-8]
noc equ DWORD [ebp-4]

lea esi, [ebp-30]
mov edi, [hStdOut]
invoke GetConsoleScreenBufferInfo, edi, esi [COLOR=red]; this is the Crash point, the return value is ERROR_NOACCESS[/COLOR]
... [COLOR=green]; I haven't forgotten the ret (nor forgotten balance the plate pile)...[/COLOR]


Why? Doesn't my hStdOut have GENERIC_READ access? (Or have I made something wrong with the the locals?)
Posted on 2002-09-22 09:25:37 by scientica
A few more suggestions.

Since you're created a Win32 Console app, you don't have to call AllocConsole

The StdCall.inc file also has proc, enter, and return macros:


proc MyFunc, Param1, Param2
.Local1 rd 1
.Local2 rd 1
enter
mov [.Local1], 0x6789ABCD
mov eax, [Param1]
invoke SomeAPI, [hStdOut], [Param1], [.Local1]
return

The Import.inc has the library, and import macros.

By using the macros, you don't have to do the ebp calculations yourself, thereby preventing errors.
Posted on 2002-09-22 17:33:42 by eet_1024
More tips/suggestions...

1. format PE GUI should be format PE CONSOLE - not the same with the first post.
2. Register preservation ebx, esi, edi ???
3. with sub esp, 12 you're allocating 12 bytes on the stack but you are reading past the allocated memory with lea esi, and writing past the allocated memory with the GetConsoleScreenBufferInfo API.
typedef struct _CONSOLE_SCREEN_BUFFER_INFO { 

COORD dwSize;
COORD dwCursorPosition;
WORD wAttributes;
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO ;
COORD is DWORD size(2 words), SMALL_RECT is QUADWORD size(4 words)

COORD + COORD + WORD +SMALL_RECT + COORD == x
4 + 4 + 2 + 8 + 4 = 22

???

try changing to sub esp, 22 and lea reg32,

4. It would be nice to .zip the whole project and attached it, so we can see it ourselves but if it's big or confidential/private, don't bother. :)
Posted on 2002-09-22 20:32:03 by stryker
Ok, now it doesn't crash. I'm far from an expert on the stack, thats why I'd like to avoid macros (since I don't know what I do then).
I did some changes and forgot to check if I allocated enough on the stack, thanks for pointing it out.
I tried to change "format PE console" to "format PR GUI", and allocate the console and console window; I tried too much when I couldn't find out why I got "ERROR_NOACCESS" from GetConsoleScreenBufferInfo, after some more debuging with Olly, I somehow got a out of memory error; that must have been due to I only allocated 12 byte on the stack.

Register preservation, well, I usually do this (I preserve all registers I use, exept from eax). But I just didn't push 'n' pop 'em, don't know why. :o

Well, if I would post a zip file with the project. First I'd have top clear up the code (It's full of comments, and commented out code, and who knows what more). For the second, I don't know if I'll complete this project (or push it on to the stack of unfinished prjects). :)

eet_1024, as I said previously, I'd like to avoid macros when I code in fasm. Since I want to learn what I'm doing and why, macros is something I might utilize when I have learnt what they do for me and why.
Well there are exceptions, the import and library macros are for now a must. But some day I'll learn why I use them (in the deph, I know without them the PE will not be able to call teh APIs) and what they do (exactly), but now I'm focusing on learing to write windows apps in fasm.

Now the final question for the stack-gurus:
Is this right, or have I reversed teh order of the structure mebers (It's supposed to be an CONSOLE_SCREEN_BUFFER_INFO struct on the stack)?


sub esp, 22
sbi_dwSize equ DWORD [ebp-22] ;COORD
sbi_dwSize_X equ WORD [ebp-22]
sbi_dwSize_Y equ WORD [ebp-20]
sbi_dwCursorPosition equ DWORD [ebp-18] ;COORD
sbi_dwCursorPosition_X equ WORD [ebp-18]
sbi_dwCursorPosition_Y equ WORD [ebp-16]
sbi_wAttributes equ DWORD [ebp-14] ;WORD
sbi_srWindow equ DWORD [ebp-12] ;SMALL_RECT
sbi_srWindow_Left equ WORD [ebp-12]
sbi_srWindow_Top equ WORD [ebp-10]
sbi_srWindow_Right equ WORD [ebp-8]
sbi_srWindow_Bottom equ WORD [ebp-6]
sbi_dwMaximumWindowSize equ DWORD [ebp-4] ;COORD
Posted on 2002-09-23 11:17:12 by scientica
I am not a stack guru but I do know the answer. Yes, that is the correct order.
Posted on 2002-09-23 11:50:47 by stryker
No, you're right it should be qword, since the sbi_srWindow is a RECT.
Yoppie! :) (my selfconfidece rises when I do something hard right, this is one such thing)
Posted on 2002-09-23 12:07:18 by scientica
btw, I deleted some of the original text above because I thought it doesn't make any sense and would probably render it useless(using QUADWORD) when were using 32bit registers unless with MMX/SSE... Anyway here's my solution instead of using QUADWORD.
sbi_srWindow_1 equ DWORD [ebp-12]  ;1st DWORD(1st and 2nd fields)

sbi_srWindow_2 equ DWORD [ebp-8] ;2nd DWORD(3rd and 4th fields)
as long as you got the correct sequence of all the structure fields, this doesn't matter. :)
Posted on 2002-09-23 12:10:14 by stryker
Scientica,

You already know what the macros do.

The enter macro allows you to replace with a label. It uses the enter instruction which does the same as
	push	ebp

mov ebp, esp
sub esp, 12

The only downside of the enter macro is that It's for Function Level 0 only.


The return macro uses leave and ret n, effectively undoing the enter instruction.
Posted on 2002-09-24 02:08:46 by eet_1024
Function Level 0? :confused:

BTW, aren't enter and leave s-l-o-w instructins (enter: 10 tick (push ebp/mov ebp,esp/sub esp,x: 3 tick), 3 tick (mov esp,ebp/pop ebp: 2 tick)). I think I prefer the long way, at least for the enter. :rolleyes:
Posted on 2002-09-25 09:49:15 by scientica
Yeah, there much slower. But if you can change the macros to your liking.

Level 1 Functions cat access the parameters of the calling function. I haven't looked into it yet.

As for speed, the app I'm working on calls an external compiler multiple times. So the few hundred clock cycles I've burned up are insignificant; that and I'm too lazy to change the macros.
Posted on 2002-09-26 01:02:46 by eet_1024