News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

In search of macros

Started by donkey, April 22, 2008, 07:01:14 AM

Previous topic - Next topic

donkey

The header project is plodding along at a reasonable rate so I decided to ask for submissions for objective 4 of the project "To create a standard set of GoAsm macros for use in projects". The two macros I have included are pretty much the only ones I use, they are CoInvoke and CInvoke, for COM and C calling convention functions respectively. Any macros will be considered but they should be generally useful and simple to use, also suggestions for which should be included and what criteria should be applied in order to make the choice.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Here is my favourite one - before resorting to Olly, I'll just use a
deb "You are in proc xxx now"
Once you click Cancel, no more messages.

deb MACRO arg ; deb "You are in proc xxx now"
  pushad
  .if ShowMSG==IDOK ; initialise in .data as ShowMSG dd IDOK
mov ShowMSG, IDCANCEL ; avoid multiple boxes
invoke MessageBox, 0, chr$(<arg>), addr DebugMsg, MB_OKCANCEL
mov ShowMSG, eax
  .endif
  popad
ENDM


Another useful snippet:

MyProc proc stuff:DWORD
LOCAL MyTmp:DWORD
LOCAL ofn:OPENFILENAME
LOCAL rc:RECT
call ClearLocals   ; no arguments needed

A simple way to initialise all local variables. All registers are preserved, except eax which will be zeroed (warning: don't use with xx proc uses esi arg:DWORD).

ClearLocals proc ; first instruction after LOCALS - eax will be zero on exit
pop EspGlob ; save the return address to a global variable - now
; the stack is identical to the calling procedure
xchg eax, ecx ; save ecx
mov ecx, ebp ; base page of calling procedure
sub ecx, esp ; ebp - esp = No. of bytes in locals
mov esp, ebp ; discard existing locals
shr ecx, 2 ; divide by four
@@: push 0 ; dwords on stack
loop @B
xchg eax, ecx ; restore ecx, 0 to eax
push EspGlob ; restore the return address
ret
ClearLocals endp

donkey

Hi jj2007,

I guess I should have been more specific, I am building a header project for GoAsm and a set of standard GoAsm macros, I am not sure that the ones you posted will translate well but I will take a look.

I have decided to add the pushq macro that allows for QWORD pushes, something I find useful from time to time...

pushq(%1) MACRO
    PUSH [%1+4]
    PUSH [%1]
ENDM


Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

#3
I do like the clear locals idea but I would rather it be a macro than a procedure. I was thinking about something like this...

ClearLocals MACRO
// Preserve EDI
mov edx,edi

// Get the size of the stack
mov ecx,ebp
sub ecx,esp

// Base of local variables
lea edi,[ebp]
sub edi,ecx
shr ecx,2

// Fill with zeros
mov eax,0
rep stosd

// Restore EDI
mov edi,edx
ENDM


Haven't fully tested it but it should work

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Synfire

If you check out the WIN32A.INC you'll find a small collection of macros I threw together for various users. You are more than welcome to include those. Sorry, they're kinda old, so they use the older style of multi-line macros.

#DEFINE SUPPORTS_IDENT 01
#DEFINE SUPPORTS_FPU 02
#DEFINE SUPPORTS_TSC 03
#DEFINE SUPPORTS_CX8 04
#DEFINE SUPPORTS_CMOV 05
#DEFINE SUPPORTS_CLFSH 06
#DEFINE SUPPORTS_MMX 07
#DEFINE SUPPORTS_FXSR 08
#DEFINE SUPPORTS_SSE 09
#DEFINE SUPPORTS_SSE2 10
#DEFINE SUPPORTS_SSE3 11
#DEFINE SUPPORTS_HTT 12

; Undocumented Opcodes
#DEFINE bht DB 2Eh ; Branch Hint: Taken
#DEFINE bhnt DB 3Eh ; Branch Hint: Not Taken
#DEFINE salc DB 0D6h ; Set AL based on Carry Flag

; Custom Opcodes
cpu_(%f)= \
push ebx \
#IF %f == 01 \
pushfd \
pop edx \
pushfd \
pop eax \
xor eax, 200000h \
push eax \
popfd \
pushfd \
pop eax \
xor eax, edx \
#ELSEIF %f == 02 \
mov eax, 1 \
cpuid \
mov eax, edx \
#ELSEIF %f == 03 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-4 \
shr eax, 31-4+4 \
#ELSEIF %f == 04 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-8 \
shr eax, 31-8+8 \
#ELSEIF %f == 05 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-15 \
shr eax, 31-15+15 \
#ELSEIF %f == 06 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-19 \
shr eax, 31-19+19 \
#ELSEIF %f == 07 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-23 \
shr eax, 31-23+23 \
#ELSEIF %f == 08 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-24 \
shr eax, 31-24+24 \
#ELSEIF %f == 09 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-25 \
shr eax, 31-25+25 \
#ELSEIF %f == 10 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-26 \
shr eax, 31-26+26 \
#ELSEIF %f == 11 \
mov eax, 1 \
cpuid \
mov eax, edx \
shl eax, 31-28 \
shr eax, 31-28+28 \
#ELSEIF %f == 12 \
mov eax, 1 \
cpuid \
mov eax, ecx \
#ENDIF \
pop ebx

msm(%dst,%src)= \
push %src \
pop %dst

mrm(%dst,%src,%reg)= \
mov %reg, %src \
mov %dst, %reg

MEMALLOC(%size)= \
#IFNDEF BkMacros_Process_Heap \
DATA SECTION \
BkMacros_Process_Heap DD 0 \
CODE SECTION \
INVOKE Kernel32:GetProcessHeap \
mov D[BkMacros_Process_Heap], EAX \
#ENDIF \
INVOKE Kernel32:HeapAlloc, D[BkMacros_Process_Heap], 00000008h, %size

MEMFREE(%pmem)= \
INVOKE Kernel32:HeapFree, D[BkMacros_Process_Heap], 0, %pmem

donkey

Hi Synfire,

Though I think cpu_ is not a general enough macro to be included I will have to think some more on the subject. Branch hints are available in GoAsm as part of the syntax...

hint.nobranch           ;insert 2Eh
hint.branch             ;insert 3Eh

For salc, I will include it as part of the windows.h header file since it is a useful opcode I have both used and seen others use in code, it should operate under a X86USEUNDOC switch so it can be easily be traced and removed if necessary. The next version of Windows.h (my current version) will contain the lines...

#IFDEF X86USEUNDOC
// Submitted by Synfire
#DEFINE salc DB 0D6h ; Set AL based on Carry Flag
#DEFINE SALC salc
#ENDIF


I think this is a fair treatment for the opcode since it requires it to be explicitly allowed.


The other macros, mrm, msm, memalloc and memfree are all useful and general enough so they will be included.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Hi Synfire,

I have modified your MEMALLOC and MEMFREE macros cosmetically since I use the convention that all labels either used in or generated by macros should be prefixed with %... This is how they will appear in macros.a :

#IFNDEF MEMALLOC
MEMALLOC(%size) MACRO
#IFNDEF %Process_Heap
DATA SECTION
%Process_Heap DD 0
CODE SECTION
INVOKE Kernel32:GetProcessHeap
mov [%Process_Heap], EAX
#ENDIF
INVOKE Kernel32:HeapAlloc, [%Process_Heap], 00000008h, %size
ENDM
#ENDIF

#IFNDEF MEMFREE
MEMFREE(%pmem) MACRO
INVOKE Kernel32:HeapFree, [%Process_Heap], 0, %pmem
ENDM
#ENDIF


Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Synfire

You wouldn't believe how hard those two (MEMALLOC/MEMFREE) were to write using the old multiline style.. well, MEMALLOC anyways.