I try to write a macro creating a window
STATIC_CONTROL_CREATION MACRO hParent:REQ,X:REQ,_:REQ,W:REQ,H:REQ,lpszTitle:REQ,dwStyle:REQ
mov [rsp + 40h],hParent
mov eax,__H
mov DWORD PTR [rsp + 20h],__X
mov DWORD PTR [rsp + 28h],__Y
mov DWORD PTR [rsp + 30h],__W
mov DWORD PTR [rsp + 38h],eax ;; H
xor ecx,ecx
mov rax,hInstance
mov DWORD PTR [rsp + 48h],-1
mov [rsp + 58h],ecx
lea rdx,szClass_Static + rip
mov r8,lpszTitle
mov r9d,dwStyle
mov [rsp + 50h],rax ;; hInstance
call CreateWindowExA
EXITM
ENDM
and I have the error:
C:\Users\XXXXXXXXXXXXXXXDocuments\# Assembleur #\Awpe\Awpe.asm(868): error: Expected 'ENDM'.
What is the problem?
I rarely use macros and I am not lucky.
I read the help file and all seemed OK.
Why?
Hi Philippe,
You don't need EXITM to terminate the macro. ENDM does the job.
Reading Pelles help file :
QuoteThe body may contain one or more EXITM directives, making it possible to return a value from the macro. The use of EXITM signals the macro as being a special function-like macro suitable for use in expressions. All tokens following EXITM up to the following line break will be used as the return value.
Thank you Vortex
The problem was because I had no new line after ENDM
8)
Hi Philippe,
You are welcome. Any specific reason to avoid the invoke macro in your code?
Hi Vortex,
I add the of making a macro or a procedure.
Like I never make macros, I would lie to try
I has 95 windows to create
That's all
Philippe
Hi Philippe,
QuoteLike I never make macros
I understand your choice but invoke is simplifiying a lot of tedious tasks.
Hello Vortex,
I agree with you but if the code is not pretty I prefer doing it at the hand.
A thing that we should be able to modify easily is the prolog.
I read a lot of thing about it.
I think that if you want an aligned string or structure we must declare it as a string and then declare a pointer on it but a place it is aligned on a 16 byte boundary.
Example
LOCAL _Lvi:LVITEM becomes
LOCAL _Lvi[2 * SIZEOF LVITEM]:BYTE
LOCAL _lpLvi:LPLVITEM
lea rax,_Lvi
and rax,NOT 15
mov _lpLvi,rax
then only use the pointer
That's very fresh, maybe there are errors in my writing.
I read this from AMD - Optimization - 25112.PDF
https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/40332.pdf (https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/40332.pdf)
What you need for prolog ?
WinMainCRTStartup proc
this is empty prolog
also some align things are solved with right size LOCALs ?
I don't use asm, expect for fun.
hi Timo
Or keeping variables into register rather that stack.
I wonder if it would be a good idea to have a structure into which we have the local variables?
What do you think?
Hi Philippe,
You could align your structures by calculating their sizes.
Hi Philippe,
MASM – Stack Memory Alignment :
http://www.atelierweb.com/index.php/masm-stack-memory-alignment/
Hello and Thank you Vortex,
I have read (quickly) this post and it is the reason I used structures and delared them as a LOCAL variable like this:
STACKPTR_SEARCH_DIRECTORY STRUCT 8
lpHeaders LPPHR_PE_ANALYZER ? ; 8
lpDirectoryAddress LPSTR ? ; 8
lpszDirectoryName LPSTR ? ; 8
lpLvi LPLVITEM ? ; 8
lpszTmp LPBYTE ? ; 8
lpszVirtualAddress LPBYTE ? ; 8
lpszVirtualSize LPBYTE ? ; 8
hListView HWND ? ; 8
STACKPTR_SEARCH_DIRECTORY ENDS ; 64
LPSTACKPTR_SEARCH_DIRECTORY TYPEDEF PTR STACKPTR_SEARCH_DIRECTORY
STACKDATA_SEARCH_DIRECTORY STRUCT 16
szTmp BYTE 128 dup(?) ; 128
Lvi LVITEM <> ; 88
szVirtualAddress BYTE 64 dup(?) ; 64
szVirtualSize BYTE 64 dup(?) ; 64
dwDirectoryIndex DWORD ? ; 4
STACKDATA_SEARCH_DIRECTORY ENDS ; 348
LPSTACKDATA_SEARCH_DIRECTORY TYPEDEF PTR STACKDATA_SEARCH_DIRECTORY
STACK_SEARCH_DIRECTORY STRUCT 16
Data STACKDATA_SEARCH_DIRECTORY <> ; 352
Pointers STACKPTR_SEARCH_DIRECTORY <> ; 64
STACK_SEARCH_DIRECTORY ENDS ; 416
LPSTACK_SEARCH_DIRECTORY TYPEDEF PTR STACK_SEARCH_DIRECTORY
I hope I have not made errors
Give me your advices and remarks
I use a 16 bye alignment in case I use MMX instructions
I USE ONE STRUCTURE FOR DATAS AND THE OTHERR ONE FOR POINTERS
Philippe
Rather than using structure I thought to use a buffer and computing a 16 bytesd boundary, when found I declare a structure pointer on that position
Hi Philippe,
Your structures are looking OK. Thr most important is to align properly the members of the structures.
Hi Philippe,
The quick test below ( excluding the SSE stuff for the moment ) demonstrates that Poasm is successfully aligning the local structures to QWORD boundary.
include LocalStructAlign.inc
PRINTPAGERANGE STRUCT
nFromPage dd ?
nToPage dd ?
PRINTPAGERANGE ENDS
sample STRUCT
x db ?
y db ?
sample ENDS
.data
a1 db 'OFFSET var1 = %X',13,10,0
a2 db 'OFFSET var2 = %X',13,10,0
a3 db 'OFFSET ppr = %X',13,10,0
a4 db 'OFFSET s = %X',13,10,0
a5 db 'OFFSET var3 = %X',13,10,0
.data?
buffer db 64 dup(?)
.code
start PROC PARMAREA=4*QWORD
call main
invoke ExitProcess,0
start ENDP
main PROC PARMAREA=4*QWORD
LOCAL var1:QWORD ; rsp+50H
LOCAL var2:QWORD ; rsp+48H
LOCAL ppr:PRINTPAGERANGE ; rsp+38H
LOCAL s:sample ; rsp+30H
LOCAL var3:QWORD ; rsp+28H
invoke wsprintf,ADDR buffer,ADDR a1,ADDR var1
invoke StdOut,ADDR buffer
invoke wsprintf,ADDR buffer,ADDR a2,ADDR var2
invoke StdOut,ADDR buffer
invoke wsprintf,ADDR buffer,ADDR a3,ADDR ppr
invoke StdOut,ADDR buffer
invoke wsprintf,ADDR buffer,ADDR a4,ADDR s
invoke StdOut,ADDR buffer
invoke wsprintf,ADDR buffer,ADDR a5,ADDR var3
invoke StdOut,ADDR buffer
ret
main ENDP
Output on Windows 7 Sp1 :
OFFSET var1 = 22FC60
OFFSET var2 = 22FC58
OFFSET ppr = 22FC48
OFFSET s = 22FC40
OFFSET var3 = 22FC38
Hi Philippe,
This version aligns the structure to QWORD boundary :
sample STRUCT
x db ?
y db ?
padding db 6 dup(?)
sample ENDS
Hello My Master Vortex.
sample STRUCT 8
x db ?
Y db ?
sample ENDS
This one too
Ok I know how to align a structure but if somewhere two members of this structure must be aligned on a 16 byte boundary and the orhers on 4 bytes? Except with padding I don't see how to do
Pelle's also aligns very well the code on 16 bytes and data on 4 bytes
Hi Philippe,
QuoteOk I know how to align a structure but if somewhere two members of this structure must be aligned on a 16 byte boundary and the orhers on 4 bytes? Except with padding I don't see how to do
You are right. Consider this simple example :
sample STRUCT 16
x dd ?
y dd ?
z oword ?
sample ENDS
y and z are aligned to 16 byte boundary.
OWORD = 16 bytes
Hello Vortex,
Or directly like this
sample STRUCT 16
x OWORD ?
y OWORD ?
z OWORD ?
sample ENDS
In this case the structure address will have to be aligned on a multiple of 16
As we don't touch to the prolog I declare a Tmp variable
LOCAL TMP[256]:Byte
LEA RAX,TMP
AND RAX,NOT 15
MOV PtrStructure,RAX
What Do you think?
If the stack is aligned by 4 bytes, declare a dummy variable
LOCAL Dummy[16]:BYTE
LOCAL MyStruct:STRUCTURE
One thing I don't understand is if I had six strings I must repeat it for each string.
Philippe
Hi Philippe,
Try to declare all your structuresas as LOCALs. We can introduce dummy local variables between those critical LOCALs to satisfy the alignmnet requirements.
Hi Vortex,
That's what I did but if we could have a directive like ALIGN that would be great.
Yestirday I looked at a disassembler written in C.
There were many structures using many UNIONS and records, very hard to read and to translate
EVEN POH2iNC DID NOT ARRIVED TO TRANSLATE
I have a keyboard that itself when it muts write in uppercase.
Have a look:
#ifdef _ENABLE_VEX_INFO
struct vex_info {
struct {
uint8_t type;
union {
struct byte2 {
uint8_t vex_pp: 2;
uint8_t vex_l: 1;
uint8_t vex_v: 4;
uint8_t vex_r: 1;
} vexc5b;
uint8_t val5;
};
union {
struct byte3 {
uint8_t vex_m : 5;
uint8_t vex_b : 1;
uint8_t vex_x : 1;
uint8_t vex_r : 1;
uint8_t vex_pp : 2;
uint8_t vex_l : 1;
uint8_t vex_v : 4;
uint8_t vex_w : 1;
} vexc4b;
uint16_t val4;
};
};
};
#endif
struct instruction {
uint64_t disp;
uint64_t imm;
uint64_t label;
#ifdef _ENABLE_VEX_INFO
struct vex_info _vex;
#endif
#ifdef _ENABLE_RAW_BYTES
uint8_t instr[15];
#endif
uint8_t prefixes[4];
uint8_t op;
union
{
struct
{
uint8_t rm : 3;
uint8_t reg : 3;
uint8_t mod : 2;
} bits;
uint8_t value;
} modrm;
union
{
struct
{
uint8_t rex_b : 1;
uint8_t rex_x : 1;
uint8_t rex_r : 1;
uint8_t rex_w : 1;
} bits;
uint8_t value;
} rex;
union
{
struct
{
uint8_t base : 3;
uint8_t index : 3;
uint8_t scaled : 2;
} bits;
uint8_t value;
} sib;
uint8_t vex[3];
int length;
int disp_len;
int imm_len;
uint16_t set_prefix; // bit mask
uint16_t set_field;
uint8_t jcc_type;
int8_t vex_cnt;
int8_t prefix_cnt;
};
:-\ :-* :'(
Another converter :
3. About h2incX
This tool's purpose is to convert C header files to Masm-style include files.
It is much more powerful than Microsoft's h2inc tool. The main purpose is to convert the Win32 include files,
but it should work with any C header files as well. It is a simple Win32 console application, but a 32bit DOS extended binary version is included as well to be used on Non-Win32 platforms.
https://www.terraspace.co.uk/uasm.html#p3
Japheth's h2incX :
https://github.com/Baron-von-Riedesel/h2incX
Thank You Vortex.
One thing is strange with PoAsm is using union, or I don't understand. I never use them.
h2IncX is more complete that PoH2Inc.
I would use it it with the "-D3" parameter.
Gave a good day Philippe
I tried tocompile JWAsm but too many errors in the source file
About h2incc (https://github.com/madebr/h2incc)
ThankY ou :)
Hi Timo,
Many thanks.