Unsigned dword/qword

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
Tenaja
Addict
Addict
Posts: 1959
Joined: Tue Nov 09, 2010 10:15 pm

Re: Unsigned dword/qword

Post 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?
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Unsigned dword/qword

Post 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
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Unsigned dword/qword

Post 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)
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Unsigned dword/qword

Post 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
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Unsigned dword/qword

Post 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
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Unsigned dword/qword

Post 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.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Unsigned dword/qword

Post 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 
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: Unsigned dword/qword

Post by Thunder93 »

Tried.

Code: Select all

PureBasic.asm [259]:
xor rax, rax
error: illegal instruction.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Unsigned dword/qword

Post 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
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Unsigned dword/qword

Post 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?
Windows 11, Manjaro, Raspberry Pi OS
Image
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Unsigned dword/qword

Post 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
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Unsigned dword/qword

Post 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
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Unsigned dword/qword

Post 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
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Unsigned dword/qword

Post 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
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: Unsigned dword/qword

Post 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
Post Reply