flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
revolution 25 Jan 2025, 12:25
Mat Quasar wrote: Out of curiousity, I use disassembler to see ... So for fasm you can also examine the macros to discover the internal details of everything they can do and how they work. |
|||
![]() |
|
Mat Quasar 25 Jan 2025, 12:55
Thanks @revolution. So far I have examined "invoke", "cinvoke", "fastcall", "stdcall", "locals" and "proc...endp".
Even the "library" and "import" keyword in PE ".idata" section are also macro, I think. Once I know how it is translated to raw Assembly, I am more happier to use the macros. |
|||
![]() |
|
AsmGuru62 25 Jan 2025, 13:53
These macro also have an awesome feature.
If you have the proc/endp declared in the source, but the name of the 'proc' is not mentioned anywhere else, then the EXE file FASM produces will not have the code between proc/endp included! It is like HLL Linker option: "Remove unreferenced code". Very cool! Say, you have a file with 50 functions and you include it and call only a couple of functions. Only their code will be inside the EXE file. In x64 code proc/endp also balance the stack on 16 byte frame automatically, even if you declare locals. |
|||
![]() |
|
Mat Quasar 25 Jan 2025, 14:43
Good to know, @AsmGuru62.
|
|||
![]() |
|
Mat Qua sar 18 Jun 2025, 16:00
I created an example that replace PROC/ENDP with code like I shown in post #1:
It is probably my preliminary Win32 dialog/form for my simple database program (that I planned to do): Code: format PE GUI 4.0 include 'win32a.inc' IDD_MAIN = 100 IDC_BOX = 101 IDC_ADD = 102 IDC_UPDATE = 103 IDC_REMOVE = 104 section '.code' code readable executable entry $ invoke GetModuleHandle,0 invoke DialogBoxParam,eax,IDD_MAIN,HWND_DESKTOP,DialogProc,0 invoke ExitProcess,0 DialogProc: push ebp mov ebp, esp push ebx push esi push edi cmp dword [ebp+12],WM_INITDIALOG je .wminitdialog cmp dword [ebp+12],WM_COMMAND je .wmcommand cmp dword [ebp+12],WM_CLOSE je .wmclose xor eax,eax jmp .finish .wminitdialog: jmp .processed .wmcommand: cmp dword [ebp+16],BN_CLICKED shl 16 + IDC_ADD jne .processed invoke MessageBoxA, HWND_DESKTOP, _caption, _title, 0x40 jmp .processed .wmclose: invoke EndDialog,[ebp+8],0 .processed: mov eax,1 .finish: pop edi pop esi pop ebx leave retn 16 _caption db 'Yay! ADD Button clicked',0 _title db 'dbform',0 section '.idata' import readable library kernel32,'kernel32.DLL', user32,'user32.DLL' include 'api\kernel32.inc' include 'api\user32.inc' section '.rsrc' resource data readable directory RT_DIALOG, dialogs resource dialogs, IDD_MAIN, LANG_ENGLISH + SUBLANG_DEFAULT, mainform dialog mainform,'dbform',0,0,300,200, DS_CENTER + WS_CAPTION + WS_SYSMENU dialogitem 'Button','Main',-1,10,10,280,180,WS_VISIBLE + BS_GROUPBOX dialogitem 'Button','Add',IDC_ADD,150,30,70,15,WS_VISIBLE + BS_DEFPUSHBUTTON dialogitem 'Button','Update',IDC_UPDATE,150,50,70,15,WS_VISIBLE dialogitem 'Button','Remove',IDC_REMOVE,150,70,70,15,WS_VISIBLE enddialog
|
||||||||||
![]() |
|
Core i7 19 Jun 2025, 04:29
Mat Qua sar wrote: I created an example that replace PROC/ENDP with code like I shown in post #1: I understand that this is an experiment, but you must agree that it is not convenient to control arguments this way (especially when there are many of them). For example, you need to remember that [ebp+24] is the fifth argument from the beginning, etc. It is much more convenient to access arguments by their aliases in the form of text strings, which is implemented in proc/endp macros. This also applies to the prologue/epilogue of a procedure. |
|||
![]() |
|
Mat Qua sar 19 Jun 2025, 08:16
Core i7 wrote: ... Agreed. It was just fun to use primitive way to make it work like PROC/ENDP macro. ![]() |
|||
![]() |
|
Core i7 19 Jun 2025, 08:29
yes, this is exactly how any debugger displays the entry into a procedure
|
||||||||||
![]() |
|
AsmGuru62 19 Jun 2025, 16:24
I once tried to 'relieve' EBP of its duties in PROC/ENDP principle.
So both the parameters and locals would be accessed by ESP. It was a nightmare stuff! Every function had a matching structure for locals, and parameters, and preserving registers. Like this one: Code: struct LocVarsProc1 ; ; the area to preserve used registers ; used_ebp dd ? used_esi dd ? used_edi dd ? ; ; the area for locals (short fields first to save encoding length) ; handle dd ? path rb 256 ; ; Return Address Location ; RetAddr dd ? ; ; Parameters (named properly for each function) ; Param1 dd ? Param2 dd ? Param3 dd ? Param4 dd ? ends Function itself: Code: align 16 MyInsaneProcedure: sub esp, LocVarsProc1.RetAddr ; ; preserve registers ; mov [esp + LocVarsProc1.used_ebp], ebp mov [esp + LocVarsProc1.used_esi], esi mov [esp + LocVarsProc1.used_edi], edi ; ; use EBP, ESI, EDI as you wish ; lea esi, [esp + LocVarsProc1.path] mov ebp, [esp + LocVarsProc1.Param4] ; ; etc. ; ; if you use PUSH here, do not access locals until POP is done. ; ; restore registers ; mov edi, [esp + LocVarsProc1.used_edi] mov esi, [esp + LocVarsProc1.used_esi] mov ebp, [esp + LocVarsProc1.used_ebp] ; ; cleanup and return ; add esp, LocVarsProc1.RetAddr ret 4*4 And the call: Code: push 4 3 2 1 call MyInsaneProcedure Neat! Of course, using PROC/ENDP is a small price to pay to just leave EBP alone. The bloat of code is obvious. To save registers using PUSH/POP takes one byte only vs the few bytes for each MOV into/from structure. I dropped that horrible idea soon enough. |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.