added fasm2 as well
This commit is contained in:
54
toolchain/fasm2/include/macro/com32.inc
Normal file
54
toolchain/fasm2/include/macro/com32.inc
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
macro cominvk Object,proc,args&
|
||||
iterate arg, args
|
||||
indx 1+%%-%
|
||||
pushd arg
|
||||
end iterate
|
||||
if ~ defined Object#.com.object
|
||||
err `Object,' is not a COM object'
|
||||
end if
|
||||
mov eax,[Object]
|
||||
push eax
|
||||
mov eax,[eax]
|
||||
call [eax+Object.proc]
|
||||
end macro
|
||||
|
||||
macro comcall handle,Interface,proc,args&
|
||||
iterate arg, args
|
||||
indx 1+%%-%
|
||||
pushd arg
|
||||
end iterate
|
||||
if ~ defined Interface#.com.interface
|
||||
err `Interface,' is not a COM interface'
|
||||
end if
|
||||
match prefix [addr], :handle
|
||||
mov eax,handle
|
||||
push eax
|
||||
mov eax,[eax]
|
||||
else
|
||||
push handle
|
||||
local _handle
|
||||
_handle := handle
|
||||
mov eax,[_handle]
|
||||
end match
|
||||
call [eax+Interface.proc]
|
||||
end macro
|
||||
|
||||
macro interface name,methods&
|
||||
struc name
|
||||
. dd ?
|
||||
virtual at 0
|
||||
iterate method, methods
|
||||
.method dd ?
|
||||
end iterate
|
||||
end virtual
|
||||
.com.object = name.com.interface
|
||||
end struc
|
||||
virtual at 0
|
||||
iterate method, methods
|
||||
name.method dd ?
|
||||
end iterate
|
||||
define name
|
||||
name.com.interface = $ shr 2
|
||||
end virtual
|
||||
end macro
|
51
toolchain/fasm2/include/macro/com64.inc
Normal file
51
toolchain/fasm2/include/macro/com64.inc
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
macro cominvk Object,proc,args&
|
||||
if ~ defined Object#.com.object
|
||||
err `Object,' is not a COM object'
|
||||
end if
|
||||
macro call dummy
|
||||
mov rax,[rcx]
|
||||
Call [rax+Object.proc]
|
||||
end macro
|
||||
match any, args
|
||||
fastcall -,[Object],args
|
||||
else
|
||||
fastcall -,[Object]
|
||||
end match
|
||||
purge call
|
||||
end macro
|
||||
|
||||
macro comcall handle,Interface,proc,args&
|
||||
if ~ defined Interface#.com.interface
|
||||
err `Interface,' is not a COM interface'
|
||||
end if
|
||||
macro call dummy
|
||||
mov rax,[rcx]
|
||||
Call [rax+Interface.proc]
|
||||
end macro
|
||||
match any, args
|
||||
fastcall -,handle,args
|
||||
else
|
||||
fastcall -,handle
|
||||
end match
|
||||
purge call
|
||||
end macro
|
||||
|
||||
macro interface name,methods&
|
||||
struc name
|
||||
. dq ?
|
||||
virtual at 0
|
||||
iterate method, methods
|
||||
.method dq ?
|
||||
end iterate
|
||||
end virtual
|
||||
.com.object = name.com.interface
|
||||
end struc
|
||||
virtual at 0
|
||||
iterate method, methods
|
||||
name.method dq ?
|
||||
end iterate
|
||||
define name
|
||||
name.com.interface = $ shr 3
|
||||
end virtual
|
||||
end macro
|
67
toolchain/fasm2/include/macro/export.inc
Normal file
67
toolchain/fasm2/include/macro/export.inc
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
macro export dllname,exports&
|
||||
iterate <label,string>, exports
|
||||
|
||||
local module,addresses,names,ordinal,count
|
||||
count = %%
|
||||
dd 0,0,0,RVA module,1
|
||||
dd count,count,RVA addresses,RVA names,RVA ordinal
|
||||
addresses:
|
||||
repeat count
|
||||
indx %
|
||||
dd RVA label
|
||||
end repeat
|
||||
names:
|
||||
repeat count
|
||||
dd RVA names.name#%
|
||||
end repeat
|
||||
ordinal:
|
||||
repeat count
|
||||
dw %-1
|
||||
end repeat
|
||||
module db dllname,0
|
||||
repeat count
|
||||
indx %
|
||||
names.name#% db string,0
|
||||
end repeat
|
||||
|
||||
local x,y,z,str1,str2,v1,v2
|
||||
x = count shr 1
|
||||
while x > 0
|
||||
y = x
|
||||
while y < count
|
||||
z = y
|
||||
while z-x >= 0
|
||||
load v1:dword from names+z*4
|
||||
str1 = ($-(RVA $))+v1
|
||||
load v2:dword from names+(z-x)*4
|
||||
str2 = ($-(RVA $))+v2
|
||||
while v1 > 0
|
||||
load v1:byte from str1+%-1
|
||||
load v2:byte from str2+%-1
|
||||
if v1 <> v2
|
||||
break
|
||||
end if
|
||||
end while
|
||||
if v1 < v2
|
||||
load v1:dword from names+z*4
|
||||
load v2:dword from names+(z-x)*4
|
||||
store v1:dword at names+(z-x)*4
|
||||
store v2:dword at names+z*4
|
||||
load v1:word from ordinal+z*2
|
||||
load v2:word from ordinal+(z-x)*2
|
||||
store v1:word at ordinal+(z-x)*2
|
||||
store v2:word at ordinal+z*2
|
||||
else
|
||||
break
|
||||
end if
|
||||
z = z-x
|
||||
end while
|
||||
y = y+1
|
||||
end while
|
||||
x = x shr 1
|
||||
end while
|
||||
|
||||
break
|
||||
end iterate
|
||||
end macro
|
337
toolchain/fasm2/include/macro/if.inc
Normal file
337
toolchain/fasm2/include/macro/if.inc
Normal file
@ -0,0 +1,337 @@
|
||||
|
||||
define _if _if
|
||||
|
||||
define _if..if? _if
|
||||
define _if..else? _else
|
||||
define _if..elseif? _elseif
|
||||
define _if..endif? _endif
|
||||
define _if..while? _while
|
||||
define _if..endw? _endw
|
||||
define _if..repeat? _repeat
|
||||
define _if..until? _until
|
||||
|
||||
calminstruction (cmd) ? &a&
|
||||
transform cmd,_if
|
||||
arrange cmd, cmd a
|
||||
assemble cmd
|
||||
end calminstruction
|
||||
|
||||
macro _if cond
|
||||
__IF equ :
|
||||
local endif
|
||||
__ENDIF equ endif
|
||||
local else
|
||||
__ELSE equ else
|
||||
jcondexpr __ELSE,1,cond
|
||||
end macro
|
||||
|
||||
macro _else
|
||||
jmp __ENDIF
|
||||
match _else, __ELSE
|
||||
_else:
|
||||
end match
|
||||
restore __IF
|
||||
__IF equ
|
||||
end macro
|
||||
|
||||
macro _elseif cond
|
||||
jmp __ENDIF
|
||||
match _else, __ELSE
|
||||
_else:
|
||||
end match
|
||||
restore __ELSE
|
||||
local else
|
||||
__ELSE equ else
|
||||
jcondexpr __ELSE,1,cond
|
||||
end macro
|
||||
|
||||
macro _endif
|
||||
match :_else, __IF __ELSE
|
||||
_else:
|
||||
end match
|
||||
match endif, __ENDIF
|
||||
endif:
|
||||
end match
|
||||
restore __ELSE
|
||||
restore __ENDIF
|
||||
restore __IF
|
||||
end macro
|
||||
|
||||
macro _while cond
|
||||
local while
|
||||
while:
|
||||
__WHILE equ while
|
||||
local endw
|
||||
__ENDW equ endw
|
||||
jcondexpr __ENDW,1,cond
|
||||
end macro
|
||||
|
||||
macro _endw
|
||||
jmp __WHILE
|
||||
match endw, __ENDW
|
||||
endw:
|
||||
end match
|
||||
restore __ENDW
|
||||
restore __WHILE
|
||||
end macro
|
||||
|
||||
macro _repeat
|
||||
local repeat
|
||||
repeat:
|
||||
__REPEAT equ repeat
|
||||
end macro
|
||||
|
||||
macro _until cond
|
||||
jcondexpr __REPEAT,1,cond
|
||||
restore __REPEAT
|
||||
end macro
|
||||
|
||||
macro newlocal? var
|
||||
local new
|
||||
redefine var new
|
||||
end macro
|
||||
|
||||
macro JCONDEXPR?: target,mode,cond
|
||||
local buffer,current,counter
|
||||
local neg,conj
|
||||
local f,t
|
||||
buffer equ cond
|
||||
newlocal f
|
||||
newlocal t
|
||||
while 1
|
||||
match ~x, buffer
|
||||
buffer equ x
|
||||
neg = (mode) xor 1
|
||||
else
|
||||
neg = mode
|
||||
end match
|
||||
|
||||
match (x, buffer
|
||||
counter = 1
|
||||
current equ (
|
||||
buffer equ x
|
||||
while counter > 0
|
||||
match p)s, buffer
|
||||
match (ps, p
|
||||
counter = counter + 1
|
||||
current equ current (
|
||||
buffer equ ps)s
|
||||
else match pp(ps, p
|
||||
counter = counter + 1
|
||||
current equ current pp(
|
||||
buffer equ ps)s
|
||||
else
|
||||
counter = counter - 1
|
||||
current equ current p
|
||||
buffer equ )s
|
||||
end match
|
||||
else
|
||||
current equ current buffer
|
||||
buffer equ
|
||||
break
|
||||
end match
|
||||
end while
|
||||
else
|
||||
current equ
|
||||
end match
|
||||
|
||||
match a|b, buffer
|
||||
match c&d, a
|
||||
current equ current c
|
||||
buffer equ &d|b
|
||||
else
|
||||
current equ current a
|
||||
buffer equ |b
|
||||
end match
|
||||
else match c&d, buffer
|
||||
match a|b, c
|
||||
current equ current a
|
||||
buffer equ |b&d
|
||||
else
|
||||
current equ current c
|
||||
buffer equ &d
|
||||
end match
|
||||
else
|
||||
current equ current buffer
|
||||
buffer equ
|
||||
end match
|
||||
|
||||
match , buffer
|
||||
match (c), current
|
||||
jcondexpr t,neg,c
|
||||
else match c, current
|
||||
jcond t,neg,c
|
||||
end match
|
||||
break
|
||||
else
|
||||
match |b, buffer
|
||||
buffer equ b
|
||||
conj = 0
|
||||
else match &d, buffer
|
||||
buffer equ d
|
||||
conj = 1
|
||||
else
|
||||
err 'invalid expression'
|
||||
end match
|
||||
if (mode) xor conj
|
||||
match (c), current
|
||||
jcondexpr f,neg xor 1,c
|
||||
else match c, current
|
||||
jcond f,neg xor 1,c
|
||||
end match
|
||||
match t,t
|
||||
t:
|
||||
end match
|
||||
newlocal t
|
||||
|
||||
else
|
||||
match (c), current
|
||||
jcondexpr t,neg,c
|
||||
else match c, current
|
||||
jcond t,neg,c
|
||||
end match
|
||||
match f,f
|
||||
f:
|
||||
end match
|
||||
newlocal f
|
||||
end if
|
||||
end match
|
||||
end while
|
||||
match t,t
|
||||
label t at target
|
||||
end match
|
||||
match f,f
|
||||
f:
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro JCOND? target,neg,cond
|
||||
match =signed? v1>==v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jl target
|
||||
else
|
||||
jge target
|
||||
end if
|
||||
else match =signed? v1<==v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jg target
|
||||
else
|
||||
jle target
|
||||
end if
|
||||
else match v1>==v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jb target
|
||||
else
|
||||
jae target
|
||||
end if
|
||||
else match v1<==v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
ja target
|
||||
else
|
||||
jbe target
|
||||
end if
|
||||
else match v1==v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jne target
|
||||
else
|
||||
je target
|
||||
end if
|
||||
else match v1<>v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
je target
|
||||
else
|
||||
jne target
|
||||
end if
|
||||
else match =signed? v1>v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jle target
|
||||
else
|
||||
jg target
|
||||
end if
|
||||
else match =signed? v1<v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jge target
|
||||
else
|
||||
jl target
|
||||
end if
|
||||
else match v1>v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jbe target
|
||||
else
|
||||
ja target
|
||||
end if
|
||||
else match v1<v2, cond
|
||||
cmp v1,v2
|
||||
if neg
|
||||
jae target
|
||||
else
|
||||
jb target
|
||||
end if
|
||||
else match =ZERO=?, cond
|
||||
if neg
|
||||
jnz target
|
||||
else
|
||||
jz target
|
||||
end if
|
||||
else match =CARRY=?, cond
|
||||
if neg
|
||||
jnc target
|
||||
else
|
||||
jc target
|
||||
end if
|
||||
else match =OVERFLOW=?, cond
|
||||
if neg
|
||||
jno target
|
||||
else
|
||||
jo target
|
||||
end if
|
||||
else match =SIGN=?, cond
|
||||
if neg
|
||||
jns target
|
||||
else
|
||||
js target
|
||||
end if
|
||||
else match =PARITY?, cond
|
||||
if neg
|
||||
jnp target
|
||||
else
|
||||
jp target
|
||||
end if
|
||||
else match v, cond
|
||||
x86.parse_operand@aux v
|
||||
if @aux.type = 'imm'
|
||||
if neg
|
||||
if v = 0
|
||||
jmp target
|
||||
end if
|
||||
else
|
||||
if v
|
||||
jmp target
|
||||
end if
|
||||
end if
|
||||
else if @aux.type = 'reg'
|
||||
test v,v
|
||||
if neg
|
||||
jz target
|
||||
else
|
||||
jnz target
|
||||
end if
|
||||
else
|
||||
cmp v,0
|
||||
if neg
|
||||
je target
|
||||
else
|
||||
jne target
|
||||
end if
|
||||
end if
|
||||
end match
|
||||
end macro
|
59
toolchain/fasm2/include/macro/import32.inc
Normal file
59
toolchain/fasm2/include/macro/import32.inc
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 4
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dd RVA name.label
|
||||
else
|
||||
dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dd 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dd RVA name.label
|
||||
else
|
||||
label dd 80000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dd 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
59
toolchain/fasm2/include/macro/import64.inc
Normal file
59
toolchain/fasm2/include/macro/import64.inc
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
macro library? definitions&
|
||||
PE.Imports:
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
dd RVA name.lookup,0,0,RVA name.str,RVA name.address
|
||||
end if
|
||||
name.referred = 1
|
||||
end iterate
|
||||
dd 0,0,0,0,0
|
||||
iterate <name,string>, definitions
|
||||
if ~ name.redundant
|
||||
name.str db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro import? name,definitions&
|
||||
align 8
|
||||
if defined name.referred
|
||||
name.lookup:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
dq RVA name.label
|
||||
else
|
||||
dq 8000000000000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if $ > name.lookup
|
||||
name.redundant = 0
|
||||
dq 0
|
||||
else
|
||||
name.redundant = 1
|
||||
end if
|
||||
name.address:
|
||||
iterate <label,string>, definitions
|
||||
if used label
|
||||
if string eqtype ''
|
||||
label dq RVA name.label
|
||||
else
|
||||
label dq 8000000000000000h + string
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
if ~ name.redundant
|
||||
dq 0
|
||||
end if
|
||||
iterate <label,string>, definitions
|
||||
if used label & string eqtype ''
|
||||
name.label dw 0
|
||||
db string,0
|
||||
align 2
|
||||
end if
|
||||
end iterate
|
||||
end if
|
||||
end macro
|
88
toolchain/fasm2/include/macro/inline.inc
Normal file
88
toolchain/fasm2/include/macro/inline.inc
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
; Simple preprocessor for inline macros.
|
||||
|
||||
; Example of use:
|
||||
;
|
||||
; inlinemacro oddflip(number)
|
||||
; return = (number) xor 1
|
||||
; end inlinemacro
|
||||
;
|
||||
; db oddflip(3), oddflip(oddflip(0) shl 1)
|
||||
|
||||
; Any kind of definition of an expression-class symbol may be used for the return value.
|
||||
|
||||
include 'xcalm.inc'
|
||||
|
||||
define inlinemacro? inlinemacro?
|
||||
|
||||
inlinemacro... = 0
|
||||
|
||||
calminstruction inlinemacro?! &declaration&
|
||||
local name
|
||||
match name(arguments?), declaration
|
||||
jyes define
|
||||
match name= arguments?, declaration
|
||||
jyes define
|
||||
match name arguments?, declaration
|
||||
define:
|
||||
arrange tmp, =__inline__.name
|
||||
arrange name, =inlinemacro.name
|
||||
publish name, tmp
|
||||
arrange tmp, =struc (=return?) name arguments
|
||||
assemble tmp
|
||||
end calminstruction
|
||||
|
||||
calminstruction end?.inlinemacro?!
|
||||
asm end struc
|
||||
check inlinemacro...
|
||||
jyes done
|
||||
compute inlinemacro..., 1
|
||||
asm inlinemacro?.enable?
|
||||
done:
|
||||
end calminstruction
|
||||
|
||||
macro inlinemacro?.enable? chain
|
||||
chain
|
||||
macro include?! file*, head
|
||||
include file, inlinemacro.enable head
|
||||
purge ?, include?
|
||||
end macro
|
||||
calminstruction ?! &text&
|
||||
local head, tail, name, arguments, more, i
|
||||
init i, 0
|
||||
match =inlinemacro? more, text
|
||||
jyes ready
|
||||
transform text, inlinemacro
|
||||
jno ready
|
||||
match =else? more, text
|
||||
jno preprocess
|
||||
compute i, i+1
|
||||
arrange text, =__inline__.?(=else =if 1) =__inline__.?(=__return__.i==1) text =__inline__.?(=end =if) =__inline__.?(=if ~=definite =__return__.i)
|
||||
preprocess:
|
||||
match head? =__inline__.name tail?, text
|
||||
jno ready
|
||||
match (arguments?) tail?, tail, ()
|
||||
jyes inline
|
||||
arrange text, head name tail
|
||||
jump preprocess
|
||||
inline:
|
||||
match ?, name
|
||||
jyes special
|
||||
local tmp, return
|
||||
compute i, i+1
|
||||
arrange return, =__return__.i
|
||||
arrange tmp, return =inlinemacro.name arguments
|
||||
arrange text, head return tail
|
||||
take text, tmp
|
||||
jump preprocess
|
||||
special:
|
||||
arrange text, head tail
|
||||
take text, arguments
|
||||
jump preprocess
|
||||
ready:
|
||||
assemble text
|
||||
take , text
|
||||
take text, text
|
||||
jyes preprocess
|
||||
end calminstruction
|
||||
end macro
|
395
toolchain/fasm2/include/macro/proc32.inc
Normal file
395
toolchain/fasm2/include/macro/proc32.inc
Normal file
@ -0,0 +1,395 @@
|
||||
|
||||
define stdcall? stdcall
|
||||
|
||||
macro stdcall?.push_string value&
|
||||
local continue
|
||||
if sizeof.TCHAR > 1
|
||||
local alignment
|
||||
virtual at $+5
|
||||
align sizeof.TCHAR
|
||||
alignment = $-$$
|
||||
end virtual
|
||||
db alignment dup 90h
|
||||
end if
|
||||
call continue
|
||||
TCHAR value,0
|
||||
continue:
|
||||
end macro
|
||||
|
||||
macro stdcall?: proc*,args&
|
||||
local count
|
||||
count = 0
|
||||
iterate arg, args
|
||||
indx 1+%%-%
|
||||
match =addr? val, arg
|
||||
if val relativeto 0 | val relativeto $
|
||||
push dword val
|
||||
else
|
||||
lea edx,[val]
|
||||
push edx
|
||||
end if
|
||||
else match =double? [var], arg
|
||||
push dword [var+4]
|
||||
push dword [var]
|
||||
count = count + 1
|
||||
else match =double? val, arg
|
||||
local low,high
|
||||
virtual at 0
|
||||
dq val
|
||||
load low:dword from 0
|
||||
load high:dword from 4
|
||||
end virtual
|
||||
push dword high
|
||||
push dword low
|
||||
count = count + 1
|
||||
else match =invoke? func, arg
|
||||
invoke func
|
||||
push eax
|
||||
else match =cinvoke? func, arg
|
||||
cinvoke func
|
||||
push eax
|
||||
else match =stdcall? func, arg
|
||||
stdcall func
|
||||
push eax
|
||||
else match =ccall? func, arg
|
||||
ccall func
|
||||
push eax
|
||||
else match first=,rest, arg
|
||||
stdcall?.push_string arg
|
||||
else match size [var], arg
|
||||
if size = 4
|
||||
push arg
|
||||
else
|
||||
if size = 1
|
||||
mov al, arg
|
||||
else if size = 2
|
||||
mov ax, arg
|
||||
else
|
||||
mov eax, arg
|
||||
end if
|
||||
push eax
|
||||
end if
|
||||
else match [var], arg
|
||||
push dword arg
|
||||
else
|
||||
if arg eqtype ''
|
||||
stdcall?.push_string arg
|
||||
else
|
||||
push dword arg
|
||||
end if
|
||||
end match
|
||||
count = count + 1
|
||||
end iterate
|
||||
pcountcheck proc,count
|
||||
call proc
|
||||
end macro
|
||||
|
||||
macro ccall?: proc*,args&
|
||||
local count
|
||||
count = 0
|
||||
iterate arg, args
|
||||
indx 1+%%-%
|
||||
match =addr? val, arg
|
||||
if val relativeto 0 | val relativeto $
|
||||
push dword val
|
||||
else
|
||||
lea edx,[val]
|
||||
push edx
|
||||
end if
|
||||
else match =double? [var], arg
|
||||
push dword [var+4]
|
||||
push dword [var]
|
||||
count = count + 1
|
||||
else match =double? val, arg
|
||||
local low,high
|
||||
virtual at 0
|
||||
dq val
|
||||
load low:dword from 0
|
||||
load high:dword from 4
|
||||
end virtual
|
||||
push dword high
|
||||
push dword low
|
||||
count = count + 1
|
||||
else match =invoke? func, arg
|
||||
invoke func
|
||||
push eax
|
||||
else match =cinvoke? func, arg
|
||||
cinvoke func
|
||||
push eax
|
||||
else match =stdcall? func, arg
|
||||
stdcall func
|
||||
push eax
|
||||
else match =ccall? func, arg
|
||||
ccall func
|
||||
push eax
|
||||
else match first=,rest, arg
|
||||
stdcall?.push_string arg
|
||||
else match size [var], arg
|
||||
if size = 4
|
||||
push arg
|
||||
else
|
||||
if size = 1
|
||||
mov al, arg
|
||||
else if size = 2
|
||||
mov ax, arg
|
||||
else
|
||||
mov eax, arg
|
||||
end if
|
||||
push eax
|
||||
end if
|
||||
else match [var], arg
|
||||
push dword arg
|
||||
else
|
||||
if arg eqtype ''
|
||||
stdcall?.push_string arg
|
||||
else
|
||||
push dword arg
|
||||
end if
|
||||
end match
|
||||
count = count + 1
|
||||
end iterate
|
||||
pcountcheck proc,count
|
||||
call proc
|
||||
if count
|
||||
add esp,count*4
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro invoke?: proc*,args&
|
||||
stdcall [proc],args
|
||||
end macro
|
||||
|
||||
macro cinvoke?: proc*,args&
|
||||
ccall [proc],args
|
||||
end macro
|
||||
|
||||
macro pcountcheck? proc*,args*
|
||||
end macro
|
||||
|
||||
define pcountsuffix %
|
||||
|
||||
prologue@proc equ prologuedef
|
||||
|
||||
macro prologuedef procname,flag,parmbytes,localbytes,reglist
|
||||
local loc
|
||||
loc = (localbytes+3) and (not 3)
|
||||
parmbase@proc equ ebp+8
|
||||
localbase@proc equ ebp-loc
|
||||
if parmbytes | localbytes
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
if localbytes
|
||||
sub esp,loc
|
||||
end if
|
||||
end if
|
||||
iterate reg, reglist
|
||||
push reg
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
epilogue@proc equ epiloguedef
|
||||
|
||||
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
|
||||
iterate reg, reglist
|
||||
indx %%-%+1
|
||||
pop reg
|
||||
end iterate
|
||||
if parmbytes | localbytes
|
||||
leave
|
||||
end if
|
||||
if flag and 10000b
|
||||
retn
|
||||
else
|
||||
retn parmbytes
|
||||
end if
|
||||
end macro
|
||||
|
||||
close@proc equ
|
||||
|
||||
macro proc? statement&
|
||||
|
||||
local _local,params,flag,regs,parmbytes,localbytes,current,tmp,initlocal
|
||||
|
||||
macro endp?!
|
||||
|
||||
localbytes = current
|
||||
|
||||
purge ret?,locals?,endl?,proclocal?
|
||||
|
||||
match close:reglist, close@proc,<regs>
|
||||
close name,flag,parmbytes,localbytes,reglist
|
||||
end match
|
||||
|
||||
end match
|
||||
end namespace
|
||||
end if
|
||||
end match
|
||||
|
||||
purge endp?
|
||||
|
||||
end macro
|
||||
|
||||
match name declaration, statement :
|
||||
if used name
|
||||
name:
|
||||
namespace name
|
||||
outscope match local?, proclocal
|
||||
|
||||
match =stdcall? args :, declaration
|
||||
define params args
|
||||
flag = 11b
|
||||
else match =stdcall? :, declaration
|
||||
define params
|
||||
flag = 11b
|
||||
else match =c? args :, declaration
|
||||
define params args
|
||||
flag = 10001b
|
||||
else match =c? :, declaration
|
||||
define params
|
||||
flag = 10001b
|
||||
else match args :, declaration
|
||||
define params args
|
||||
flag = 0
|
||||
else
|
||||
define params
|
||||
flag = 0
|
||||
end match
|
||||
define regs
|
||||
match =uses? list, params
|
||||
define params list
|
||||
while 1
|
||||
match =, tail, params
|
||||
define params tail
|
||||
break
|
||||
else match reg tail, params&
|
||||
match more&, tail
|
||||
define params more
|
||||
else
|
||||
define params
|
||||
end match
|
||||
if % = 1
|
||||
regs equ reg
|
||||
else
|
||||
regs equ regs,reg
|
||||
end if
|
||||
else
|
||||
break
|
||||
end match
|
||||
end while
|
||||
else match =, tail, params
|
||||
define params tail
|
||||
end match
|
||||
|
||||
match prologue:reglist, prologue@proc:<regs>
|
||||
prologue name,flags,parmbytes,localbytes,reglist
|
||||
end match
|
||||
|
||||
virtual at parmbase@proc
|
||||
namespace name
|
||||
match args, params
|
||||
iterate arg, args
|
||||
match argname:type, arg
|
||||
label argname:type
|
||||
rb type
|
||||
else
|
||||
?arg dd ?
|
||||
end match
|
||||
end iterate
|
||||
end match
|
||||
parmbytes := $-(parmbase@proc)
|
||||
match p, pcountsuffix
|
||||
name#p = parmbytes/4
|
||||
end match
|
||||
end namespace
|
||||
end virtual
|
||||
|
||||
macro ret? operand
|
||||
match any, operand
|
||||
retn operand
|
||||
else
|
||||
match epilogue:reglist, epilogue@proc:<regs>
|
||||
epilogue name,flag,parmbytes,localbytes,reglist
|
||||
end match
|
||||
end match
|
||||
end macro
|
||||
|
||||
current = 0
|
||||
|
||||
macro initlocal
|
||||
local area,pointer,length,value
|
||||
area::
|
||||
pointer = localbase@proc+current
|
||||
length = $@ - (localbase@proc) - current
|
||||
current = $ - (localbase@proc)
|
||||
end virtual
|
||||
while length > 0
|
||||
if length < 2
|
||||
load value:byte from area:pointer
|
||||
mov byte [pointer],value
|
||||
pointer = pointer + 1
|
||||
length = length - 1
|
||||
else if length < 4
|
||||
load value:word from area:pointer
|
||||
mov word [pointer],value
|
||||
pointer = pointer + 2
|
||||
length = length - 2
|
||||
else
|
||||
load value:dword from area:pointer
|
||||
mov dword [pointer],value
|
||||
pointer = pointer + 4
|
||||
length = length - 4
|
||||
end if
|
||||
end while
|
||||
virtual at localbase@proc+current
|
||||
end macro
|
||||
|
||||
macro locals?
|
||||
virtual at localbase@proc+current
|
||||
iterate dword, dword,qword
|
||||
macro dword? value
|
||||
if value relativeto 0
|
||||
emit dword: value
|
||||
else
|
||||
initlocal
|
||||
local pointer
|
||||
pointer := $
|
||||
end virtual
|
||||
mov dword [pointer],value
|
||||
virtual at pointer+4
|
||||
current = $ - (localbase@proc)
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
macro ? line&
|
||||
line
|
||||
if $ > $@
|
||||
initlocal
|
||||
end if
|
||||
end macro
|
||||
end macro
|
||||
|
||||
macro endl?
|
||||
purge ?, dword?,qword?
|
||||
initlocal
|
||||
end virtual
|
||||
end macro
|
||||
|
||||
macro proclocal? args&
|
||||
locals
|
||||
iterate arg, args
|
||||
match varname[count]:type, arg
|
||||
?varname dbx type:count dup ?
|
||||
else match varname:type, arg
|
||||
?varname dbx type, ?
|
||||
else match varname[count], arg
|
||||
?varname rd count
|
||||
else match varname type, arg
|
||||
?varname type
|
||||
else
|
||||
?arg dd ?
|
||||
end match
|
||||
end iterate
|
||||
endl
|
||||
end macro
|
||||
|
||||
end macro
|
491
toolchain/fasm2/include/macro/proc64.inc
Normal file
491
toolchain/fasm2/include/macro/proc64.inc
Normal file
@ -0,0 +1,491 @@
|
||||
define fastcall? fastcall
|
||||
|
||||
fastcall.r1 equ rcx
|
||||
fastcall.rd1 equ ecx
|
||||
fastcall.rw1 equ cx
|
||||
fastcall.rb1 equ cl
|
||||
fastcall.rf1 equ xmm0
|
||||
|
||||
fastcall.r2 equ rdx
|
||||
fastcall.rd2 equ edx
|
||||
fastcall.rw2 equ dx
|
||||
fastcall.rb2 equ dl
|
||||
fastcall.rf2 equ xmm1
|
||||
|
||||
fastcall.r3 equ r8
|
||||
fastcall.rd3 equ r8d
|
||||
fastcall.rw3 equ r8w
|
||||
fastcall.rb3 equ r8b
|
||||
fastcall.rf3 equ xmm2
|
||||
|
||||
fastcall.r4 equ r9
|
||||
fastcall.rd4 equ r9d
|
||||
fastcall.rw4 equ r9w
|
||||
fastcall.rb4 equ r9b
|
||||
fastcall.rf4 equ xmm3
|
||||
|
||||
fastcall?.frame = -1
|
||||
|
||||
macro frame?
|
||||
local size
|
||||
define fastcall?.frame_size size
|
||||
fastcall?.frame =: 0
|
||||
sub rsp,size
|
||||
end macro
|
||||
|
||||
macro end?.frame?
|
||||
match size, fastcall?.frame_size
|
||||
size := fastcall?.frame
|
||||
add rsp,size
|
||||
end match
|
||||
restore fastcall?.frame,fastcall?.frame_size
|
||||
end macro
|
||||
|
||||
macro endf?
|
||||
end frame
|
||||
end macro
|
||||
|
||||
macro fastcall?.inline_string var
|
||||
local data,continue
|
||||
jmp continue
|
||||
if sizeof.TCHAR > 1
|
||||
align sizeof.TCHAR,90h
|
||||
end if
|
||||
match value, var
|
||||
data TCHAR value,0
|
||||
end match
|
||||
redefine var data
|
||||
continue:
|
||||
end macro
|
||||
|
||||
macro fastcall?: proc*,args&
|
||||
local offset,framesize,type,value
|
||||
if framesize & fastcall?.frame < 0
|
||||
sub rsp,framesize
|
||||
end if
|
||||
offset = 0
|
||||
local nest,called
|
||||
called = 0
|
||||
iterate arg, args
|
||||
nest = 0
|
||||
match =invoke? func, arg
|
||||
nest = %
|
||||
else match =fastcall? func, arg
|
||||
nest = %
|
||||
end match
|
||||
if nest
|
||||
if called
|
||||
mov [rsp+8*(called-1)],rax
|
||||
end if
|
||||
frame
|
||||
arg
|
||||
end frame
|
||||
called = nest
|
||||
end if
|
||||
end iterate
|
||||
iterate arg, args
|
||||
match =float? val, arg
|
||||
type = 'f'
|
||||
value reequ val
|
||||
SSE.parse_operand@src val
|
||||
else match =addr? val, arg
|
||||
type = 'a'
|
||||
value reequ val
|
||||
x86.parse_operand@src [val]
|
||||
else match =invoke? func, arg
|
||||
if called = %
|
||||
type = 0
|
||||
value reequ rax
|
||||
x86.parse_operand@src rax
|
||||
else
|
||||
type = 'r'
|
||||
end if
|
||||
else match =fastcall? func, arg
|
||||
if called = %
|
||||
type = 0
|
||||
value reequ rax
|
||||
x86.parse_operand@src rax
|
||||
else
|
||||
type = 'r'
|
||||
end if
|
||||
else match first=,rest, arg
|
||||
type = 's'
|
||||
value reequ arg
|
||||
else
|
||||
type = 0
|
||||
value reequ arg
|
||||
SSE.parse_operand@src arg
|
||||
if @src.type = 'imm' & @src.size = 0
|
||||
if value eqtype ''
|
||||
type = 's'
|
||||
end if
|
||||
end if
|
||||
end match
|
||||
if type = 's'
|
||||
fastcall.inline_string value
|
||||
type = 'a'
|
||||
end if
|
||||
if % < 5
|
||||
if type = 'f'
|
||||
if @src.size = 8 | ~ @src.size | @src.type = 'mmreg'
|
||||
if @src.type = 'imm'
|
||||
mov rax,value
|
||||
movq fastcall.rf#%,rax
|
||||
else
|
||||
movq fastcall.rf#%,value
|
||||
end if
|
||||
else if @src.size = 4
|
||||
if @src.type = 'imm'
|
||||
mov eax,value
|
||||
movd fastcall.rf#%,eax
|
||||
else
|
||||
movd fastcall.rf#%,value
|
||||
end if
|
||||
else
|
||||
err 'invalid argument ',`arg
|
||||
end if
|
||||
else
|
||||
if type = 'a'
|
||||
lea fastcall.r#%,[value]
|
||||
else
|
||||
if type = 'r'
|
||||
@src.size = 8
|
||||
@src.type = 'mem'
|
||||
value equ [rsp+8*(%-1)]
|
||||
end if
|
||||
if @src.size = 8 | ~ @src.size
|
||||
if @src.type <> 'reg' | ~ @src.imm eq fastcall.r#%
|
||||
mov fastcall.r#%,value
|
||||
end if
|
||||
else if @src.size = 4
|
||||
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rd#%
|
||||
mov fastcall.rd#%,value
|
||||
end if
|
||||
else if @src.size = 2
|
||||
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rw#%
|
||||
mov fastcall.rw#%,value
|
||||
end if
|
||||
else if @src.size = 1
|
||||
if @src.type <> 'reg' | ~ @src.imm eq fastcall.rb#%
|
||||
mov fastcall.rb#%,value
|
||||
end if
|
||||
else
|
||||
err 'invalid argument ',`arg
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
else
|
||||
if type = 'r'
|
||||
; already on stack
|
||||
else if @src.type = 'reg'
|
||||
mov [rsp+offset],value
|
||||
else if @src.type = 'mem'
|
||||
if type = 'a'
|
||||
lea rax,[value]
|
||||
mov [rsp+offset],rax
|
||||
else
|
||||
if @src.size = 8 | ~ @src.size
|
||||
mov rax,value
|
||||
mov [rsp+offset],rax
|
||||
else if @src.size = 4
|
||||
mov eax,value
|
||||
mov [rsp+offset],eax
|
||||
else if @src.size = 2
|
||||
mov ax,value
|
||||
mov [rsp+offset],ax
|
||||
else if @src.size = 1
|
||||
mov al,value
|
||||
mov [rsp+offset],al
|
||||
else
|
||||
err 'invalid argument ',`arg
|
||||
end if
|
||||
end if
|
||||
else if @src.type = 'imm'
|
||||
if @src.size = 8 | ~ @src.size
|
||||
if (value) relativeto 0 & (value) - 1 shl 64 >= -80000000h & (value) < 1 shl 64
|
||||
mov rax,(value) - 1 shl 64
|
||||
mov [rsp+offset],rax
|
||||
else if (value) relativeto 0 & ( (value) >= 80000000h | (value) < -80000000h )
|
||||
mov rax,value
|
||||
mov [rsp+offset],rax
|
||||
else
|
||||
mov qword [rsp+offset],value
|
||||
end if
|
||||
else if @src.size = 4
|
||||
mov dword [rsp+offset],value
|
||||
else if @src.size = 2
|
||||
mov word [rsp+offset],value
|
||||
else if @src.size = 1
|
||||
mov byte [rsp+offset],value
|
||||
else
|
||||
err 'invalid argument ',`arg
|
||||
end if
|
||||
else if type = 'f' & @src.type = 'mmreg' & @src.size = 16
|
||||
movq [rsp+offset],value
|
||||
else
|
||||
err 'invalid argument ',`arg
|
||||
end if
|
||||
end if
|
||||
offset = offset + 8
|
||||
end iterate
|
||||
pcountcheck proc,offset/8
|
||||
if offset < 20h
|
||||
offset = 20h
|
||||
end if
|
||||
framesize = offset + offset and 8
|
||||
call proc
|
||||
if framesize & fastcall?.frame < 0
|
||||
add rsp,framesize
|
||||
else if fastcall?.frame >= 0 & framesize > fastcall?.frame
|
||||
fastcall?.frame = framesize
|
||||
end if
|
||||
end macro
|
||||
|
||||
macro invoke?: proc*,args&
|
||||
fastcall [proc],args
|
||||
end macro
|
||||
|
||||
macro cinvoke?: proc*,args&
|
||||
fastcall [proc],args
|
||||
end macro
|
||||
|
||||
macro pcountcheck? proc*,args*
|
||||
end macro
|
||||
|
||||
define pcountsuffix %
|
||||
|
||||
prologue@proc equ prologuedef
|
||||
|
||||
macro prologuedef procname,flag,parmbytes,localbytes,reglist
|
||||
local loc,fill
|
||||
loc = (localbytes+15) and (not 15)
|
||||
parmbase@proc equ rbp+16
|
||||
localbase@proc equ rbp-loc
|
||||
push rbp
|
||||
mov rbp,rsp
|
||||
if loc+fill
|
||||
sub rsp,loc+fill
|
||||
end if
|
||||
match any, reglist
|
||||
iterate reg, reglist
|
||||
push reg
|
||||
if % = %%
|
||||
fill := 8*(% and 1)
|
||||
end if
|
||||
end iterate
|
||||
else
|
||||
fill := 0
|
||||
end match
|
||||
end macro
|
||||
|
||||
epilogue@proc equ epiloguedef
|
||||
|
||||
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
|
||||
iterate reg, reglist
|
||||
indx %%-%+1
|
||||
pop reg
|
||||
end iterate
|
||||
leave
|
||||
retn
|
||||
end macro
|
||||
|
||||
close@proc equ
|
||||
|
||||
macro proc? statement&
|
||||
|
||||
local _local,params,flag,regs,parmbytes,localbytes,current,tmp,initlocal
|
||||
|
||||
macro endp?!
|
||||
|
||||
localbytes = current
|
||||
|
||||
purge ret?,locals?,endl?,proclocal?
|
||||
|
||||
match close:reglist, close@proc,<regs>
|
||||
close name,flag,parmbytes,localbytes,reglist
|
||||
end match
|
||||
|
||||
end match
|
||||
end namespace
|
||||
end if
|
||||
end match
|
||||
|
||||
purge endp?
|
||||
|
||||
end macro
|
||||
|
||||
match name declaration, statement :
|
||||
if used name
|
||||
name:
|
||||
namespace name
|
||||
outscope match local?, proclocal
|
||||
|
||||
match =stdcall? args :, declaration
|
||||
define params args
|
||||
flag = 11b
|
||||
else match =stdcall? :, declaration
|
||||
define params
|
||||
flag = 11b
|
||||
else match =c? args :, declaration
|
||||
define params args
|
||||
flag = 10001b
|
||||
else match =c? :, declaration
|
||||
define params
|
||||
flag = 10001b
|
||||
else match args :, declaration
|
||||
define params args
|
||||
flag = 0
|
||||
else
|
||||
define params
|
||||
flag = 0
|
||||
end match
|
||||
define regs
|
||||
match =uses? list, params
|
||||
define params list
|
||||
while 1
|
||||
match =, tail, params
|
||||
define params tail
|
||||
break
|
||||
else match reg tail, params&
|
||||
match more&, tail
|
||||
define params more
|
||||
else
|
||||
define params
|
||||
end match
|
||||
if % = 1
|
||||
regs equ reg
|
||||
else
|
||||
regs equ regs,reg
|
||||
end if
|
||||
else
|
||||
break
|
||||
end match
|
||||
end while
|
||||
else match =, tail, params
|
||||
define params tail
|
||||
end match
|
||||
|
||||
match prologue:reglist, prologue@proc:<regs>
|
||||
prologue name,flags,parmbytes,localbytes,reglist
|
||||
end match
|
||||
|
||||
virtual at parmbase@proc
|
||||
namespace name
|
||||
match args, params
|
||||
iterate arg, args
|
||||
match argname:type, arg
|
||||
label argname:type
|
||||
rb type
|
||||
else
|
||||
?arg dq ?
|
||||
end match
|
||||
end iterate
|
||||
end match
|
||||
parmbytes := $-(parmbase@proc)
|
||||
match p, pcountsuffix
|
||||
name#p = parmbytes/8
|
||||
end match
|
||||
end namespace
|
||||
end virtual
|
||||
|
||||
macro ret? operand
|
||||
match any, operand
|
||||
retn operand
|
||||
else
|
||||
match epilogue:reglist, epilogue@proc:<regs>
|
||||
epilogue name,flag,parmbytes,localbytes,reglist
|
||||
end match
|
||||
end match
|
||||
end macro
|
||||
|
||||
current = 0
|
||||
|
||||
macro initlocal
|
||||
local area,pointer,length,value
|
||||
area::
|
||||
pointer = localbase@proc+current
|
||||
length = $@ - (localbase@proc) - current
|
||||
current = $ - (localbase@proc)
|
||||
end virtual
|
||||
while length > 0
|
||||
if length < 2
|
||||
load value:byte from area:pointer
|
||||
mov byte [pointer],value
|
||||
pointer = pointer + 1
|
||||
length = length - 1
|
||||
else if length < 4
|
||||
load value:word from area:pointer
|
||||
mov word [pointer],value
|
||||
pointer = pointer + 2
|
||||
length = length - 2
|
||||
else if length < 8
|
||||
load value:dword from area:pointer
|
||||
mov dword [pointer],value
|
||||
pointer = pointer + 4
|
||||
length = length - 4
|
||||
else
|
||||
load value:qword from area:pointer
|
||||
if value < 80000000h | value >= 1 shl 64 - 80000000h
|
||||
mov qword [pointer],value
|
||||
pointer = pointer + 8
|
||||
length = length - 8
|
||||
else
|
||||
mov dword [pointer],value and 0FFFFFFFFh
|
||||
pointer = pointer + 4
|
||||
length = length - 4
|
||||
end if
|
||||
end if
|
||||
end while
|
||||
virtual at localbase@proc+current
|
||||
end macro
|
||||
|
||||
macro locals?
|
||||
virtual at localbase@proc+current
|
||||
iterate dword, dword,qword
|
||||
macro dword? value
|
||||
if value relativeto 0
|
||||
emit dword: value
|
||||
else
|
||||
initlocal
|
||||
local pointer
|
||||
pointer := $
|
||||
end virtual
|
||||
mov dword [pointer],value
|
||||
virtual at pointer+4
|
||||
current = $ - (localbase@proc)
|
||||
end if
|
||||
end macro
|
||||
end iterate
|
||||
macro ? line&
|
||||
line
|
||||
if $ > $@
|
||||
initlocal
|
||||
end if
|
||||
end macro
|
||||
end macro
|
||||
|
||||
macro endl?
|
||||
purge ?, dword?,qword?
|
||||
initlocal
|
||||
end virtual
|
||||
end macro
|
||||
|
||||
macro proclocal? args&
|
||||
locals
|
||||
iterate arg, args
|
||||
match varname[count]:type, arg
|
||||
?varname dbx type:count dup ?
|
||||
else match varname:type, arg
|
||||
?varname dbx type, ?
|
||||
else match varname[count], arg
|
||||
?varname rq count
|
||||
else match varname type, arg
|
||||
?varname type
|
||||
else
|
||||
?arg dq ?
|
||||
end match
|
||||
end iterate
|
||||
endl
|
||||
end macro
|
||||
|
||||
end macro
|
314
toolchain/fasm2/include/macro/resource.inc
Normal file
314
toolchain/fasm2/include/macro/resource.inc
Normal file
@ -0,0 +1,314 @@
|
||||
|
||||
macro directory definitions&
|
||||
iterate <type,label>, definitions
|
||||
root@resource dd 0,%t,0,%% shl 16
|
||||
local total,current,next
|
||||
total = %%
|
||||
current = -1
|
||||
next = 0
|
||||
while current < next
|
||||
current = next
|
||||
repeat total
|
||||
indx %
|
||||
if type = current
|
||||
dd type,80000000h+label-root@resource
|
||||
else if type > current & ( next = current | next > type )
|
||||
next = type
|
||||
end if
|
||||
end repeat
|
||||
end while
|
||||
break
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro resource dir,definitions&
|
||||
iterate <id,lang,label>, definitions
|
||||
dir dd 0,%t,0,%% shl 16
|
||||
local total,current,next,counter
|
||||
total = %%
|
||||
current = -1
|
||||
next = 0
|
||||
while current < next
|
||||
current = next
|
||||
counter = 0
|
||||
repeat total
|
||||
indx %
|
||||
if id = current
|
||||
if counter = 0
|
||||
dd id,80000000h+label.directory-root@resource
|
||||
end if
|
||||
counter = counter + 1
|
||||
label.count = counter
|
||||
else if id > current & ( next = current | next > id )
|
||||
next = id
|
||||
end if
|
||||
end repeat
|
||||
end while
|
||||
current = -1
|
||||
next = 0
|
||||
while current < next
|
||||
current = next
|
||||
counter = 0
|
||||
repeat total
|
||||
indx %
|
||||
if id = current
|
||||
if counter = 0
|
||||
label.directory dd 0,%t,0,label.count shl 16
|
||||
dd lang,label-root@resource
|
||||
label.resid = id
|
||||
else
|
||||
dd lang,label-root@resource
|
||||
end if
|
||||
counter = counter + 1
|
||||
else if id > current & ( next = current | next > id )
|
||||
next = id
|
||||
end if
|
||||
end repeat
|
||||
end while
|
||||
break
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro bitmap label,bitmap_file
|
||||
local data,size
|
||||
label dd RVA data,size,0,0
|
||||
data file bitmap_file:0Eh
|
||||
size = $ - data
|
||||
align 4
|
||||
end macro
|
||||
|
||||
macro icon group,definitions&
|
||||
local data,size,position,header
|
||||
iterate <label,icon_file>, definitions
|
||||
virtual at 0
|
||||
file icon_file:6,16
|
||||
load size:dword from 8
|
||||
load position:dword from 12
|
||||
end virtual
|
||||
label dd RVA data#%,size,0,0
|
||||
data#% file icon_file:position,size
|
||||
if % = %%
|
||||
align 4
|
||||
group dd RVA header,6+%%*14,0,0
|
||||
header dw 0,1,%%
|
||||
repeat %%
|
||||
indx %
|
||||
file icon_file:6,12
|
||||
dw label.resid
|
||||
end repeat
|
||||
align 4
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro cursor group,definitions&
|
||||
local data,header
|
||||
iterate <label,cursor_file>, definitions
|
||||
virtual at 0
|
||||
file cursor_file:6,16
|
||||
load label.width:byte from 0
|
||||
load label.height:byte from 1
|
||||
load label.size:dword from 8
|
||||
load label.position:dword from 12
|
||||
end virtual
|
||||
label dd RVA data#%,label.size+4,0,0
|
||||
data#% file cursor_file:10,4
|
||||
file cursor_file:label.position,label.size
|
||||
if % = %%
|
||||
align 4
|
||||
group dd RVA header,6+%%*14,0,0
|
||||
header dw 0,2,%%
|
||||
repeat %%
|
||||
indx %
|
||||
dw label.width,label.height,1,0
|
||||
dd label.size+4
|
||||
dw label.resid
|
||||
end repeat
|
||||
align 4
|
||||
end if
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro menu label
|
||||
local data,size
|
||||
label dd RVA data,size,0,0
|
||||
data dw 1,4,0,0
|
||||
local menu_level
|
||||
menu_level = 1
|
||||
macro menuitem string,id,resinfo:0,status:0,type:0
|
||||
dd MFT_STRING or type,status,id
|
||||
dw resinfo
|
||||
du string,0
|
||||
align 4
|
||||
if resinfo and MFR_END
|
||||
menu_level = menu_level - 1
|
||||
end if
|
||||
if resinfo and MFR_POPUP
|
||||
menu_level = menu_level + 1
|
||||
dd 0
|
||||
end if
|
||||
if menu_level = 0
|
||||
size = $ - data
|
||||
purge menuitem,menuseparator
|
||||
end if
|
||||
end macro
|
||||
macro menuseparator resinfo:0
|
||||
dd MFT_SEPARATOR,0,0
|
||||
dw resinfo,0
|
||||
if resinfo and MFR_END
|
||||
menu_level = menu_level - 1
|
||||
end if
|
||||
if menu_level = 0
|
||||
size = $ - data
|
||||
purge menuitem,menuseparator
|
||||
end if
|
||||
end macro
|
||||
end macro
|
||||
|
||||
macro dialog label,title,x,y,cx,cy,style,exstyle:0,menu:0,fontname:'MS Sans Serif',fontsize:8
|
||||
local data,size,items
|
||||
label dd RVA data,size,0,0
|
||||
data dd style or DS_SETFONT,exstyle
|
||||
dw items,x,y,cx,cy
|
||||
if menu <> 0
|
||||
dw 0FFFFh
|
||||
end if
|
||||
du menu,0,title,0
|
||||
du fontsize,fontname,0
|
||||
align 4
|
||||
local dialog_items_counter
|
||||
dialog_items_counter = 0
|
||||
macro dialogitem class,it_title,it_id,it_x,it_y,it_cx,it_cy,it_style,it_exstyle:0
|
||||
dd it_style or WS_CHILD,it_exstyle
|
||||
dw it_x,it_y,it_cx,it_cy,it_id
|
||||
if class eq 'BUTTON'
|
||||
dw 0FFFFh,80h
|
||||
else if class eq 'EDIT'
|
||||
dw 0FFFFh,81h
|
||||
else if class eq 'STATIC'
|
||||
dw 0FFFFh,82h
|
||||
else if class eq 'LISTBOX'
|
||||
dw 0FFFFh,83h
|
||||
else if class eq 'SCROLLBAR'
|
||||
dw 0FFFFh,84h
|
||||
else if class eq 'COMBOBOX'
|
||||
dw 0FFFFh,85h
|
||||
else
|
||||
du class,0
|
||||
end if
|
||||
match any=,any, it_title
|
||||
du it_title,0
|
||||
else if it_title eqtype ''
|
||||
du it_title,0
|
||||
else
|
||||
dw 0FFFFh,it_title
|
||||
end if
|
||||
dw 0
|
||||
align 4
|
||||
dialog_items_counter = dialog_items_counter + 1
|
||||
end macro
|
||||
macro enddialog
|
||||
size = $ - data
|
||||
items = dialog_items_counter
|
||||
purge dialogitem,enddialog
|
||||
end macro
|
||||
end macro
|
||||
|
||||
macro accelerator label,definitions&
|
||||
local data,size
|
||||
label dd RVA data,size,0,0
|
||||
data:
|
||||
iterate <fvirt,key,cmd>, definitions
|
||||
if % = %%
|
||||
dw fvirt or 80h,key
|
||||
size = %% * 8
|
||||
else
|
||||
dw fvirt,key
|
||||
end if
|
||||
dd cmd
|
||||
end iterate
|
||||
end macro
|
||||
|
||||
macro versioninfo label,fileos,filetype:0,filesubtype:0,lang,cp:0,values&
|
||||
local data,size,vivalue,visize
|
||||
label dd RVA data,size,0,0
|
||||
data dw size,visize,0
|
||||
du 'VS_VERSION_INFO',0,0
|
||||
vivalue dd 0FEEF04BDh,00010000h
|
||||
local version,count,shift,char,filever,productver
|
||||
filever = 0
|
||||
productver = 0
|
||||
iterate <name,value>, values
|
||||
if name eq 'FileVersion' | name eq 'ProductVersion'
|
||||
virtual at 0
|
||||
db value
|
||||
count = $
|
||||
version = 0
|
||||
shift = 16
|
||||
repeat count
|
||||
load char:byte from %-1
|
||||
if char='.'
|
||||
if shift mod 32
|
||||
shift = shift-16
|
||||
else
|
||||
shift = shift+32+16
|
||||
end if
|
||||
else
|
||||
version = (version and not (0FFFFh shl shift)) or ((version shr shift and 0FFFFh)*10+char-'0') shl shift
|
||||
end if
|
||||
end repeat
|
||||
end virtual
|
||||
if name eq 'FileVersion'
|
||||
filever = version
|
||||
else if name eq 'ProductVersion'
|
||||
productver = version
|
||||
end if
|
||||
end if
|
||||
end iterate
|
||||
dq filever,productver
|
||||
dd 0,0,fileos,filetype,filesubtype,0,0
|
||||
visize = $ - vivalue
|
||||
local sfi_data,sfi_size
|
||||
sfi_data dd sfi_size
|
||||
du 1,'StringFileInfo',0
|
||||
local str_data,str_size
|
||||
str_data dd str_size
|
||||
du 1,'040904E4',0
|
||||
macro vdata name,value&
|
||||
local vs_data,vs_size,value_data,value_size
|
||||
align 4
|
||||
vs_data dw vs_size,value_size/2
|
||||
du 1,name,0
|
||||
align 4
|
||||
value_data du value,0
|
||||
value_size = $ - value_data
|
||||
vs_size = $ - vs_data
|
||||
end macro
|
||||
iterate <name,value>, values
|
||||
vdata name,value
|
||||
end iterate
|
||||
purge vdata
|
||||
align 4
|
||||
str_size = $ - str_data
|
||||
sfi_size = $ - sfi_data
|
||||
local vfi_data,vfi_size,var_data,var_size
|
||||
vfi_data dd vfi_size
|
||||
du 1,'VarFileInfo',0,0
|
||||
var_data dw var_size,4
|
||||
du 0,'Translation',0,0
|
||||
dw lang,cp
|
||||
var_size = $ - var_data
|
||||
vfi_size = $ - vfi_data
|
||||
size = $ - data
|
||||
end macro
|
||||
|
||||
macro resdata label
|
||||
local data,size
|
||||
label dd RVA data,size,0,0
|
||||
data = $
|
||||
macro endres
|
||||
size = $ - data
|
||||
align 4
|
||||
purge endres
|
||||
end macro
|
||||
end macro
|
456
toolchain/fasm2/include/macro/struct.inc
Normal file
456
toolchain/fasm2/include/macro/struct.inc
Normal file
@ -0,0 +1,456 @@
|
||||
|
||||
define struct? struct?
|
||||
|
||||
namespace struct?
|
||||
|
||||
calminstruction instantiate: instance*, sname*, &values&
|
||||
|
||||
local tmp
|
||||
arrange tmp, =label instance : sname.=__size__
|
||||
assemble tmp
|
||||
arrange tmp, =namespace instance
|
||||
assemble tmp
|
||||
|
||||
match , values
|
||||
jyes values_ready
|
||||
call struct?.initialize, sname, values
|
||||
values_ready:
|
||||
|
||||
local i
|
||||
compute i, 1
|
||||
local field, val, stack
|
||||
process_statement:
|
||||
arrange field, sname.=__label#i
|
||||
transform field
|
||||
jyes labeled_statement
|
||||
arrange field,
|
||||
arrange tmp, sname.=__statement#i
|
||||
transform tmp
|
||||
jyes statement_ready
|
||||
jump finish
|
||||
|
||||
labeled_statement:
|
||||
arrange tmp, sname.=__label#i sname.=__definition#i
|
||||
transform tmp
|
||||
arrange val, =__init__.#field
|
||||
transform val
|
||||
jyes got_value
|
||||
arrange val, sname.=__default__.#field
|
||||
arrange field,
|
||||
transform val
|
||||
jno statement_ready
|
||||
got_value:
|
||||
arrange tmp, tmp val
|
||||
|
||||
statement_ready:
|
||||
|
||||
take stack, field
|
||||
take stack, i
|
||||
take stack, sname
|
||||
assemble tmp
|
||||
take , sname
|
||||
take sname, stack
|
||||
take , i
|
||||
take i, stack
|
||||
take , field
|
||||
take field, stack
|
||||
match , field
|
||||
jyes next_statement
|
||||
|
||||
arrange tmp, sname.=__size__.#field - (=$ - field)
|
||||
compute tmp, tmp
|
||||
check tmp = 0
|
||||
jyes next_statement
|
||||
check tmp > 0
|
||||
jyes fill_up
|
||||
stringify field
|
||||
err 'value too long to fit in ' bappend field
|
||||
jump next_statement
|
||||
fill_up:
|
||||
arrange tmp, =rb tmp
|
||||
assemble tmp
|
||||
|
||||
next_statement:
|
||||
compute i, i + 1
|
||||
jump process_statement
|
||||
|
||||
finish:
|
||||
asm end namespace
|
||||
end calminstruction
|
||||
|
||||
calminstruction initialize sname*, values&
|
||||
|
||||
local j, a
|
||||
compute j, 0
|
||||
arrange a, sname.=__argument
|
||||
|
||||
local tmp, field, val, sub
|
||||
process_argument:
|
||||
match field=, values, values, <>
|
||||
jyes got_argument
|
||||
arrange field, values
|
||||
arrange values,
|
||||
got_argument:
|
||||
match field:val?, field, <>
|
||||
jyes labeled_argument
|
||||
check j < 0
|
||||
jyes mixed_arguments
|
||||
compute j, j + 1
|
||||
arrange val, field
|
||||
match <val>, val
|
||||
arrange field, a#j
|
||||
transform field
|
||||
jno excess_arguments
|
||||
match <tmp>, field
|
||||
jno got_argument_field
|
||||
take a, tmp
|
||||
compute tmp, 0
|
||||
take j, tmp
|
||||
take values, val
|
||||
jump process_argument
|
||||
|
||||
excess_arguments:
|
||||
err 'excess arguments'
|
||||
jump arguments_processed
|
||||
mixed_arguments:
|
||||
err 'unsupported mixing of labeled and ordered values'
|
||||
jump arguments_processed
|
||||
|
||||
labeled_argument:
|
||||
check j > 0
|
||||
jyes mixed_arguments
|
||||
compute j, -1
|
||||
match <val>, val
|
||||
got_argument_field:
|
||||
arrange tmp, sname.=__default__.#field
|
||||
transform tmp
|
||||
jyes argument_ok
|
||||
match field.sub, field
|
||||
jno unknown_field
|
||||
arrange tmp, sname.=__default__.#field
|
||||
transform tmp
|
||||
jno unknown_field
|
||||
arrange val, sub:val
|
||||
arrange tmp, =__multi__.#field
|
||||
transform tmp
|
||||
jno append_value
|
||||
arrange val, tmp, val
|
||||
arrange tmp, =__multi__.#field
|
||||
append_value:
|
||||
publish tmp, val
|
||||
jump argument_ok
|
||||
unknown_field:
|
||||
stringify field
|
||||
arrange tmp, sname
|
||||
stringify tmp
|
||||
err tmp bappend ' has no field named ' bappend field
|
||||
jump next_argument
|
||||
|
||||
argument_ok:
|
||||
arrange tmp, =__init__.#field
|
||||
publish tmp, val
|
||||
next_argument:
|
||||
match , values
|
||||
jno process_argument
|
||||
arguments_processed:
|
||||
take , values
|
||||
take , j
|
||||
take , a
|
||||
take values, values
|
||||
jyes next_argument
|
||||
|
||||
end calminstruction
|
||||
|
||||
define pname
|
||||
define i
|
||||
define j
|
||||
define u
|
||||
define a
|
||||
|
||||
calminstruction (&label) collect? &definition&
|
||||
local sym, default, tmp
|
||||
match , definition
|
||||
jyes plain
|
||||
match :tmp?, definition
|
||||
jyes ignored
|
||||
match ==tmp?, definition
|
||||
jyes ignored
|
||||
arrange default,
|
||||
match definition= default, definition
|
||||
arrange sym, pname.=__definition#i
|
||||
publish sym:, definition
|
||||
arrange sym, pname.=__label#i
|
||||
publish sym:, label
|
||||
arrange sym, pname.=__default__.#label
|
||||
publish sym:, default
|
||||
arrange definition, label definition default
|
||||
assemble definition
|
||||
arrange definition, =__size__.#label == =$ - label
|
||||
assemble definition
|
||||
match , a
|
||||
jyes done
|
||||
compute j, j + 1
|
||||
arrange sym, a#j
|
||||
publish sym:, label
|
||||
done:
|
||||
exit
|
||||
ignored:
|
||||
arrange label, label definition
|
||||
plain:
|
||||
assemble label
|
||||
end calminstruction
|
||||
|
||||
calminstruction collect? &statement&
|
||||
local proto, sym, tmp
|
||||
check i
|
||||
jyes in_body
|
||||
|
||||
compute u, 0
|
||||
compute i, 1
|
||||
compute j, 1
|
||||
asm virtual at 0
|
||||
match pname= proto, pname
|
||||
arrange tmp, =namespace pname
|
||||
assemble tmp
|
||||
jno prototype_copied
|
||||
use_prototype:
|
||||
arrange a,
|
||||
arrange tmp, proto.=__statement#i
|
||||
transform tmp
|
||||
jno prototype_arguments
|
||||
arrange sym, pname.=__statement#i
|
||||
publish sym:, tmp
|
||||
assemble tmp
|
||||
compute i, i + 1
|
||||
jump use_prototype
|
||||
prototype_arguments:
|
||||
arrange tmp, proto.=__argument#j
|
||||
transform tmp
|
||||
jno prototype_copied
|
||||
arrange sym, pname.=__argument#j
|
||||
publish sym:, tmp
|
||||
compute j, j + 1
|
||||
jump prototype_arguments
|
||||
prototype_copied:
|
||||
compute j, j - 1
|
||||
arrange a, pname.=__argument
|
||||
|
||||
in_body:
|
||||
match =ends?, statement
|
||||
jyes close
|
||||
check u
|
||||
jno process_definition
|
||||
check u > 1
|
||||
jno union_divider_ok
|
||||
arrange tmp, =__union_divider
|
||||
arrange sym, pname.=__statement#i
|
||||
publish sym:, tmp
|
||||
assemble tmp
|
||||
compute i, i + 1
|
||||
arrange a,
|
||||
union_divider_ok:
|
||||
compute u, u + 1
|
||||
process_definition:
|
||||
match =struct?, statement
|
||||
jyes open_struct
|
||||
match =union?, statement
|
||||
jyes open_union
|
||||
arrange sym, pname.=__statement#i
|
||||
publish sym:, statement
|
||||
assemble statement
|
||||
compute i, i + 1
|
||||
exit
|
||||
open_union:
|
||||
arrange tmp, =__union_start
|
||||
arrange sym, pname.=__statement#i
|
||||
publish sym:, tmp
|
||||
assemble tmp
|
||||
compute i, i + 1
|
||||
arrange tmp, a
|
||||
take a, tmp
|
||||
compute tmp, 1
|
||||
take u, tmp
|
||||
exit
|
||||
open_struct:
|
||||
match , a
|
||||
jyes unlisted_substruct
|
||||
compute j, j + 1
|
||||
arrange sym, a#j
|
||||
arrange tmp, a#j#=_
|
||||
take a, tmp
|
||||
arrange tmp, <a>
|
||||
publish sym:, tmp
|
||||
jump begin_substruct
|
||||
unlisted_substruct:
|
||||
arrange tmp,
|
||||
take a, tmp
|
||||
begin_substruct:
|
||||
compute tmp, 0
|
||||
take j, tmp
|
||||
compute tmp, 0
|
||||
take u, tmp
|
||||
exit
|
||||
close:
|
||||
check u
|
||||
jno close_struct
|
||||
arrange tmp, =__union_end
|
||||
arrange sym, pname.=__statement#i
|
||||
publish sym:, tmp
|
||||
assemble tmp
|
||||
compute i, i + 1
|
||||
take , a
|
||||
take , u
|
||||
exit
|
||||
close_struct:
|
||||
take , a
|
||||
take , j
|
||||
take , u
|
||||
take a, a
|
||||
jyes done
|
||||
asm end namespace
|
||||
arrange sym, pname.=__size__
|
||||
compute tmp, $
|
||||
publish sym:, tmp
|
||||
arrange tmp, #sym
|
||||
arrange sym, =sizeof.pname
|
||||
publish sym, tmp
|
||||
asm end virtual
|
||||
assemble statement
|
||||
done:
|
||||
end calminstruction
|
||||
|
||||
end namespace
|
||||
|
||||
macro struct? declaration*, attributes
|
||||
if defined Struct.CheckAlignment & Struct.CheckAlignment
|
||||
struct?.packed = 0
|
||||
else
|
||||
struct?.packed = 1
|
||||
end if
|
||||
match =packed?, attributes
|
||||
struct?.packed = 1
|
||||
else match any, attributes
|
||||
err 'unknown attribute ',`any
|
||||
end match
|
||||
|
||||
define struct?.pname declaration
|
||||
struct?.i = 0
|
||||
mvstruc ?, struct?.collect?
|
||||
mvmacro ?, struct?.collect?
|
||||
end macro
|
||||
|
||||
macro ends?
|
||||
mvmacro struct?.collect?, ?
|
||||
mvstruc struct?.collect?, ?
|
||||
|
||||
match name, struct?.pname
|
||||
|
||||
label name: name.__size__ at name.__size__
|
||||
|
||||
struct?.check name
|
||||
|
||||
local sname
|
||||
define sname name
|
||||
|
||||
calminstruction (instance) name values&
|
||||
call struct?.instantiate, instance, sname, values
|
||||
end calminstruction
|
||||
|
||||
calminstruction name &values&
|
||||
local ic, iname
|
||||
init ic
|
||||
compute ic, ic + 1
|
||||
arrange iname, sname#ic
|
||||
call struct?.instantiate, iname, sname, values
|
||||
end calminstruction
|
||||
|
||||
end match
|
||||
end macro
|
||||
|
||||
macro __union_start
|
||||
local union
|
||||
union:
|
||||
union.i = 0
|
||||
union.size = 0
|
||||
union.initialized = 0
|
||||
macro __union_open
|
||||
union.i = union.i + 1
|
||||
if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1)
|
||||
virtual at union
|
||||
end if
|
||||
end macro
|
||||
macro __union_close
|
||||
if $@ > union
|
||||
if union.i > 1
|
||||
union.init := union.i
|
||||
end if
|
||||
if union.initialized
|
||||
err 'conflicting initialization of union'
|
||||
else
|
||||
union.initialized = union.i
|
||||
end if
|
||||
end if
|
||||
if $ - union > union.size
|
||||
union.size = $ - union
|
||||
end if
|
||||
if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1)
|
||||
end virtual
|
||||
end if
|
||||
end macro
|
||||
macro __union_divider
|
||||
__union_close
|
||||
__union_open
|
||||
end macro
|
||||
macro __union_end
|
||||
__union_close
|
||||
if $ - union < union.size
|
||||
rb union.size - ($ - union)
|
||||
end if
|
||||
purge __union_open,__union_close,__union_divider,__union_end
|
||||
end macro
|
||||
__union_open
|
||||
end macro
|
||||
|
||||
calminstruction breakifndef? sym
|
||||
transform sym
|
||||
jyes ok
|
||||
asm break
|
||||
ok:
|
||||
end calminstruction
|
||||
|
||||
macro struct?.check name
|
||||
if ~ struct?.packed
|
||||
local alignment, maxalignment
|
||||
maxalignment = 1
|
||||
while 1
|
||||
breakifndef name.__statement#%
|
||||
match label, name.__label#%
|
||||
if defined name.label
|
||||
local alignment
|
||||
alignment = 1
|
||||
if sizeof name.label > 0
|
||||
alignment = 1 shl (bsf sizeof name.label)
|
||||
end if
|
||||
match type, name.__definition#%
|
||||
if defined type.__alignment
|
||||
alignment = type.__alignment
|
||||
end if
|
||||
end match
|
||||
if name.label mod alignment > 0
|
||||
repeat 1, natural: alignment
|
||||
display 'warning: ',`name,'.',`label,' not aligned to its natural boundary (',`natural,')',13,10
|
||||
end repeat
|
||||
else if alignment > maxalignment
|
||||
maxalignment = alignment
|
||||
end if
|
||||
end if
|
||||
end match
|
||||
end while
|
||||
if sizeof name mod maxalignment > 0
|
||||
repeat 1, size: sizeof name, natural: maxalignment
|
||||
display 'warning: size of ',`name,' (',`size,') not aligned to its natural boundary (',`natural,')',13,10
|
||||
end repeat
|
||||
end if
|
||||
name.__alignment := maxalignment
|
||||
end if
|
||||
end macro
|
Reference in New Issue
Block a user