Hello!
Currently I learning asm with AVX and lost a little bit with Macros. Especially with this one: https://github.com/Apress/modern-x86-as ... 4-AVX.asmh
(used in this example https://github.com/Apress/modern-x86-as ... 07_06_.asm)
The goal is to create DLL in EuroAssembler with exactly same functionality. Is there elegant way to port the macros like _CreateFrame and _Save/RestoreXmmRegs to EuroAssembler?
Thank you in advance,
Andrey.
MASM Macros to EuroAssembler
-
- Posts: 3
- Joined: 01 Jun 2023 09:11
- vitsoft
- Site Admin
- Posts: 49
- Joined: 04 Nov 2017 20:08
- Location: Vítkov, The Czech Republic
- Contact:
Re: MASM Macros to EuroAssembler
Hello Andrey, there is a way but not much elegant and I had to omit MASM directives for SEH (Structured Exception Handling) which are not supported by €ASM:
If you want it more elegant, use macros from https://euroassembler.eu/maclib/fastcall.htm
Uses saves and restores the enumerated GPR and XMM registers (unfortunately only the low half of XMM)
However, you can reserve space on stack for save/restore XMMs with LocalVar and you won't need the complex MASM frame machinery. Something like
;------------------------------------------------------------------------- ; Description: The following macro generates code that creates a stack ; frame for x86-64 functions. ; Macro Parameters: %1 Prefix Macro symbolic name prefix ; %2 StkSizeLocal1 Size in bytes for local1 vars ; %3 StkSizeLocal2 Size in bytes for XMM reg save area ; %4..%10 Rnv1 - Rnv7 Non-volatile registers to save _CreateFrame %MACRO Prefix,StkSizeLocal1,StkSizeLocal2,Rnv1,Rnv2,Rnv3,Rnv4,Rnv5,Rnv6,Rnv7 %IF %StkSizeLocal1 \ 16 ; Make sure stack sizes are valid %ERROR Macro parameter %StkSizeLocal1 must be evenly divisible by 16. %ENDIF %IF %StkSizeLocal2 \ 16 %ERROR Macro parameter %StkSizeLocal2 must be evenly divisible by 16. %ENDIF %IF %StkSizeLocal2 > 240 %ERROR Macro parameter %StkSizeLocal2 must be less than or equal to 240. %ENDIF PUSH RBP ; Push previous frame pointer. %GPRtoPush %SET ; Make the list of GPR-to-save empty. %GPRtoPop %SET ; Make the list of GPR-to-restore empty. ArgNr %FOR 4..10 ; FOR-loop thru 4-th and further macro argument. %GPR %SET2 %%Rnv%ArgNr %IF %GPR ; If ArgNr-th argument is specified. %GPRtoPush %SET %GPRtoPush,%GPR ; Populate the list of registers to save. %GPRtoPop %SET %GPR,%GPRtoPop ; Populate the list in inversed order. %ENDIF %ENDFOR ArgNr %NumPushReg %SETL %GPRtoPop %NumPushReg %SETA %NumPushReg + 1 ; Increment because RBP was already pushed. %IF %NumPushReg > 1 PUSH %GPRtoPush ; Push all specified non-volatile registers specified on the list. %ENDIF %StackPad %SETA ((%NumPushReg & 1) ^ 1) * 8 ; Zero when there are no other GPR than RBP. %StackSizeTotal %SETA %StkSizeLocal1+%StkSizeLocal2+%StackPad SUB RSP,%StackSizeTotal %IF %StkSizeLocal2 > 0 LEA RBP,[RSP+%StkSizeLocal2] %ELSE MOV RBP,RSP %ENDIF ; Create the symbols for current function %Prefix{}StackSizeTotal EQU %StackSizeTotal %Prefix{}StackSizeLocal1 EQU %StkSizeLocal1 %Prefix{}StackSizeLocal2 EQU %StkSizeLocal2 %Prefix{}OffsetHomeRCX EQU %StkSizeLocal1+%NumPushReg*8+%StackPad+8 %Prefix{}OffsetHomeRDX EQU %StkSizeLocal1+%NumPushReg*8+%StackPad+16 %Prefix{}OffsetHomeR8 EQU %StkSizeLocal1+%NumPushReg*8+%StackPad+24 %Prefix{}OffsetHomeR9 EQU %StkSizeLocal1+%NumPushReg*8+%StackPad+32 %Prefix{}OffsetStaclArgs EQU %StkSizeLocal1+%NumPushReg*8+%StackPad+40 %ValNameOffsetSaveXmmRegs %SET %Prefix{}OffsetSaveXmmRegs %Prefix{}OffsetSaveXmmRegs EQU %StkSizeLocal2 %ValNameOffsetDeleteFrame %SET %Prefix{}OffsetDeleteFrame %Prefix{}OffsetDeleteFrame EQU %StkSizeLocal1+%StackPad %ENDMACRO _CreateFrame ;------------------------------------------------------------------------- ; Description: The following macro generates code that de-allocate a ; stack frame previously created using _CreateFrame. ; Macro Parameters: Rnv1 - Rnv7 Non-volatile registers to restore _DeleteFrame %MACRO Rnv1,Rnv2,,, %IF (%ValNameOffsetDeleteFrame > 0) LEA RSP,[RBP+%ValNameOffsetDeleteFrame] %ELSE MOV RSP,RBP %ENDIF %IF %GPRtoPop ; List of Rnv7..Rnv1, if any. POP %GPRtoPop ; Restore all pushed registers at once. %ENDIF POP RBP %ENDMACRO _DeleteFrame ;------------------------------------------------------------------------- ; Description: The following macro generates code that saves the ; specified non-volatile registers to the local save area. ; Macro Parameters: Rnv1 - Rnv7 Non-volatile XMM registers to save. _SaveXmmRegs %MACRO Rnv0,Rnv1,Rnv2,Rnv3,Rnv4,Rnv5,Rnv6,Rnv7,Rnv8,Rnv9 %position %SETA 0 ; Position of XMM register stored in Local2 (0,16,32..) reg %FOR %* ; Repeat the %FOR block with all arguments. VMOVDQA [RBP-%ValNameOffsetSaveXmmRegs+%position],%reg %position %SETA %position+16 %ENDFOR reg %ENDMACRO _SaveXmmRegs ;------------------------------------------------------------------------- ; Description: The following macro generates code that restores the ; specified non-volatile registers from the local save area. ; Macro Parameters: Rnv1 - Rnv7 Non-volatile XMM registers to restore. ;------------------------------------------------------------------------- _RestoreXmmRegs %MACRO Rnv0,Rnv1,Rnv2,Rnv3,Rnv4,Rnv5,Rnv6,Rnv7,Rnv8,Rnv9 %position %SETA 0 ; Position of XMM register stored in Local2 (0,8,16,24..) reg %FOR %* ; Repeat the %FOR block with all arguments. VMOVDQA %reg,[RBP-%ValNameOffsetSaveXmmRegs+%position] %position %SETA %position+16 %ENDFOR reg %ENDMACRO _RestoreXmmRegs ;------------------------------------------------------------------------- ; A simple program to test the macros defined above. EUROASM CPU=X64,SIMD=AVX, NoWarn=2101 ; EUROASM ListRepeat=yes,ListMacro=yes,ListVar=yes ; Only if you want to debug the listing. Andrey PROGRAM Format=DLL,Width=64 EXPORT ConvertImgU8ToF32_ ConvertImgU8ToF32_ PROC _CreateFrame U2F_,0,160 _SaveXmmRegs xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 NOP ; Here should be inserted instructions from the procedure ConvertImgU8ToF32_ NOP ; https://github.com/Apress/modern-x86-as ... 07_06_.asm Done: _RestoreXmmRegs xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 _DeleteFrame RET ENDP ConvertImgU8ToF32_ ; %Display UserVariables, Symbols ; Only if you want to debug the listing. ENDPROGRAM
If you want it more elegant, use macros from https://euroassembler.eu/maclib/fastcall.htm
Uses saves and restores the enumerated GPR and XMM registers (unfortunately only the low half of XMM)
However, you can reserve space on stack for save/restore XMMs with LocalVar and you won't need the complex MASM frame machinery. Something like
EUROASM CPU=X64,SIMD=AVX, NoWarn=2101 ; EUROASM ListRepeat=yes,ListMacro=yes,ListVar=yes ; Only if you want to debug the listing. Elegant PROGRAM Format=DLL,Width=64 INCLUDE "fastcall.htm" EXPORT ConvertImgU8ToF32_ ConvertImgU8ToF32_ Procedure des, src, num_pixels Uses RSI,RDI ; GPR which shouldn't be clobbered in the procedure. ; The number of enumerated GPRs should be even to keep 16byte alignment of the following local stack variables. SavedXMM10 LocalVar Size=16 SavedXMM11 LocalVar Size=16 SavedXMM12 LocalVar Size=16 ; etc. VMOVDQA [%SavedXMM10],XMM10 ; Manually store XMMs which should't be clobbered. VMOVDQA [%SavedXMM11],XMM11 VMOVDQA [%SavedXMM12],XMM12 ; etc. ; Make sure num_pixels is valid and pixel buffers are properly aligned xor eax,eax ;set error return code ; Here should be instructions from the original procedure ConvertImgU8ToF32_ mov eax,1 ;set success return code Done: VMOVDQA XMM12,[%SavedXMM12] ; Manually restore XMMs which should't be clobbered. VMOVDQA XMM11,[%SavedXMM11] VMOVDQA XMM10,[%SavedXMM10] ; etc. EndProcedure ConvertImgU8ToF32_ ENDPROGRAM
-
- Posts: 3
- Joined: 01 Jun 2023 09:11
Re: MASM Macros to EuroAssembler
Wow, thank you so much, Pavel, it works after some minor changes like
vmovdqa xmm0, xmmword ptr [rdx] > vmovdqa xmm0, [rdx]
and
Uint8ToFloat real4 255.0, 255.0, 255.0, 255.0 > Uint8ToFloat: DD 255.0, 255.0, 255.0, 255.0
(tried Uint8ToFloat: DO..., but euroasm told me that the Oword memory variable cannot be statically initialized.)
Anyway got both ConvertImgU8ToF32 and ConvertImgF32ToU8 running. AVX rocks, they're fast.
Last week I've created simple DLL in MASM, NASM, FASM and YASM, but I like EuroAssembler, really. Now can continue my exercises.
The next step is to call some functions from third-party DLL directly from asm, but I'll get this myself, for sure.
Thanks again for your time and help!
Andrey.
vmovdqa xmm0, xmmword ptr [rdx] > vmovdqa xmm0, [rdx]
and
Uint8ToFloat real4 255.0, 255.0, 255.0, 255.0 > Uint8ToFloat: DD 255.0, 255.0, 255.0, 255.0
(tried Uint8ToFloat: DO..., but euroasm told me that the Oword memory variable cannot be statically initialized.)
Anyway got both ConvertImgU8ToF32 and ConvertImgF32ToU8 running. AVX rocks, they're fast.
Last week I've created simple DLL in MASM, NASM, FASM and YASM, but I like EuroAssembler, really. Now can continue my exercises.
The next step is to call some functions from third-party DLL directly from asm, but I'll get this myself, for sure.
Thanks again for your time and help!
Andrey.
- vitsoft
- Site Admin
- Posts: 49
- Joined: 04 Nov 2017 20:08
- Location: Vítkov, The Czech Republic
- Contact:
Re: MASM Macros to EuroAssembler
Hi, nice to read this.
Actually not directly with one value but this can be bypassed with specifying the type of each element. Here is an example of three variants how to define a vector of four real4 numbers (32bit DWORDs) and setting the vector type to OWORD:AndreyDmitriev wrote: ↑06 Jun 2023 08:33 Uint8ToFloat real4 255.0, 255.0, 255.0, 255.0 > Uint8ToFloat: DD 255.0, 255.0, 255.0, 255.0
(tried Uint8ToFloat: DO..., but euroasm told me that the Oword memory variable cannot be statically initialized.)
|[.data] ::::Section changed. |00000000:00007F4300007F43~|Uint8ToFloat1 DD 255.0, 255.0, 255.0, 255.0 |00000010:00007F4300007F43~|Uint8ToFloat2 DO D 255.0, D 255.0, D 255.0, D 255.0 |00000020:00007F4300007F43~|Uint8ToFloat3 DO 4*DWORD 255.0 | | %Display Symbols=Uint8* |# D1400 **** %DISPLAY Symbols=Uint8* |# D1450 Uint8ToFloat1,[.data]:00000000h,type='D',size=16,scope='S',ref='N',fix=Y,src="Andrey.asm"{143} |# D1450 Uint8ToFloat2,[.data]:00000010h,type='O',size=16,scope='S',ref='N',fix=Y,src="Andrey.asm"{144} |# D1450 Uint8ToFloat3,[.data]:00000020h,type='O',size=16,scope='S',ref='N',fix=Y,src="Andrey.asm"{145} |# D1790 **** End of %DISPLAY
Who is online
Users browsing this forum: No registered users and 1 guest