Page 4 of 6
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 1:33 am
by Tenaja
idle wrote:I'm spamming the thread now might have to moderate myself;
I don't have an x86 vm setup at the moment or windows either
so this should hopefully work now and I'll go back and edit my spam !
Code: Select all
CompilerIf SizeOf(Integer) = 8
Macro edx : rdx : EndMacro
CompilerEndIf
Macro EnableUnsigned()
!macro IDIV var
!{
!xor edx,edx
!div var
!}
!macro SAR reg,var
!{
!shr reg,var
!}
!macro SAL reg,var
!{
!shl reg,var
!}
EndMacro
Macro DisableUnsigned()
!purge IDIV
!purge SAR
!purge SAL
UndefineMacro EnableUnsigned
EndMacro
Procedure Unsigned(arg1.i,op1.l,arg2.i)
Select op1
Case '<'
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setb al
ProcedureReturn
Case '<='
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setbe al
ProcedureReturn
Case '>'
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!seta al
ProcedureReturn
Case '>='
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setae al
ProcedureReturn
Case '='
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!sete al
ProcedureReturn
Case '<>'
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setne al
ProcedureReturn
EndSelect
EndProcedure
x.l=$FFFFFFFF
y.l=$FFFFFFFE
If Unsigned(x,'>=',y/2) ; unsigned comparison.
Debug "OK"
EnableUnsigned()
Debug y / 2
y<<1
DisableUnsigned()
Debug y / 2
EndIf
Can you post your final working code in Tips & Tricks?
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 2:12 am
by idle
@Tenaja, yes once it's working properly!
there are still some issues to resolve, think I've sorted the unsigned macro
but I'm still trying to get the unsigned div to work
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 3:07 am
by Keya
BRILLIANT WORK, IDLE!!!!!!!!!!!!

only just got to test it a second ago but looks good!!!
operators, evaluations... but also some functions!? im not sure how many
Code: Select all
EnableUnsigned()
Debug y / 2 ;Good (unsigned)
Debug Str(y / 2) ;Bad(?) (signed)
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 4:52 am
by idle
it might be ok now I'm was trying to work out how to patch MOVSXD with an fasm macro
pb outputs
Code: Select all
MOVSXD r15,dword [v_y]
MOV rax,r15
MOV rcx,2
CQO
IDIV rcx
MOV r15,rax
which creates a problem sign extending the input, I tried substituting it with lea but that didn't work out
so I resorted to a match which might be ok!
it's currently working for x64 don't know for x86 might need adapting
Code: Select all
CompilerIf SizeOf(Integer) = 8
Macro edx : rdx : EndMacro
CompilerElse
Macro rax : eax : EndMacro
CompilerEndIf
Macro EnableUnsigned()
!macro IDIV var
!{
!mov edx,0
!div var
!}
!macro SAR reg,var
!{
!shr reg,var
!}
!macro SAL reg,var
!{
!shl reg,var
!}
!macro MOVSXD reg,var
!{
!match =dword x , var
!\{ mov eax, var
!mov reg,rax \}
!}
EndMacro
Macro DisableUnsigned()
!purge IDIV
!purge SAR
!purge SAL
!purge MOVSXD
UndefineMacro EnableUnsigned
EndMacro
Procedure Unsigned(arg1.i,op1.l,arg2.i)
EnableASM
Select op1
Case '<'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setb al
ProcedureReturn
Case '<='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setbe al
ProcedureReturn
Case '>'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!seta al
ProcedureReturn
Case '>='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setae al
ProcedureReturn
Case '='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!sete al
ProcedureReturn
Case '<>'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setne al
ProcedureReturn
EndSelect
EndProcedure
Global x.l,y.l
x=$1
y=$FFFFFFFE
Debug y ;Hex(y,#PB_Long)
y / 2
Debug y ;Hex(y,#PB_Long)
EnableUnsigned()
y=$FFFFFFFE
If Unsigned(x,'<=',y) ; unsigned comparison.
Debug "OK"
y / 2
Debug y ;Hex(y,#PB_Long) ;7FFFFFFF
y << 1
Debug y ;Hex(y ,#PB_Long) ;FFFFFFFE
DisableUnsigned()
Debug y
y / 2
Debug y ;Hex(y,#PB_Long)
EndIf
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 5:46 am
by Thunder93
PureBasic.asm [274]:
xor rax, rax
error: illegal instruction.
PBx86 under Win x64
-----------
Debug Output from PBx64:
Code: Select all
FFFFFFFE
FFFFFFFF
OK
2147483647
4294967294
-1
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 6:04 am
by wilbert
Replacing asm instructions like this would be highly unpredictable and unstable.
There might be places in the source code where PB outputs one of these instructions where you don't expect it.
Also for example the macro for IDIV. You are replacing edx with zero. But when you do a quad division on x86, edx might be used also (not sure).
Separate procedures for different unsigned operations are a much better approach.
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 6:06 am
by idle
try changing this compilerif
Code: Select all
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
CompilerElse
Macro edx : rdx : EndMacro
CompilerEndIf
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 6:19 am
by Thunder93
Tried.
Code: Select all
PureBasic.asm [259]:
xor rax, rax
error: illegal instruction.
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 6:19 am
by wilbert
Here's my simple suggestion for comparing
Code: Select all
Procedure UComp(a.i, b.i)
; output -1 when a < b
; output 0 when a = b
; output 1 when a > b
CompilerIf SizeOf(Integer) = 8
!mov rdx, [p.v_a]
!cmp rdx, [p.v_b]
!setnz dl
!sbb rax, rax
CompilerElse
!mov edx, [p.v_a]
!cmp edx, [p.v_b]
!setnz dl
!sbb eax, eax
CompilerEndIf
!or al, dl
ProcedureReturn
EndProcedure
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 6:56 am
by idle
wilbert wrote:Replacing asm instructions like this would be highly unpredictable and unstable.
There might be places in the source code where PB outputs one of these instructions where you don't expect it.
Also for example the macro for IDIV. You are replacing edx with zero. But when you do a quad division on x86, edx might be used also (not sure).
Separate procedures for different unsigned operations are a much better approach.
It's easy enough to make regular pb macros to do it, but it doesn't fit syntactically with what people want.
the only issue I think for unpredictability would be with movsxd but as long as the macro is enabled and disabled appropriately
it should trap it.
zeroing edx / rdx should be fine for the native integer size, as for unsigned quads on x86 yes it will probably need another approach but is it really needed?
The issues with signed types only rears it self on pointer arithmetic (native size) and passing to the odd lib function.
are there other ops to consider than movsx idiv and the tests on flags from cmp?
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 7:14 am
by wilbert
idle wrote:are there other ops to consider than movsx idiv and the tests on flags from cmp?
CWD, CDQ, CQO, maybe IMUL
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 11:07 am
by idle
not sure if fasm macros will eat CQO and related ops, will have to check the disassembly
here's the latest, x64 only at the moment
Code: Select all
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
CompilerElse
Macro edx : rdx : EndMacro
CompilerEndIf
Macro EnableUnsigned()
!macro IDIV var
!{
!mov edx,0
!div var
!}
!macro IMUL reg,var
!{
!mul reg
!mov reg,rax
!}
!macro SAR reg,var
!{
!shr reg,var
!}
!macro SAL reg,var
!{
!shl reg,var
!}
!macro MOVSXD reg,var
!{
!match =dword x , var
!\{ mov eax, var
!mov reg,rax \}
!}
!macro CQO {}
!macro CDO {}
!macro CWD {}
!macro CBW {}
!macro CWDE{}
!macro CDQE {}
EndMacro
Macro DisableUnsigned()
!purge IDIV
!purge IMUL
!purge SAR
!purge SAL
!purge MOVSXD
!purge CQO
!purge CDO
!purge CWD
!purge CBW
!purge CWDE
!purge CDQE
UndefineMacro EnableUnsigned
EndMacro
Procedure Unsigned(arg1.i,op1.l,arg2.i)
EnableASM
Select op1
Case '<'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setb al
ProcedureReturn
Case '<='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setbe al
ProcedureReturn
Case '>'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!seta al
ProcedureReturn
Case '>='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setae al
ProcedureReturn
Case '='
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!sete al
ProcedureReturn
Case '<>'
!xor rax,rax
!mov edx, [p.v_arg1]
!cmp edx, [p.v_arg2]
!setne al
ProcedureReturn
EndSelect
EndProcedure
Global x.l,y.l
x=2
y=$FFFFFFFE
Debug y
y / 2
Debug y
EnableUnsigned()
y=$FFFFFFFE
If Unsigned(x,'<=',y) ; unsigned comparison.
Debug "OK"
y / 2
Debug y ;Hex(y,#PB_Long) ;7FFFFFFF
y * x
Debug y ;Hex(y ,#PB_Long) ;FFFFFFFE
y >> 1
Debug y ;Hex(y ,#PB_Long) ;FFFFFFFE
y << 1
Debug y
y - x
Debug y
y + x
Debug Str(y)
DisableUnsigned()
Debug Str(y)
y / 2
Debug y ;Hex(y,#PB_Long)
EndIf
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 11:11 am
by Keya
i dont understand why it's complaining about "illegal instruction: xor rax, rax" in x86 because the rax->eax macro is supposed to take care of that. Weird!
Anyway I did a manual global replace of 'rax' to 'eax', and removed the eax macro, and it compiles and outputs:
Code: Select all
-2
-1
OK
2147483647
-2147348480
1073809408
-2147348480
-2147348482
-2147348480
-2147348480
-1073674240
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 11:17 am
by wilbert
Keya wrote:i dont understand why it's complaining about "illegal instruction: xor rax, rax" in x86 because the rax->eax macro is supposed to take care of that.
That macro substituting rax with eax, only works for lines of code without an exclamation mark.
So you would have to replace all
!xor rax,rax with
xor rax,rax
Re: Unsigned dword/qword
Posted: Thu Mar 24, 2016 11:19 am
by Keya
spot on wilbert!

i just simply replaced "! xor rax, rax" with "xor rax, rax" as per your suggestion and it compiles smoothly now