🌟 IsDiffInRange, IsSumInRange, & IsProductInRange Macros for Various Data Types

Started by Theo Gottwald, April 13, 2024, 02:44:56 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

**🌟 IsDiffInRange, IsSumInRange, & IsProductInRange Macros for Various Data Types 🌟**

These samples demonstrate how DOUBLE, SINGLE, and EXTENDED data types can be utilized in x86 ASM to perform operations.

**📋 Overview:**
The **IsProductInRange** macros are designed to check if the product of two numbers (n1 and n2) falls within a specified range (allow). They return a LONG value:
- **1** 🟢: Product is within the range.
- **0** 🔴: Product is outside the range.

**🔧 Macro List:**
- IsProductInRange_Double(n1, n2, allow)
- IsProductInRange_Single(n1, n2, allow)
- IsProductInRange_Extended(n1, n2, allow)

**📐 Parameters:**
- **n1**: First number.
- **n2**: Second number.
- **allow**: Specified range.

**📝 Usage:**
```asm
result = IsProductInRange_Double(n1, n2, allow)
```
Replace `n1`, `n2`, and `allow` with your actual numbers or variables, and `result` with a variable to store the return value.

**💡 Additional Information:**
These macros leverage the x87 FPU for calculations and comparisons, using the FPU stack and flags to determine results. The macros return a LONG value, but can be adapted to return a byte.

Feel free to integrate these in your projects and share your experiences! 🚀


'------------------------------------------------------------------------------------------------
' Only for use with DOUBLE
' Originalname: zSignedInRangeFPU
MACRO FUNCTION IsDiffInRange_Double(n1, n2, allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fild n1         'get the first number (Double)
!fisub n2        'subtract the second number
!fabs            'make result positive
!fild allow      'get the range
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret
'------------------------------------------------------------------------------------------------
' (n1 AS SINGLE, n2 AS SINGLE, allow AS SINGLE)
MACRO FUNCTION IsDiffInRange_Single(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!filds n1        'get the first number (Single)
!fisub n2        'subtract the second number
!fabs            'make result positive
!filds allow     'get the range (Single)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret
'------------------------------------------------------------------------------------------------
' (n1 AS EXTENDED, n2 AS EXTENDED, allow AS EXTENDED)
'
MACRO FUNCTION IsDiffInRange_Extended(n1, n2, allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fld n1          'get the first number (Extended)
!fisub n2        'subtract the second number
!fabs            'make result positive
!fld allow       'get the range (Extended)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret
'------------------------------------------------------------------------------------------------
' These macros check if the sum of two numbers (n1 and n2) is within the specified range (allow).
' They return a LONG value, with 1 indicating that the sum is within the specified range, and 0 indicating that the sum is outside the specified range.
' (n1 AS DOUBLE, n2 AS DOUBLE, allow AS DOUBLE)
MACRO FUNCTION IsSumInRange_Double(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fild n1         'get the first number
!fiadd n2        'add the second number
!fabs            'make result positive
!fild allow      'get the range
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret


'------------------------------------------------------------------------------------------------
'  (n1 AS SINGLE, n2 AS SINGLE, allow AS SINGLE)
MACRO FUNCTION IsSumInRange_Single(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!filds n1        'get the first number (Single)
!fiadds n2       'add the second number (Single)
!fabs            'make result positive
!filds allow     'get the range (Single)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret

'------------------------------------------------------------------------------------------------
' (n1 AS EXTENDED, n2 AS EXTENDED, allow AS EXTENDED)
MACRO FUNCTION IsSumInRange_Extended(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fld n1          'get the first number (Extended)
!fiadd n2        'add the second number (Extended)
!fabs            'make result positive
!fld allow       'get the range (Extended)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret
'------------------------------------------------------------------------------------------------
' These macros use the x87 FPU (Floating Point Unit) to perform the calculations and comparisons.
' The FPU stack is used to store and manipulate the values, and the FPU flags are used to determine the result of the comparison.
' The macros return a LONG value, but this can be changed to return a byte by removing the
' !xor ecx, ecx line and replacing !mov ret, ecx with !mov ret, cl.
'------------------------------------------------------------------------------------------------
'  (n1 AS DOUBLE, n2 AS DOUBLE, allow AS DOUBLE)
MACRO FUNCTION IsProductInRange_Double(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fild n1         'get the first number
!fimul n2        'multiply the first number with the second number
!fabs            'make result positive
!fild allow      'get the range
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret

'------------------------------------------------------------------------------------------------
'  (n1 AS SINGLE, n2 AS SINGLE, allow AS SINGLE)
MACRO FUNCTION IsProductInRange_Single(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!filds n1        'get the first number (Single)
!fimuls n2       'multiply the first number with the second number (Single)
!fabs            'make result positive
!filds allow     'get the range (Single)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret

'------------------------------------------------------------------------------------------------
' (n1 AS EXTENDED, n2 AS EXTENDED, allow AS EXTENDED)
MACRO FUNCTION IsProductInRange_Extended(n1, n2,allow)
  MACROTEMP ret
  DIM ret AS LONG

!xor ecx,ecx     'only needed if you need to return a LONG. If you can return a byte then remove this.
!fld n1          'get the first number (Extended)
!fimul n2        'multiply the first number with the second number (Extended)
!fabs            'make result positive
!fld allow       'get the range (Extended)
!fcompp          'compare the positive result with the range and pop both from the FPU stack so stack is now empty

!fstsw ax        'get FPU flags to ax
!sahf            '..and from ax into the CPU flags

!setae cl        'set CL conditional on the flags. cl now contains the return value of 1 or 0.
!mov ret,ecx     'return the whole of ecx but could just return cl

ExitNow:
END MACRO = ret

'------------------------------------------------------------------------------------------------