flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] Lucas Prime Test

Goto page Previous  1, 2, 3  Next
Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 17 Feb 2019, 17:57
Code:
; is F a factor of 2^N-1
macro MFactorQ N*,F*
        local B,T,D
        D = 1 + bsr F
        B = 1
        T = 1
        while B < N & T
                if (B+D) <= N
                        T = ((T+1) shl D)-1
                        B = B + D
                        T = T mod F
                else
                        T = T + T + 1
                        B = B + 1
                        if T >= F
                                T = T mod F
                        end if
                end if
        end while
        repeat 1,t:T,b:B,f:F
                if T = 0
                        display `f,' divides 2^',`b,'-1.',13,10
                else
                        display '2^',`b,'-1 mod ',`f,' = ',`t,13,10
                end if
        end repeat
end macro

MFactorQ 1001664179, 1878753956886303627167 ; 2 min
MFactorQ 3930621659, 6134708376727152865752497 ; 10 min    

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 17 Feb 2019, 17:57
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 27 Feb 2019, 01:27
Is there an a way to terminate the assembly process without producing an error? I don't want an output file, but presently am using "err 'No Output File'".
Code:
test-file.fasmg [66]:
        err 'No Output File'
Custom error: No Output File.
The terminal process terminated with exit code: 1    
I need to prune zero length files from the directory or parse around "no file errors" to find actual errors. Another solution would be to output to NUL, but this too splits the build process. It would be nice to have a solution within the source itself.

Maybe "format null" could not produce a file?

[EDIT] found several solutions to delete an empty file:
https://stackoverflow.com/questions/9378972/how-do-i-detect-and-delete-a-file-if-it-is-empty-using-a-windows-batch-file

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 22 Jan 2020, 03:11; edited 1 time in total
Post 27 Feb 2019, 01:27
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 13 Mar 2019, 02:00
bitRAKE wrote:
Next I try to verify some data: There is list of cube sums at https://arxiv.org/abs/1604.07746v1
The answer is 42 !

https://www.youtube.com/watch?v=ASoz_NuIvP0

[EDIT] Found!

https://youtu.be/zyG8Vlw5aAw

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 06 Sep 2019, 17:05; edited 1 time in total
Post 13 Mar 2019, 02:00
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 14 Jul 2019, 11:45
Tried to encapsulate commandline option testing to something like:
Code:
OPTION "s","silent"
        bts [Options.FLAGS],FLAG_SILENT
END OPTION

OPTION "h","help"
        mov rax,[.pArgv]
        push qword [rax]
        lea rdx,[HelpMessage]
        call STD_OUTPUT_HANDLE__wsprintfA
        pop rax
END OPTION    
... which resulted in the following try ...
Code:
Options.count = 0

macro OPTION text&
        local skip
        macro END.OPTION!
                        label skip.0
                esc end macro
                end repeat
                purge END.OPTION
        end macro

        Options.count = Options.count + 1
        repeat 1,i:Options.count
        esc macro Options.i
                iterate txt,text
                        virtual at 1
                                ; rely on DU to convert UTF8 to widechar
                                du txt
                                load temp: $-1 from $$
                        end virtual
                        if % = %%
                                skip.temp = 1
                        end if
                        repeat ((bsr temp) shr 4) + 2
Display "0"+%% ; 1?
                                if % = %%
                                        if % and 1
                                                cmp word [rsi+2*(%+1)],temp
                                        else
                                                cmp dword [rsi+2*(%+1)],temp
                                        end if
                                        if skip.temp
                                                ; fall through to process, if txt is last alternative
                                                jnz skip.0
                                        else
                                                ; jump over alternatives to process
                                                jz skip.dont
                                        end if
                                else if ~ (% and 1)
                                        cmp dword [rsi+2*(%+2)],temp and $FFFFFFFF
                                        temp = temp shr 32
                                        if skip.temp
                                                ; if txt is last alternative skip process
                                                jnz skip.0
                                        else
                                                ; try next alternative
                                                jnz skip.%
                                        end if
                                end if
                        end repeat
                        label skip.%
                end iterate
                label skip.dont
end macro

macro __OPTIONS
        postpone ?
        repeat Options.count
                Options.%
        end repeat
        end postpone
end macro    
Can't seem to get this to work as expected. Completely baffled how REPEAT ?+2 could result in %%=1.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 14 Jul 2019, 11:45
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 14 Jul 2019, 11:52
bitRAKE wrote:
Can't seem to get this to work as expected. Completely baffled how REPEAT ?+2 could result in %%=1.
When you define a macro inside a REPEAT block, the "%%" in the text of the inner macro is replaced with a number. So the body of your macro contains a hard-coded number in place of every occurrence of "%%" (and the same goes for "%").

To make matters worse, "%" and "%%" are global parameters (not limited by a scope, as long as you are inside some repeated block, they have a value), so even encapsulating the macro definition would not save you here.
Post 14 Jul 2019, 11:52
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 14 Jul 2019, 12:14
A reduced sample that demonstrates the problem:
Code:
repeat 1,i:1
        macro Options.i
                iterate txt, 'a','b','c'
                        display '0'+%%
                end iterate
        end macro
end repeat

Options.1    
And a kind of a messy solution:
Code:
macro preserve_counters? %:%, %%:%%
        macro end?.preserve_counters?
                end match
        end macro
        outscope match %:%%, %:%%
end macro


repeat 1,i:1
        preserve_counters
                macro Options.i
                        iterate txt, 'a','b','c'
                                display '0'+%%
                        end iterate
                end macro
        end preserve_counters
end repeat

Options.1    
But in this case I think it would be better to just get rid of the outer REPEAT, for example by using MATCH to extract the name of macro to define from a symbolic variable (you could even maintain Options.count as a symbolic variable).
Post 14 Jul 2019, 12:14
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 30 Jul 2019, 14:27
Since I didn't need the count, I went with something similar to:
Code:
postpone ?
OPTIONS
end postpone

macro OPTIONS
end macro

macro OPTION text&
        macro END.OPTION!
                esc end macro
                purge END.OPTION
        end macro

        esc macro OPTIONS
                OPTIONS
                iterate txt, text
                        display "0"+%,txt
                end iterate
                display 13,10
end macro


OPTION 'a','b','c'

END OPTION

OPTION 'x','y','z'

END OPTION    
This is less efficient perhaps?

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 30 Jul 2019, 14:27
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 11 Dec 2019, 12:57
Code:
; add to string list in sorted order
macro sort_into str_list*,text*&
        local inserted

        iterate t0, text
        inserted = 0
        repeat 1,k0:t0
                match S,str_list
                iterate sN, S
                        if inserted
                                str_list reequ str_list,sN
                        else if % = 1
                                repeat 1,kN:sN
                                        if k0 < kN
                                                str_list reequ t0,sN
                                                inserted = 1
                                        else
                                                str_list reequ sN
                                        end if
                                end repeat
                        else if % = %% ; not 1
                                repeat 1,kN:sN
                                        if k0 < kN
                                                str_list reequ str_list,t0,sN
                                        else
                                                str_list reequ str_list,sN,t0
                                        end if
                                end repeat
                        else
                                repeat 1,kN:sN
                                        if k0 < kN
                                                str_list reequ str_list,t0,sN
                                                inserted = 1
                                        else
                                                str_list reequ str_list,sN
                                        end if
                                end repeat
                        end if
                end iterate
                end match
        end repeat
        end iterate
end macro


my_list equ "6","A","k"
display 13,10,my_list

sort_into my_list,"1" ; test before
display 13,10,my_list

sort_into my_list,"y" ; test after
display 13,10,my_list

sort_into my_list,"x" ; test middle
display 13,10,my_list

; list merge sorted
temp_list equ "0","-","z","h"
match X,temp_list
        sort_into my_list,X
end match
display 13,10,my_list    

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 11 Dec 2019, 12:57
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 24 Jan 2020, 20:42
Code:
virtual at 16
calign::        ; AMD Family 17h, Model 30h-3Fh Recommended NOP encoding
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66'66'66'66'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66'66'66'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66'66'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66'66h
        emit 16 : 00'00'00'00'00'84'1F'0F'66h
        emit 16 : 00'00'00'00'00'84'1F'0Fh
        emit 16 : 00'00'00'00'80'1F'0Fh
        emit 16 : 00'00'44'1F'0F'66h
        emit 16 : 00'00'44'1F'0Fh
        emit 16 : 00'40'1F'0Fh
        emit 16 : 00'1F'0Fh
        emit 16 : 90'66h
        emit 16 : 90h
end virtual

;macro code_align?
;       delta = 15-((0 scaleof $)+15) mod 16
;       if delta > 0
;               load dat : delta from calign : (16-delta) shl 4
;               emit delta : dat
;       end if
;end macro


calminstruction code_align? boundary:16
        check   boundary eq 16 & ($ relativeto 0 | ( $ relativeto PE.RELOCATION & PE.SECTION_ALIGNMENT mod boundary = 0 ))
        jyes    allowed
        arrange value, =err 'section not aligned enough'
        assemble value
        exit
    allowed:
        compute boundary, (boundary-1)-((0 scaleof $)+boundary-1) mod boundary
        check boundary eq 0
        jyes done
        arrange value, =load =dat : boundary =from =calign : (16-boundary) =shl 4
        assemble value
        arrange value, =emit boundary : =dat
        assemble value
    done:
end calminstruction


; just a test
repeat 16
        rb %
        code_align
end repeat
assert $=256    
Every processor seems to have its own recommendation on code alignment to reduce pipeline resource use and stalls.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 24 Jan 2020, 20:42
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 24 Jan 2020, 20:51
While I've been testing assembly of HeavyThing with CALM-powered fasmg, I used this kind of conversion of its alignment macros:
Code:
struc bstr? bytes&
        virtual at 0
                db bytes
                load . : $ from 0
        end virtual
end struc

define aligncode aligncode
namespace aligncode
        ?15 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0x66, 0xf, 0x1f, 0x44, 0x00, 0x00
        ?14 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0xf, 0x1f, 0x44, 0x00, 0x00
        ?13 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0xf, 0x1f, 0x40, 0x00
        ?12 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0xf, 0x1f, 0x00
        ?11 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0x66, 0x90
        ?10 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, \
                 0x90
        ?9 bstr 0x66, 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
        ?8 bstr 0xf, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
        ?7 bstr 0xf, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00
        ?6 bstr 0x66, 0xf, 0x1f, 0x44, 0x00, 0x00
        ?5 bstr 0xf, 0x1f, 0x44, 0x00, 0x00
        ?4 bstr 0xf, 0x1f, 0x40, 0x00
        ?3 bstr 0xf, 0x1f, 0x00
        ?2 bstr 0x66, 0x90
        ?1 bstr 0x90
        ?0 := ''
end namespace

define virtual          virtual
define end_virtual      end virtual

calminstruction aligncode alignment
        check   alignment
        jno     done
        local   a
        assemble virtual
        arrange alignment, =align alignment
        assemble alignment
        compute a, $ - $$
        assemble end_virtual
        check   a
        jno     done
        arrange a, =db =aligncode.a
        assemble a
    done:
end calminstruction    
Post 24 Jan 2020, 20:51
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 02 Aug 2020, 10:39
Brent-Pollard-Rho is a historical algorithm, the first to factor the ninth Fermat number. Reading the paper, it's cycle-finding portion is not a major improvement (theoretically), but it transformed the problem into a form with other potential optimizations.
Code:
include 'gcd.g' ; binary large number greatest common divisor

; test on F_8 = 2^2^8 + 1, which took 2 hours to factor in 1980

n = 1 shl (1 shl 8) + 1 ; F8, Fermat Number
n = 1 shl (1 shl 11) + 1

; initial constants:
c = 1
max = 1 shl 24
check = 17

while 1
        factor = 1 ; trivial factor

        x1 = 2
        x2 = 4 + c
        range = 1
        product = 1
        terms = 0

        i = 0
        while i < max
                j = 0
                while j < range
                        x2 = (x2 * x2 + c) mod n
                        if x1 > x2 ; absolute value of (x1-x2)
                                xT = ((x1 - x2) mod n)
                        else
                                xT = ((x2 - x1) mod n)
                        end if
                        if xT = 0 ; (x1-x2), is a multiple of (n)
                                display "."
                        else
                                product = (product * xT) mod n
                        end if
                        terms = terms + 1
                        if terms = check
                                factor GCD product,n
                                if factor < n
                                if factor > 1
                                        break ; factor (factor)
                                end if
                                end if
                                product = 1
                                terms = 0
                                factor = 1
                        end if
                        j = j + 1
                end while
                if factor > 1
                        break ; factor (factor)
                end if

                x1 = x2
                range = range shl 1
                j = 0
                while j < range
                        x2 = (x2 * x2 + c) MOD n
                        j = j + 1
                end while
                i = i + 1
        end while
        if factor > 1
                repeat 1,N0:factor,N1:n
                        display 13,10,`N0,' is a non-trivial factor of ',`N1,13,10
                end repeat
                break
        end if

        ; select another (c)
        c = c + 1
end while    
...and the binary gcd.g
Code:
struc GCD A*,B*
        if A = 0
                . = B
        else if B = 0
                . = A
        else if A = B
                . = A
        else
                local shift,t0,t1
                shift = bsf (A or B)
                t0 = A shr shift
                t1 = B shr (bsf B)
                while t0 > 0
                        t0 = t0 shr (bsf t0)
                        if t1 > t0
                                t0 = t1 - t0
                                t1 = t1 - t0
                        else
                                t0 = t0 - t1
                        end if
                end while
                . = t1 shl shift
        end if
end struc    
Generalized Floyd's cycle-finder (doesn't actually return the cycle length directly):
Code:
; where f:S->S is some easily-computable function, and x_0 in S.
struc f X*
.=((X)*(X)+C) mod S
end struc


; Floyd's Algorithm:
; find m >= 0 and n >= 1 such that x_(m+n) = x_m,
; then x_(i+n) = x_i for all i >= m.

x = x0
y = x0
j = 0
while x <> y
        j = j + 1
        x f x
        y f y
        y f y
end while
; j is a multiple of n (the period)
; x = x_j, y = x_2j    
Brent's Algorithm (B_Q=2):
Code:
u = 0
Q = 2

y = x0
r = 1 shl u ; Q^u
k = 0
done = 0
while ~ done
        x = y
        j = k
        r = Q * r
        while ~ done
                k = k + 1
                y f y
                if x = y
                        done = 1
                end if
                if k>= r
                        break
                end if
        end while
end while
n = k - j    
Which actually translates to quite small x86:
Code:
.out:   mov [.x],rax
        mov [.j],rbx
        shl [.r],1 ; r = Q * r
.inn:   add rbx,1
        call f
        cmp rax,[.x]
        jz .done
        cmp rbx,[.r]
        jc .inn
        jmp .out
.done:  sub rbx,[.j] ; period    
...returning the period directly!

It is important to process the power of two (Q) intervals separately because of the choice of (f). I know the brack-tracking has been excluded. Wink

It's been 40 years. What kind of speed up should we expect from the same algorithm? No less than three orders would be my guess.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 02 Aug 2020, 10:39
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 09 Aug 2020, 18:53
Code:
; Modulus by Special Forms:
;       2^N
;       2^N - 1
;       2^N + 1
;
; Most of the time N is constant through a large calculation and it would be
; advantageous to cache the bitmask of that value globally. These algorithms
; are overly general in that regard.
;
; In x86 code many of the constants can be eliminated. For example, maintaining
; a large integer in granular packets no shifts are needed. Or tests for zero
; of a large integer can be accumulated during the previous operation.


struc mod_2ⁿ val,n
        . = val and ((1 shl n) - 1)
end struc


struc mod_2ⁿ−1 val,n
        local D,X
        D = (1 shl n) - 1
        X = val
        . = val
        while X > D
                . = 0
                while X
                        . = . + (X and D)
                        X = X shr n
                end while
                X = .
        end while
        if . = D
                . = 0
        end if
end struc


struc mod_2ⁿp1 val,n
        local D,X,sign
        D = (1 shl n) - 1
        X = val
        sign = 1
        . = 0
        while X
                if sign
                        . = . + (X and D)
                else ; force positive
                        . = . - (X and D) + D + 2
                end if
                sign = sign xor 1
                X = X shr n
                if X = 0
                        if . > (D + 1)
                                . = (. and D) - (. shr n)
                        end if
                end if
        end while
end struc


IF __source__=__file__
; https://board.flatassembler.net/topic.php?p=210079#210079
include 'Randomizer.g' ; Tomasz Grysztar's xorshift implementation
Randomizer.SEED := %t

repeat 16
        N Randomizer.rand 4095
        X Randomizer.rand32
        N = N or 1
        X = (X shl (%*N)) + 2*(X*N) + 1
        K = bsr X

        temp mod_2ⁿ X, N
        if temp <> (X mod (1 shl N))
                display "mod_2ⁿ: fail",13,10
                break
        end if

        temp mod_2ⁿ−1 X, N
        if temp <> (X mod ((1 shl N)-1))
                display "mod_2ⁿ−1: fail",13,10
                break
        end if

        temp mod_2ⁿp1 X, N
        if temp <> (X mod ((1 shl N)+1))
                display "mod_2ⁿp1: fail",13,10
                break
        end if

        repeat 1,n:N,k:K
                display 9,"tested N = ",`n,9,"(on ",`k," bit number)",13,10
        end repeat
end repeat
display "pass",13,10

END IF    
The test is about 3 seconds here.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 09 Aug 2020, 18:53
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 29 Aug 2020, 14:17
In continuation of an earlier exchange here:
Tomasz Grysztar wrote:
To make matters worse, "%" and "%%" are global parameters (not limited by a scope, as long as you are inside some repeated block, they have a value), so even encapsulating the macro definition would not save you here.
I knew it was not really a good design decision, and now I finally made "%" and "%%" be limited to the same scope as all other (named) parameters defined by "repeat" etc. For example if you do "repeat 10, i:0", parameter "%" is now limited in scope similarly to "i" (for example, it is not evaluated inside called macros). Please forgive me that it took so long!
Post 29 Aug 2020, 14:17
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 29 Aug 2020, 22:45
Thank you, modularity win by reducing side-effects. I noticed some other changes, a bunch of ESC everywhere - still trying to grok the extent from the manual additions. Reduces the need for ESC at every scope? Might need an example of that to understand what it means. Shifting scales and scopes boggles the mind.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 29 Aug 2020, 22:45
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 30 Aug 2020, 08:55
bitRAKE wrote:
Thank you, modularity win by reducing side-effects. I noticed some other changes, a bunch of ESC everywhere - still trying to grok the extent from the manual additions. Reduces the need for ESC at every scope? Might need an example of that to understand what it means. Shifting scales and scopes boggles the mind.
Yes, it removes the need to use multiple ESC when the macros are properly nested (which is majority of use cases).
Post 30 Aug 2020, 08:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 02 Sep 2020, 21:00
Code:
struc (id) interface? iid,func&
        struc (object) id
                macro object A&
                end macro
                object#__#id rq 1
        end struc
end struc

IUnknown interface 00000000-0000-0000-C000-000000000046,\
        QueryInterface,AddRef,Release

tst IUnknown    
I thought something like this would need ESC, but my error was solved by using "?tst IUnknown". Very useful little feature. One pass is using the STRUC and then the next using the MACRO.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 02 Sep 2020, 21:00
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 03 Sep 2020, 15:25
Code:
; A consistent framework for parameter passing and management:

define FRAME? FRAME? ; root needs definition to be reachable through namespaces

; tail of stack frame is almost always the same, name the parts to simplify use
; this is only true after ENTER instruction
iterate X, RBP,RET,RCX,RDX,R8,R9
        define FRAME?.#X? (rbp+8*%-8)
end iterate

; Convenient names for stack parameters > 4, using RBP indexing to reduce size.
; N, parameter count needed
; d, qword parity at this stack depth to achieve MOD 16 addresses
; TODO: support brief local variables
macro FRAME?.ENTER? N*,d=0
        local D
        D=(N+((N-d) and 1))
        enter 8*D,0
        repeat N-4,i:4 ; named "..P4" and up, zero based so numbers match parity with stack
                define ..P#i rbp - 8*D + i*8
        end repeat
        macro FRAME?.LEAVE?
                repeat N-4,i:4
                        restore ..P#i
                end repeat
                leave
                purge FRAME?.LEAVE?
        end macro
end macro


; only support constant source types: memory addresses or literals
macro FRAME?.PARAMS? PP& ; w64 ABI parameter convension
        iterate p,PP
                indx %%-%+1 ; reverse order
                repeat 1,f:%%-% ; need correct index - 1
                match A|=f:R|B,:|0:RCX|1:RDX|2:R8|3:R9|:
                        mov R,p
                else ; f > 3
                        mov qword[..P#f],p
                end match
                end repeat
        end iterate
end macro    
almost featureless

Edit: Just realized my parity parameter is reversed because ENTER stores RBP on the stack. Was using it as intended from a different perspective then commented and coded based on that perspective.

Some examples of use:
Code:
; At the very minimal of assistance
enter 32,0
mov [FRAME.RCX],rcx ; save for use later
; use API functions - stack remains aligned
leave
retn


; Using more support
frame.enter 12
mov [FRAME.RCX],rcx ; using our shadow space
mov [..P11],rax ; using local parameter space
; use API functions - stack remains aligned
frame.leave
retn    
It's meant to be extremely light-weight and transparent. FRAME.PARAMS is meant to be generic for fastcall with shadow space; used by COM and STDCALL. I'll need to at least add types to process floats, and skipping over nops (like, MOV RCX,RCX).

ADDR seems like hidden trickery -- introduces bugs. Despite really liking the feature, I don't like hiding bugs (i.e. the user needs to know about the internal operation to correctly use the feature). I can think of a couple way to design around this self-imposed limitation. #1, Could select a volatile register based on use - lots of registers are technically availible. #2, error if RAX is used after ADDR - maybe attempt processing parameters in forward direction before quiting. #3, make ADDR have a register parameter so user must be "aware" of side-effects.

For #2,
Code:
repeat elementsof src
        if ((src metadata % metadata 1) relativeto x86.reg)     ; register
        if (src metadata % scale 0) = 0\                        ; RAX..AL
        | (src metadata % scale 0) = -4                         ; AH
                err "ADDR/RAX: invalid combination of parameters"
        end if
        end if
end repeat    

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 04 Sep 2020, 10:58; edited 2 times in total
Post 03 Sep 2020, 15:25
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8349
Location: Kraków, Poland
Tomasz Grysztar 03 Sep 2020, 17:34
I feel that the title of this thread becomes more and more misleading. Perhaps some of the snippets deserve to be put into separate threads?
Post 03 Sep 2020, 17:34
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 04 Sep 2020, 00:19
fasmg macro language crash course.
(minus calm syntax)

a brief survey of fasmg techniques

Perhaps at least three threads are here currently, but it's only two pages.

earlier, ALIGN work: https://board.flatassembler.net/topic.php?t=20949

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 04 Sep 2020, 00:19
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4015
Location: vpcmpistri
bitRAKE 14 Sep 2020, 19:46
Maybe a useful perspective?
Code:
previous value:

        N/A             discarded       preserved       brought back    /w transfer

        :=              =               =:              restore
                        reequ           equ             restore
                        redefine        define          restore
        macro:                          macro           purge           mvmacro
                                        struc           restruc         mvstruc    
Post 14 Sep 2020, 19:46
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.