flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > constant always a constant in my procedure |
Author |
|
bitRAKE 30 Mar 2013, 22:52
I know that you would need to count with the preprocessor. Look at baldr's post here. There was another post with specific explanation of this technique, but some time searching - I was unable to find it.
IIRC, FASM macros use a different method at assemble-time. Maybe use the listing tools to RE that process? _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
30 Mar 2013, 22:52 |
|
hopcode 31 Mar 2013, 08:00
this is 64bit, ABI is more complex than 32 bit. but may give you an hint. that is very raw and without fanciness
http://code.google.com/p/x64lab/source/browse/develop/macro/mrk_macrow.inc line 114 and 190 HTH, _________________ ⠓⠕⠏⠉⠕⠙⠑ |
|||
31 Mar 2013, 08:00 |
|
alwaysnub 31 Mar 2013, 18:29
Ok i fixed it. I simply need to declare the offset as equ then add to it the size of each parameter. See:
Code: macro PROC ProcName,[arg] ;Define procedure. { define ProcName $ BytesAtProc = 0 ParamOffset equ 8 reverse match argName:argType, arg \{ match =BYTE, argType \\{ BytesAtProc = BytesAtProc + 1 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+1 \\} match =WORD, argType \\{ BytesAtProc = BytesAtProc + 2 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+2 \\} match =DWORD, argType \\{ BytesAtProc = BytesAtProc + 4 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+4 \\} match =QWORD, argType \\{ BytesAtProc = BytesAtProc + 8 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+8 \\} \} common define BytesAt#ProcName BytesAtProc PUSH EBP MOV EBP,ESP } Note that BytesAt#ProcName is used to fix the stack after the call to the procedure. Im da man |
|||
31 Mar 2013, 18:29 |
|
baldr 31 Mar 2013, 19:54
alwaysnub wrote: Ok i fixed it. Perhaps define ProcName $ isn't doing what you're expecting (define is a preprocessor directive, and $ is a compiler symbol). Same for define BytesAt#ProcName BytesAtProc. Win32 ABI uses 32-bit stack values for BYTE and WORD values too (so you might be quite surprized). Arguments are pushed in reverse before call, yet on stack they're in natural order (i.e. first of them is at ebp+8 anyway). Difference between define and equ is that latter expands symbolic constants in assigned value prior to definition, while former defers expansion until symbolic constant usage. Is ItsOffset defined anywhere? |
|||
31 Mar 2013, 19:54 |
|
alwaysnub 31 Mar 2013, 20:08
its not for windows, its for my own OS, hence the difference in how addressing the stack is working... define ProcName $ should work, though untester as of right now (I know BytesAt#ProcName works correctly because im looking at the bytes in the bin file). Also ItsOffset becomes apart of arg Name. Here is my complete source for your understanding:
Code: macro PROC ProcName,[arg] ;Define procedure. { define ProcName $ BytesAtProc = 0 ParamOffset equ 8 reverse match argName:argType, arg \{ match =BYTE, argType \\{ BytesAtProc = BytesAtProc + 1 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+1 \\} match =WORD, argType \\{ BytesAtProc = BytesAtProc + 2 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+2 \\} match =DWORD, argType \\{ BytesAtProc = BytesAtProc + 4 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+4 \\} match =QWORD, argType \\{ BytesAtProc = BytesAtProc + 8 argName#ItsOffset equ ParamOffset argName equ [EBP+argName#ItsOffset] ParamOffset equ ParamOffset+8 \\} \} common define BytesAt#ProcName BytesAtProc PUSH EBP MOV EBP,ESP } macro ENDP ;End procedure. { POP EBP RETD } macro PCALL ProcName,[arg] ;Directly call procedure. { forward PUSH arg common CALL NEAR DWORD ProcName ADD ESP,BytesAt#ProcName } macro PICALL ProcName,[arg] ;Indirectly call procedure. { forward PUSH arg common CALL NEAR DWORD [ProcName] ADD ESP,BytesAt#ProcName } |
|||
31 Mar 2013, 20:08 |
|
baldr 01 Apr 2013, 08:29
alwaysnub,
Well, custom calling conventions are always fun to explore. Let's see: Code: include "proc.finc" use32 org 0x10000 PROC abs, x: DWORD mov eax, x .again: neg eax jo .done js .again .done: ENDP PROC max, y: DWORD, z: DWORD mov eax, y mov ecx, z cmp eax, ecx cmovl eax, ecx ENDP align 16 PCALL abs, -10 PCALL max, eax, 11 Code: include "proc.finc" use32 org 0x10000 ; PROC abs, x: DWORD PUSH EBP ;00010000: 55 MOV EBP,ESP ;00010001: 89 E5 ; mov eax, x mov eax, [EBP+8] ;00010003: 8B 45 08 .again: neg eax ;00010006: F7 D8 ; jo .done jo 0x1000C ;00010008: 70 02 ; js .again js 0x10006 ;0001000A: 78 FA .done: ; ENDP POP EBP ;0001000C: 5D RETD ;0001000D: C3 ; PROC max, y: DWORD, z: DWORD PUSH EBP ;0001000E: 55 MOV EBP, ESP ;0001000F: 89 E5 ; mov eax, y mov eax, [EBP+8+4] ;00010011: 8B 45 0C ; mov ecx, z mov ecx, [EBP+8] ;00010014: 8B 4D 08 cmp eax, ecx ;00010017: 39 C8 cmovl eax, ecx ;00010019: 0F 4C C1 ; ENDP POP EBP ;0001001C: 5D RETD ;0001001D: C3 ;;; So far, so good. Now we'll try to call them align 16 ;0001001E: 90 90 ; PCALL abs, -10 PUSH -10 ;00010020: 6A F6 CALL 0x10022 ;00010022: E8 FB FF FF FF ;;; WTF?! CALL instruction refers to itself as a target! ADD ESP, 8 ;00010027: 83 C4 08 ;;; Huh? There were only 4 bytes pushed! ; PCALL max, eax, 11 PUSH eax ;0001002A: 50 PUSH 11 ;0001002B: 6A 0B CALL 0x1002D ;0001002D: E8 FB FF FF FF ;;; Now it becomes clearer, I think. ADD ESP, 8 ;00010032: 83 C4 08 ;;; Probably everything is clear now.
Anyway, your calling convention looks like weird mix of pascal and cdecl. Parameters pushing order makes it almost unusable for variadic functions, then caller being responsible for stack cleanup seems not very size-optimal. While unaligned stack is almost OK, your PCALL/PICALL macros simply push actual parameters (well, push ax is perfectly valid, does push al?) And last, but not least, embedded brackets in formal parameters' definition prevent their proper usage. Consider this: Code: PROC bswap8, qw:QWORD mov edx, qw; start with low dword bswap edx; byte-swap it mov eax, ???; we're stuck, high dword seems to be inaccessible |
|||
01 Apr 2013, 08:29 |
|
alwaysnub 02 Apr 2013, 03:24
I have found a solution to most of the problems except defining the address of the function... I tried defining ProcName as a label in the PROC macro (ProcName:) but it did not work. any ideals ??? preferably one that works so that i can define the procedure under the call?
And one last question, how do i/can i add a period to an equ constant? For example: ProcName.something equ something I have tried without success. Your help much appreciated! |
|||
02 Apr 2013, 03:24 |
|
baldr 02 Apr 2013, 06:09
alwaysnub wrote: I have found a solution to most of the problems except defining the address of the function... I tried defining ProcName as a label in the PROC macro (ProcName:) but it did not work. any ideals ??? preferably one that works so that i can define the procedure under the call? alwaysnub wrote: And one last question, how do i/can i add a period to an equ constant? |
|||
02 Apr 2013, 06:09 |
|
alwaysnub 03 Apr 2013, 00:48
Yes, ProcName: does seem to work, when testing it last night i was thinking the call op used a direct address in its code when its using an offset (which i new), i must have been sleeping
however: argName#.something equ Blah does not work correctly. argName does not become the argName, but instead it is argName... lol Code: macro PROC ProcName,[arg] ;Define procedure. { common ProcName: PUSH EBP MOV EBP,ESP BytesAtProc = 0 ParamOffset equ 8 reverse match argName:argType, arg \{ match =WORD, argType \\{ BytesAtProc = BytesAtProc + 2 argName equ [EBP+ParamOffset] ParamOffset equ ParamOffset+1 argName#.HiByte equ [EBP+ParamOffset] ParamOffset equ ParamOffset+1 \\} match =DWORD, argType \\{ BytesAtProc = BytesAtProc + 4 argName equ [EBP+ParamOffset] ParamOffset equ ParamOffset+4 \\} match =QWORD, argType \\{ BytesAtProc = BytesAtProc + 8 argName equ [EBP+ParamOffset] ParamOffset equ ParamOffset+8 \\} \} } macro ENDP ;End procedure. { POP EBP RETD BytesAtProc } macro PCALL ProcName,[arg] ;Directly call procedure. { forward PUSH arg common CALL NEAR DWORD ProcName } macro PICALL ProcName,[arg] ;Indirectly call procedure. { forward PUSH arg common CALL NEAR DWORD [ProcName] } USE16 ORG 0 PCALL MyFunction, AX, DWORD 249 someData: DD 0 PROC MyFunction, Lkiop:WORD, Ihujwef:DWORD MOV AX,Lkiop MOV EAX,Ihujwef ;MOV AL,Lkiop.HiByte ;not working!!! MOV AL,argName.HiByte ;works !!! ??? ;ENDP What you think? |
|||
03 Apr 2013, 00:48 |
|
baldr 03 Apr 2013, 08:00
alwaysnub wrote: argName#.something equ Blah does not work correctly. argName does not become the argName, but instead it is argName. Your notation is somewhat inconsistent with general fasm rule: name is an address, [name] is a value at that address. If you remove brackets in argName equ [EBP+ParamOffset], no additional equs needed: simple mov al, [Lkiop+1] will do. BytesAtProc is always 8 less than ParamOffset, isn't it? You may use RETD ParamOffset-8 in ENDP with the very same effect (and drop BytesAtProc altogether). There is a trick to perform calculations with preprocessor: rept evaluates base value for counter symbol (it does so for number of repetitions too, but now it's insignificant). So, assuming ParamOffset is 8, rept 1 x:ParamOffset+4 { ParamOffset equ x } results in ParamOffset being 12, not 8+4 as ParamOffset equ ParamOffset+4 does. |
|||
03 Apr 2013, 08:00 |
|
alwaysnub 04 Apr 2013, 02:55
Quote: Your notation is somewhat inconsistent with general fasm rule: name is an address, [name] is a value at that address. If you remove brackets in argName equ [EBP+ParamOffset], no additional equs needed: simple mov al, [Lkiop+1] will do. More like inconsistent with asm in general... am i right? lol I think it comes down to how much of the assembly the programmer wants to hide (make it look like a higher language). I personally think MOV AX,Lkiop & MOV AL,Lkiop.HiByte is nice and clean. Quote: BytesAtProc is always 8 less than ParamOffset, isn't it? You may use RETD ParamOffset-8 in ENDP with the very same effect (and drop BytesAtProc altogether). Nice thinking! Here it is everyone, free example: Code: macro PROC ProcName,[arg] ;Define procedure. { common ProcName: PUSH EBP MOV EBP,ESP ParamOffset equ 8 reverse match argName:argType, arg \{ match =WORD, argType \\{ argName equ [EBP+ParamOffset] rept 1 x:ParamOffset+1 \\\{ ParamOffset equ x \\\} argName\#.HiByte equ [EBP+ParamOffset] rept 1 x:ParamOffset+1 \\\{ ParamOffset equ x \\\} \\} match =DWORD, argType \\{ argName equ [EBP+ParamOffset] rept 1 x:ParamOffset+2 \\\{ ParamOffset equ x \\\} argName\#.HiWord equ [EBP+ParamOffset] rept 1 x:ParamOffset+2 \\\{ ParamOffset equ x \\\} \\} \} } macro ENDP ;End procedure. { POP EBP RETD ParamOffset-8 } macro PCALL ProcName,[arg] ;Directly call procedure. { common if ~ arg eq forward PUSH arg common end if CALL NEAR DWORD ProcName } macro PICALL ProcName,[arg] ;Indirectly call procedure. { common if ~ arg eq forward PUSH arg common end if CALL NEAR DWORD [ProcName] } USE16 ORG 0 PCALL MyFunction, AX, DWORD 249 PCALL MyFunction2 PROC MyFunction, Lkiop:WORD, Ihujwef:DWORD MOV AX,Lkiop MOV EAX,Ihujwef MOV AL,Lkiop.HiByte MOV AX,Ihujwef.HiWord ENDP PROC MyFunction2 ;No parameter proc. ENDP If you find any problems or have any ideals let us know baldr. Thanks! |
|||
04 Apr 2013, 02:55 |
|
revolution 04 Apr 2013, 03:10
It is unfortunate that Intel decided to use mov for register copy, memory load and memory store. So constructs like 'MOV AX,Lkiop' are ambiguous. Does it load a memory value or a constant? MASM has those unfortunate HLL lookalike constructs also.
To me it would be much clearer to determine that 'MOV AX,[Lkiop]' is a memory read. Unambiguous. And 'MOV AX,Lkiop' is a constant load. Also unambiguous if one adopts the syntax of all memory references must use the square brackets []. Mixing memory reads and constants loads with the same syntax creates not only a problem of ambiguity, but also how to extract the constant value (if one exists)? And thus the keyword 'offset' was born. A kludge upon a kludge IMO. |
|||
04 Apr 2013, 03:10 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.