Would it be possible to named macro with any character like (+ * / - : , < > ... )* in future, access to char into parameter (%1 %2 ..) for cmp, instead entire word comparison**.
*: it's for translate unprintable ascii with C stuff for example:
\\ Literal backslash
\" Double quote
\' Single quote
\n Newline (line feed)
\r Carriage return
\b Backspace
\t Horizontal tab
\f Form feed
\a Alert (bell)
\v Vertical tab
\? Question mark (used to escape trigraphs)
%% Percentage mark, printf format strings only (Note \% is non standard and is not always recognised)
\ooo Character with octal value ooo
\xhh Character with hexadecimal value hh
and why not generate equation (2 * 3 + [rax] ...) directly/faster in asm code instead use compiler for it, design for complexes calculus.
**: it's for those macro, and I would like to detect if param is a reg/mem/string/label/nbr for doing a monster optimization, cause in that case, I will able to delete some useless mov uses for param passing when it's a label:
;=============================================================================================.
; call_win (call function with Windows ABI x64)
; https://msdn.microsoft.com/en-us/library/ms235286.aspx
; %0 = number of parameters received
; %1 = call_win.1st parameter
; %2 = func.1st parameter
;=============================================================================================.
%macro call_win 1-*
;{
%assign i 0 ; For shrink stack by n bytes
sub rsp, 40
;{
%if (%0 >= 2) ; func.1st
;{
%ifidni %2, ; if (string)
;{
[section .data]
%%str1: db %2, 0
[section .code]
mov rcx, %%str1
;}
%else ; else (reg/mem/string/label/nbr)
mov rcx, %6
%endif
;}
%endif
%if (%0 >= 3) ; func.2nd
;{
%ifidni %3, ; if (string)
;{
[section .data]
%%str2: db %3, 0
[section .code]
mov rdx, %%str2
;}
%else ; else (reg/mem/string/label/nbr)
mov rdx, %6
%endif
;}
%endif
%if (%0 >= 4) ; func.3rd
;{
%ifidni %4, ; if (string)
;{
[section .data]
%%str3: db %4, 0
[section .code]
mov r8, %%str3
;}
%else ; else (reg/mem/string/label/nbr)
mov r8, %6
%endif
;}
%endif
%if (%0 >= 5) ; func.4th
;{
%ifidni %5, ; if (string)
;{
[section .data]
%%str4: db %5, 0
[section .code]
mov r9, %%str4
;}
%else ; else (reg/mem/string/label/nbr)
mov r9, %6
%endif
;}
%endif
%if (%0 >= 6) ; func.5th
;{
sub rsp, ((%0 - 4 - 1) * 8) ; ((nbr_param - 4(param_nostack) - 1(func's name)) * 8(byte))
%rep (%0 - 4 - 1) ; Repeat block of code until all element are store in stack
;{
%ifidni %6, ; if (reg)
mov [rsp + (40 + (8 * i))], %6
%elifidni %6, ; if (mem)
;{
mov rax, %6
mov [rsp + (40 + (8 * i))], rax
;}
%elifidni %6, ; if (string)
;{
[section .data]
%%str5: db %6, 0
[section .code]
mov [rsp + (40 + (8 * i))], i64 %%str5
;}
%else ; else (label/nbr)
mov [rsp + (40 + (8 * i))], i64 %6
%endif
%assign i (i + 1) ; Next element of stack: 8 byte
%rotate 1 ; Rotate element right to left for scanning all element parsing in macro.
;}
%endrep
%rotate 1 ; Return to first param
;}
%endif
call %1
;}
add rsp, 40
%if (%0 >= 6) ; func.5th
add rsp, ((%0 - 4) * 8)
%endif
;}
%endmacro
;=============================================================================================.
; / call_win
;=============================================================================================.
*:
%macro memclr 2
;{
;==============================================================================================================.
; Name : memclr (ptr dest, ptr limit) |
; Purpose : Clear all buffer's content untill reach pointer's limit. |
; Input : dest - limit |
; Output : [dest] |
; Destoy : None |
; Data : Stack |
; Define : |
%define STACK_PARAM (2 * E64) ; dest/limit |
%define STACK_REG (2 * E64) + (1 * E8) + (1 * E256) ; rdi/rcx + al + ymm0 |
%define STACK_SIZE (STACK_PARAM + STACK_REG) ;|
; ;|
%define DEST (rsp - STACK_SIZE) + (E64 * 0) ;|
%define LIMIT (rsp - STACK_SIZE) + (E64 * 1) ;|
; ;|
%define REG1 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 0) ;|
%define REG2 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 1) ;|
%define REG3 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 2) + (E8 * 0) ;|
%define REG4 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 2) + (E8 * 1) + (E256 * 0) ;|
;==============================================================================================================.
;{
; Store function's reg in stack
mov [REG1], rdi
mov [REG2], rcx
mov [REG3], al
vmovups [REG4], ymm0
; Store function's param in stack
m2m [DEST ], %1, rdi
m2m [LIMIT], %2, rdi
; Store function's param in function's reg
mov rdi, [DEST]
mov rcx, [LIMIT]
vxorpd ymm0, ymm0, ymm0 ; For white screen
; vpxor ymm0, ymm0, ymm0 ; Need avx2
; vmovups ymm0, [ps_infinit] ; For the fun, look like freak game due to "random" color equal to texture
; Function's core
%push memclr
%ifctx memclr
;{
sub rcx, E256 - 1 ; For data corrupt protect due to avx padding.
;{
%$1:
;{
vmovups [rdi], ymm0
add rdi, E256
;}
jif rdi ,<=, rcx, %$1
;}
add rcx, E256 - 1 ; Restore origin address
; Do 1 byte move loop, for fill end memory
dec rdi ; for avoid to do if(rdi <= rcx) before stosb
xor al, al
%$2:
;{
stosb ; [rdi++] = al
;}
jif rdi ,<=, rcx, %$2
;}
%endif
; Retore function's reg
mov rdi , [REG1]
mov rcx , [REG2]
mov al , [REG3]
vmovups ymm0, [REG4]
;}
;===================================================================================================.
; / memclr |
;===================================================================================================.
;}
%endmacro
%macro memcpy 3
;{
;===================================================================================================.
; Name : memcpy (ptr dest, ptr src, ptr limit) |
; Purpose : Copy content of src into dest, while limit isn't reach. |
; Input : dest - src - limit |
; Output : [dest] |
; Destoy : None |
; Data : Stack |
%define STACK_PARAM (3 * E64) ; dest/src/limit |
%define STACK_REG (3 * E64) + (1 * E256) ; rdi/rsi/rcx + ymm0 |
%define STACK_SIZE (STACK_PARAM + STACK_REG) ;|
; ;|
%define DEST (rsp - STACK_SIZE) + (E64 * 0) ;|
%define SRC (rsp - STACK_SIZE) + (E64 * 1) ;|
%define LIMIT (rsp - STACK_SIZE) + (E64 * 2) ;|
; ;|
%define REG1 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 0) ;|
%define REG2 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 1) ;|
%define REG3 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 2) ;|
%define REG4 (rsp - STACK_SIZE) + STACK_PARAM + (E64 * 3) + (E256 * 0) ;|
;===================================================================================================.
;{
; Store function's reg in stack
mov [REG1], rdi
mov [REG2], rsi
mov [REG3], rcx
vmovups [REG4], ymm0
; Store function's param in stack
m2m [DEST ], %1, rdi
m2m [SRC ], %2, rdi
m2m [LIMIT], %3, rdi
; Store function's param in function's reg
mov rdi, [DEST ]
mov rsi, [SRC ]
mov rcx, [LIMIT]
; Function's core
%push memcpy
%ifctx memcpy
;{
sub rcx, E256 - 1 ; For data corrupt protect due to avx padding.
;{
%$l:
;{
vmovups ymm0, [rsi]
vmovups [rdi], ymm0
add rdi, E256
add rsi, E256
;}
jif rsi ,<=, rcx, %$l
;}
add rcx, E256 - 1 ; Restore origin address
; Do 1 byte move loop, for fill end memory
dec rdi ; for avoid to do if(rdi <= rcx) before stosb
dec rsi ; ...
%$2:
;{
movsb ; [rdi++] = [rsi++]
;}
jif rsi ,<=, rcx, %$2
;}
%endif
; Retore function's reg from stack
mov rdi , [REG1]
mov rsi , [REG2]
mov rcx , [REG3]
vmovups ymm0, [REG4]
;}
;===================================================================================================.
; / memcpy |
;===================================================================================================.
;}
%endmacro
sincosps:
http://pastebin.com/x5XvT7pwI know invoke macro but I prefer to build my own macro for understanding and customize.