flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
Tomasz Grysztar 06 Apr 2017, 14:04
Another variant which is even cleaner thanks to the use of enumerated variables for fastcall register names:
Code: define 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 macro fastcall? proc*,args& local offset,framesize,type,value if framesize sub rsp,framesize end if offset = 0 match any, args iterate arg, args match =float? val, arg type = 'f' redefine value val SSE.parse_operand @src,val else match =addr? val, arg type = 'a' redefine value val x86.parse_operand @src,[val] else type = 0 redefine value arg SSE.parse_operand @src,arg end match 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 @src.size = 8 | ~ @src.size redefine target fastcall.r#% if @src.type <> 'reg' | ~ @src.imm eq fastcall.r#% mov fastcall.r#%,value end if else if @src.size = 4 redefine target fastcall.rd#% if @src.type <> 'reg' | ~ @src.imm eq fastcall.rd#% mov fastcall.rd#%,value end if else if @src.size = 2 redefine target fastcall.r#% if @src.type <> 'reg' | ~ @src.imm eq fastcall.rw#% mov fastcall.rw#%,value end if else if @src.size = 1 redefine target fastcall.rb#% if @src.type <> 'reg' | ~ @src.imm eq fastcall.rb#% end if else err 'invalid argument ',`arg end if end if end if 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 mov qword [rsp+offset],value 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 end match framesize = offset + offset and 8 call proc if framesize add rsp,framesize end if end macro macro invoke? proc*,args& fastcall [proc],args end macro macro cinvoke? proc*,args& fastcall [proc],args end macro |
|||
![]() |
|
Tomasz Grysztar 06 Apr 2017, 14:13
The above ones still miss another feature of fasm's macro: the inline strings support. This can be added with a small insertion like this:
Code: if @src.type = 'imm' & @src.size = 0 if value eqtype '' & ~ type = 'f' inline_string value type = 'a' end if end if Code: macro inline_string var local data,continue jmp continue data TCHAR var,0 redefine var data continue: end macro |
|||
![]() |
|
Tomasz Grysztar 12 Apr 2017, 18:38
This macro with added "frame"/"endf" feature is now part of the fasm-like Windows headers package for fasmg.
|
|||
![]() |
|
VEG 28 Apr 2017, 19:42
Tomasz Grysztar wrote: for example another implementation of "inline_string" could insert the string into data section, and perhaps even check for duplicates. |
|||
![]() |
|
Tomasz Grysztar 28 Apr 2017, 20:18
VEG wrote: Oh, nice idea! I think such technique will be very useful in different situations. Will be nice to have an example how to add some contents to a virtual container, and then insert all these contents in specific place of the binary. It could be useful not just for strings, but even for pieces of code, for example. Or you can add resources to the .rsrc section from different places (near the code which uses these resources) and in one special command all resources will be placed in the proper place. Code: string.buffer = '' postpone string.data := string.buffer end postpone macro fastcall?.inline_string var local data virtual at fastcall?.strings db string.buffer data TCHAR var,0 load string.buffer:$-$$ from $$ end virtual redefine var data end macro ; Put this line in your data section: fastcall?.strings db string.data This is a plain and simple variant, it does not try to reuse strings. It is, however, completely order-independent, you can put the data section first or last and it is going to work correctly in all cases. As for the string reuse, there are also multiple variants that come to my mind. One could be to use Boyer-Moore-Hornspool search like in a similar set of macros I made for fasm 1. This would have an advantage that it would be able to find reusable substrings. The other option could be to use EVAL to define symbols with names derived from string (something like base64 encoding) in a special namespace and this way utilize fasmg's symbol lookup to quickly check if a given string has already been placed somewhere and at what address. |
|||
![]() |
|
VEG 28 Apr 2017, 20:48
Tomasz Grysztar, oh, thank you for this example. I will definitely use it. It is a thing that I was almost dreaming about while using FASM1
![]() |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.