Seite 1 von 1

Multiplikation von zwei Quads mod andere Quad - ASM to PB?

Verfasst: 16.03.2022 20:41
von STARGÅTE
Hallo Leute,

aktuell gibt es ja so eine Art "C-Backend" Hype, daher möchte ich auch ein paar meiner Prozeduren ASM-frei machen.
In einem Programm benötige ich die Operation: X = (A * B) mod C, wobei X, A, B und C Quads sein müssen.
In Assembler mache ich das über MUL und DIV, die ja mit 128 bit klar kommen, weil sie zwei Register nutzen.

Code: Alles auswählen

Procedure.q MulMod(Factor1.q, Factor2.q, Mod.q)
	! MOV rax, [p.v_Factor1]
	! MUL qword [p.v_Factor2]  ; RDX:RAX = Factor1 * Factor2
	! CMP rdx, qword [p.v_Mod]
	! JB @F
		! MOV rcx, rax             ; RCX = RAX
		! MOV rax, rdx             ; RAX = RDX
		! MOV rdx, 0
		! DIV qword [p.v_Mod]      ; RDX = RAX % Mod
		! MOV rax, rcx             ; RAX = RCX
	! @@:
	! DIV qword [p.v_Mod]      ; RDX = RDX:RAX % Mod
	! MOV rax, rdx
	ProcedureReturn
EndProcedure

Debug MulMod(210987654321, 210987654321, 170)
Aber wie würde ich das in "pure" PureBasic umschreiben? Vermutlich müsste ich alle Quads als zwei Longs betrachten und viele Zwischenergebnisse berechnen oder hat jemand n andere Idee?

Re: Multiplikation von zwei Quads mod andere Quad - ASM to PB?

Verfasst: 16.03.2022 22:44
von mk-soft
Hat ein wenig gedauert ... Compiler C-Backend vergessen zu wählen ;)

Erst mal nur Mul.

Code: Alles auswählen

CompilerIf #PB_Compiler_Backend <> #PB_Backend_C
  CompilerError "For C-Backend!"
CompilerEndIf

Procedure extmul(a.q, b.q, *lo.quad, *hi.quad)
  !__int128 result = ((__int128)v_a * (__int128)v_b);
  !p_lo->f_q = (quad)result;
  !p_hi->f_q = result >> 64;
EndProcedure

Define a, b, lo, hi

a = $1000000000000001
b = 256

extmul(a, b, @lo, @hi)

Debug lo
Debug hi

Re: Multiplikation von zwei Quads mod andere Quad - ASM to PB?

Verfasst: 16.03.2022 23:02
von mk-soft
Könnte so passen ...

Code: Alles auswählen

CompilerIf #PB_Compiler_Backend <> #PB_Backend_C
  CompilerError "Fot C-Backend!"
CompilerEndIf

Procedure extmul(a.q, b.q, *lo.quad, *hi.quad)
  !__int128 result = ((__int128)v_a * (__int128)v_b);
  !p_lo->f_q = (quad)result;
  !p_hi->f_q = result >> 64;
EndProcedure

Procedure extmulmod(a.q, b.q, mod.q, *lo.quad, *hi.quad)
  !__int128 result = ((__int128)v_a * (__int128)v_b) % (__int128)v_mod;
  !p_lo->f_q = (quad)result;
  !p_hi->f_q = result >> 64;
EndProcedure

Define a, b, lo, hi

a = $0100000000000001
b = 256

extmul(a, b, @lo, @hi)
Debug StrU(lo, #PB_Quad)
Debug hi

extmulmod(a, b, 10, @lo, @hi)

Debug StrU(lo, #PB_Quad)
Debug hi
P.S.
extmulmod läuft unter macOS und Linux

Windows:
---------------------------
PureBasic - Linker error
---------------------------
error: Unresolved external symbol '__modti3' - referenced from 'PureBasic.obj'.
POLINK: fatal error: 1 unresolved external(s).

Re: Multiplikation von zwei Quads mod andere Quad - ASM to PB?

Verfasst: 16.03.2022 23:14
von STARGÅTE
Hallo mk-soft,

dein erster Code (nur Multiplikation) funktioniert bei mir, danke schon mal dafür.
Beim zweiten Code bekomme ich die folgende Fehlermeldung:
PureBasic - Linker error
---------------------------
error: Unresolved external symbol '__modti3' - referenced from 'PureBasic.obj'.
POLINK: fatal error: 1 unresolved external(s).

Re: Multiplikation von zwei Quads mod andere Quad - ASM to PB?

Verfasst: 16.03.2022 23:37
von mk-soft