flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Tyler 05 Jul 2010, 06:06
> is there a way I can gain local re-usable labels
Use a global label(w/o a '.') and every local label(w/ a '.') after it can be reused until you declare the next global label. Example Code: glob: .loc: ; glob.loc jmp .loc ; jmp glob.loc glob2: .loc: jmp .loc ; jmp glob2.loc jmp glob.loc ; jumps to .loc if glob As for controlling the stack frame, just use labels instead of procs and create it yourself. I don't want to read all that, anymore ?s, just ask clearly ![]() |
|||
![]() |
|
revolution 05 Jul 2010, 07:42
You should be returning from WinMain with ret 0x14 to properly release the stack frame. But Windows will likely be lenient to the error anyway when you use retn instead, but it is bad practice really.
The fasm macros define ret to produce the proper retn XX code (as you saw). So if, for some reason, you don't want the frame return code (ret XX) then use retn instead. |
|||
![]() |
|
LocoDelAssembly 05 Jul 2010, 15:56
But is this a PE or a MS COFF source? If it is a PE then those parameters are pretty much invalid, the entry point has nothing. If it is a MS COFF you'll need to link to some library that calls your WinMain because if it is the executable entry point then you're in the same trouble again.
[edit]For "proc" documentation and related stuff check here: http://flatassembler.net/docs.php?article=win32 [/edit] |
|||
![]() |
|
bobsobol 05 Jul 2010, 22:40
It is a PE... but it is not the entry point.
It's attempting to create a source listing (in assembler) for a program written in Visual C++ 6. The code produced by VC6 doesn't produce a stack frame for the WinMain() routine, but does pass the normal parameters to it, as my example code follows. Much of the VC6 entry point is pretty useless, checking to see what CPU the PE is designed for in x86 32-bit code etc... when clearly the PE wouldn't have been executed if it wasn't running on an x86 32-bit compatible CPU. It also sets up a Structured Exception Handler, which I have coded an equivalent for, creates some heap storage etc. But crucially, WinMain() doesn't create a separate stack frame, so LEAVEing and releasing it on return is not an issue. The WinMain() compiled by VC6, returns with a simple RET (or RETN, as in a flat file all returns are near XD) Special thanks to Tyler, that helps a lot... but can I define names of the parameters passed on the stack with a label alone? (hCurrInstance, hPrevInstance, lpCmdLine, nCmdShow, ShowState) Or does that simply become too difficult for the Assembler (compiler) to keep track of when they are part of the active stack, and not part of the original frame passed to the procedure? |
|||
![]() |
|
LocoDelAssembly 05 Jul 2010, 23:48
You could dump proc and do this instead:
Code: WinMain: virtual at esp+4 .hCurrInstance dd ? .hPrevInstance dd ? .lpCmdLine dd ? .nCmdShow dd ? .ShowState dd ? end virtual ; The following instruction is just an example: mov eax, [.hCurrInstance] ret For returning with a simple "ret" you should do this: Code: proc WinMain c, hCurrInstance,hPrevInstance,lpCmdLine,nCmdShow,ShowState ; Notice the "c" after WinMain ret endp *Provided the programmer does not violates that assumption of course but with ESP it is impossible to hold if there are PUSH sequences. |
|||
![]() |
|
Tomasz Grysztar 06 Jul 2010, 09:12
LocoDelAssembly wrote: But that won't prevent the PUSH EBP/MOV EBP, ESP prolog nor the LEAVE epilog because "proc" macro always uses EBP to take advantage of its invariability* in the execution of the body. It is better to say, that it is the default prologue/epilogue set of macros that always uses EBP. You can still use some other setting and make "proc" macro work with completely different strategy. See this thread for details: http://board.flatassembler.net/topic.php?t=10518 |
|||
![]() |
|
bobsobol 07 Jul 2010, 03:20
Both excellent answers. Thank you LocoDelAssembly & Tomasz.
FASMs Macro capabilities are considerably more complex than I am used to in a Macro Assembler, and I guess that's part of why it's often referred to as a compiler. Yet it does still give me the native x86 feel, which I loose if I go as far as HLA. It will take me some time (I think) to understand the complete ins-and-outs of the default Proc Macro, and define one that suites my purposes. But it's clear to me that that is possible. For now, I think I'll go with the label, and .label methods, and see how often I can make use of the "virtual - end virtual" syntax to improve readability. Or, maybe store ESP+4 on entry, (somewhere) and then keep constants (EQUates) for the offset against that? That should work and empower the reader. No? Code: WinMain: .Arg dd ? .hCurrInstance EQU 0 .hPrevInstance EQU 4 .lpCmdLine EQU 8 .nCmdShow EQU 12 .ShowState EQU 16 mov .Arg,ESP+4 mov EAX, .Arg add EAX, .lpCmdLine push EAX ; Arg.lpCmdLine push lpMyString call [lstrcmp] jnz .Invalid jmp .Continue .Invalid ret .Continue ... ... It is enough, to know that something can be done to make these Macros (or ones like them) fit the conventions used the High Level build method. (Don't ask why that's important... Long story.) |
|||
![]() |
|
bitshifter 09 Jul 2010, 04:28
That code has lots of problems i dont care to mention...
But if you want to do it the hard way, then here you go... Code: format PE GUI 4.0 entry start include 'win32a.inc' section '.code' code readable executable start: push SW_SHOWNORMAL ; WinMain: nShow call [GetCommandLine] push eax ; WinMain: lpszArgs push NULL ; WinMain: hPrev (always NULL on Win32) push NULL ; GetModuleHandle: hModule call [GetModuleHandle] push eax ; WinMain: hInst call WinMain push eax ; ExitProcess: nExitCode call [ExitProcess] ; INT WINAPI WinMain ( HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArgs, INT nShow ) WinMain: label .hInst dword at esp+4 label .hPrev dword at esp+8 label .lpszArgs dword at esp+12 label .nShow dword at esp+16 push MB_OK ; MessageBox: dwStyle (bumped esp 4) push _caption ; MessageBox: lpszCaption (bumped esp 8) push [.lpszArgs+8] ; MessageBox: lpszMessage push HWND_DESKTOP ; MessageBox: hwndOwner call [MessageBox] xor eax,eax ; WinMain: Return value retn 16 section '.data' data readable writeable _caption db 'Command line args...',0 section '.idata' import data readable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL' include 'api\kernel32.inc' include 'api\user32.inc' _________________ Coding a 3D game engine with fasm is like trying to eat an elephant, you just have to keep focused and take it one 'byte' at a time. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.