flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > problem defining data with "local" macro |
Author |
|
Tomasz Grysztar 20 Dec 2006, 22:41
Right, so it's just one more correction to macros in latest 1.67.17 package.
|
|||
20 Dec 2006, 22:41 |
|
madmatt 21 Dec 2006, 00:23
Great! Thanks.
|
|||
21 Dec 2006, 00:23 |
|
madmatt 05 Jan 2007, 18:12
Um, this is more a request than a bug, but would it be possible to align DQWORD (xmm?) data on the stack to 16 bytes? And for that matter, mmx data to 8 bytes?
|
|||
05 Jan 2007, 18:12 |
|
vid 05 Jan 2007, 20:35
like this?
Code: locals align 16 dq 0 endl but i agree for LOCAL macro, 8 and 16 byte data should be aligned |
|||
05 Jan 2007, 20:35 |
|
madmatt 05 Jan 2007, 21:42
Vid: tried your method but get an invalid value error.
After thinking about it a bit more, I have to wonder if it's even possible? the esp value would change each run of the executeable, and therefore alignment would be next to impossible to calculate?. |
|||
05 Jan 2007, 21:42 |
|
LocoDelAssembly 05 Jan 2007, 22:29
BTW, is this possible with EBP-based frames? I found pretty hard aligning and keeping access to parameters (but on ESP-based frames EBP clould be dedicated for parameters access and ESP for local variables access).
|
|||
05 Jan 2007, 22:29 |
|
vid 06 Jan 2007, 04:43
madmatt: you are right, i didn't realize that. but you still can do something like:
Code: push ebp mov ebp, esp and ebp, not (16-1) ;16 = highest needed alignment, can be also 8 sub esp, 1234 you just need to tweak proc macros |
|||
06 Jan 2007, 04:43 |
|
LocoDelAssembly 06 Jan 2007, 05:20
vid, since proc uses EBP based frame I think that this is quite imposible, the padding will be of variable length but the offsets will not change on runtime, so things like:
Code: mov eax, [parameter] Code: mov eax, [ebp+fixedOffset] Code: mov eax, [ebp+fixedOffset+paddingSize] A solution to keep EBP-based frames could be modifying proc macros to signalize invoke/stdcall/ccall to perform correct alignment. Example: Code: stdcall exampleProc, 4, 6, 9 proc exampleProc stackAlignment:QWORD, arg1, arg2, arg3 ret endp The "dissasembling" of that is Code: ; and esp, -7 ; I'd would like to use it but I have no idea of how to restore its original value... sub esp, 4 ; ESP-4 push 9 ; ESP-8 push 6 ; ESP-12 push 4 ; ESP-16 call exampleProc ; ESP-20 add esp, 4 exampleProc: push ebp ; ESP-24 mov ebp, esp ; Now we have a QWORD aligned ESP (24 mod 8 = 0) leave retn 12 A possible solution but quite unoptimal could be relocating parameters after padding by moving them to the padding area. |
|||
06 Jan 2007, 05:20 |
|
vid 06 Jan 2007, 08:39
sorry, i'm ill now, my thinking is kinda slowed down
|
|||
06 Jan 2007, 08:39 |
|
LocoDelAssembly 06 Jan 2007, 15:33
I checked IA-32 Intel® Architecture Optimization the Appendix D Stack Alignment, I don't like what I saw... It needs EBX so it's simple unnaceptable (for me at least).
Note that I was wrong about moving to the padding area because I forgot that between local variables and parameter exists something called return address so doing such movement will overwrite it... (unless of course that the total length of the parameters are less than the padding size). For that reason actually we need to assign some space in the stack frame and copy all parameters to it (so the stack will have two copies of the parameters). The other alternative (which I like a little more) is leaving the resposability of aligning the stack to the caller in this way: 1- If invoke/stdcall/ccall is called from a non proc context then is resposability of the programmer to preserve ESP in some way. 2- If invoke/stdcall/ccall is called from a proc context then the proc macro will redefine invoke/stdcall/ccall with a special code that will do "mov [ebp+secretESPSaveArea], esp" and proc macro of course will define such local variable if it detects that there was some call to a proc with stackAlignment option. So here an example of case 2 Code: proc a stdcall b, 1, 2, 3 ret endp proc b arg1, arg2, arg3 ret endp The "dissasembling": Code: a: push ebp mov ebp, esp sub esp, 4 ; Space for secretESPSaveArea mov [ebp+secretESPSaveArea], esp and esp, -8 sub esp, 4 ; (total size of parameters[12] + return address size[4] + callee's EBP save area[4]) mod 8 push 3 push 2 push 1 call b mov esp, [ebp+secretESPSaveArea] leave ret b: push ebp mov ebp, esp ; sub esp, 4 ; Space for secretESPSaveArea (Not this time since b does not call anything needing stack alignment) leave retn 12 |
|||
06 Jan 2007, 15:33 |
|
LocoDelAssembly 06 Jan 2007, 19:25
Forget secretESPSaveArea, it is really stupid specially when we have an alternative which is context independent...
This is my new alternative Code: mov edx, esp ; Since "addr" destroys EDX I take the license to do the same and esp, -8 ; for QWORD alignment; -16 for DQWORD alignment; -4 for DWORD alignment (typicaly unneded since stack looses its DWORD aligning on very few and unconventional situations like push reg16) sub esp, (espSaveArea+totalSizeOfParamenters+returnAddressSize+CalleeEBPSaveArea) mod alignmentSize push edx push allParams call procedure pop esp |
|||
06 Jan 2007, 19:25 |
|
LocoDelAssembly 06 Jan 2007, 23:04
Code: ; ### DON'T USE THE MACROS BELOW macro PrepareStack alignment, paramsSize { mov edx, esp ; Since "addr" destroys EDX I take the license to do the same and esp, -alignment if ((paramsSize+12) mod alignment) > 0 sub esp, alignment - ((paramsSize+12) mod alignment) end if push edx } macro CalculateParamsSize outResult, [params] { common outResult = 0 forward if params ~eq outResult = outResult + 4 match =double param, params\{outResult = outResult + 4\} end if } macro DoCall callType, proc, [params] { common local paramsSize if defined proc#.stackAlignment CalculateParamsSize paramsSize, params PrepareStack proc#.stackAlignment, paramsSize callType proc, params pop esp else callType proc, params end if } ;### ONLY USE THE MACROS BELOW macro SetStackAlignment procName, alignType { local stackAlignment stackAlignment = 0 match =DWORD, alignType\{stackAlignment = 4\} match =QWORD, alignType\{stackAlignment = 8\} match =DQWORD, alignType\{stackAlignment = 16\} if ~stackAlignment display `alignType," is not a valid alignment" err end if procName#.stackAlignment = stackAlignment } macro invoke proc, [params] { common DoCall invoke, proc, params } macro cinvoke proc, [params] { common DoCall cinvoke, proc, params } macro stdcall proc, [params] { common DoCall stdcall, proc, params } macro ccall proc, [params] { common DoCall ccall, proc, params } In any place use SetStackAlignment procName, {DWORD|QWORD|DQWORD} I tested it a little so more testings are welcome Cheers PS: BTW, http://board.flatassembler.net/topic.php?p=50905#50905 is still a good feature to have since my macros just aligns EBP but that doesn't prevent you from unalign local data, for example Code: locals character: BYTE sseData: DQWORD ; Unaligned even with my macros ends But this feature will require a built in proc SetStackAlignment feature to inform to "align" up to which number the alignment can be made. Last edited by LocoDelAssembly on 07 Jan 2007, 00:24; edited 3 times in total |
|||
06 Jan 2007, 23:04 |
|
madmatt 06 Jan 2007, 23:08
I've found a solution that is simple , and am wondering why I didn't think of it before . This will also allow arrays of DQWORDS as well.
Code: proc SomeProc local aligned_address:DWORD, xmmdata:[(NUMBER_OF_DQWORDS * 16) + 16] lea eax, [xmmdata] and eax, $fffffff0 add eax, 16 mov [aligned_address], eax .....more code endp |
|||
06 Jan 2007, 23:08 |
|
LocoDelAssembly 07 Jan 2007, 00:35
I did some bugs corrections. Using your example I did the following test that runs flawlessly
Code: format pe gui include 'win32axp.inc' include 'stackAlignment.inc' ; The macros posted previously NUMBER_OF_DQWORDS equ 8 dec esp ;guaranteed odd number stdcall SomeProc inc esp ret proc SomeProc local xmmdata[NUMBER_OF_DQWORDS]:DQWORD SetStackAlignment SomeProc, DQWORD match count, NUMBER_OF_DQWORDS { rept count i:0, NUMBER_OF_DQWORDS\{movdqa xmm\#i, [xmmdata+16*i]\} } ret endp The dissasembling of all that (with the assistance of OllyDbg ) is: Code: dec esp mov edx, esp and esp, -16 sub esp, 4 push edx call SomeProc pop esp inc esp retn SomeProc: push ebp mov ebp, esp sub esp, $80 movdqa xmm0, [ebp-80] movdqa xmm1, [ebp-70] movdqa xmm2, [ebp-60] movdqa xmm3, [ebp-50] movdqa xmm4, [ebp-40] movdqa xmm5, [ebp-30] movdqa xmm6, [ebp-20] movdqa xmm7, [ebp-10] leave retn Without the macros the program crashes inmediately of course since movdqa requires aligned addresses. |
|||
07 Jan 2007, 00:35 |
|
madmatt 07 Jan 2007, 07:01
Making it a little bit simpler, thanks to locodelassembly:
Code: proc SomeProc local aligned_address:DWORD, xmmdata[NUMBER_OF_DQWORDS + 1]:DQWORD lea eax, [xmmdata] and eax, $fffffff0 add eax, 16 mov [aligned_address], eax .....more code endp |
|||
07 Jan 2007, 07:01 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.