Page 1 of 1

YASM/NASM define 80-bit variable

Posted: Wed Oct 02, 2019 9:03 am
by ~
To define an 80-bit value we can do:

Code: Select all

dt 0.0

How to do the same if I want to define an 80-bit bitwise variable?

Re: YASM/NASM define 80-bit variable

Posted: Wed Oct 02, 2019 10:26 am
by iansjack
variable: rest 1

Re: YASM/NASM define 80-bit variable

Posted: Wed Oct 02, 2019 10:31 am
by alexfru
~ wrote:To define an 80-bit value we can do:

Code: Select all

dt 0.0
How to do the same if I want to define an 80-bit bitwise variable?
There are no bit/integer operations on 80-bit values in x86. You'll need to compose e.g. a 80-bit XOR using a 64-bit XOR and a 16-bit XOR.
Probably for this reason NASM's DT directive doesn't accept integer constants and requires floating point or packed BCD (the latter suffixed with p or prefixed with 0p, e.g. 33p or 0p33).
If your values are relatively small or simple patterns, you can just use a combination of two directives, e.g.:

Code: Select all

dd bits63_0
dw bits79_64

Re: YASM/NASM define 80-bit variable

Posted: Fri Oct 04, 2019 1:42 am
by ~
I've had to use:

Code: Select all

dq 0000000000000000000000000000000000000000000000000000000000000000b ;0-63
dw                                                                 0000000000000000b ;64-80

or

Code: Select all

dd 00000000000000000000000000000000b  ;0-31
dd                                 00000000000000000000000000000000b ;32-63
dw                                                                 0000000000000000b ;64-80


By now.

Re: YASM/NASM define 80-bit variable

Posted: Fri Oct 04, 2019 2:01 am
by Solar
Smelling a X-Y problem here... what are you wanting a 80-bit variable for?

Are you, by any chance, trying to store a x86 extended precision floating point?

Re: YASM/NASM define 80-bit variable

Posted: Fri Oct 04, 2019 4:58 am
by dseller

Code: Select all

resb 80

Re: YASM/NASM define 80-bit variable

Posted: Fri Oct 04, 2019 5:54 am
by iansjack
I think you mean

resb 10

Re: YASM/NASM define 80-bit variable

Posted: Mon Oct 07, 2019 3:27 am
by dseller
iansjack wrote:I think you mean

resb 10
You're right! For some reason I read 80 bytes. #-o

Re: YASM/NASM define 80-bit variable

Posted: Sat Oct 12, 2019 3:34 pm
by ~
Solar wrote:Smelling a X-Y problem here... what are you wanting a 80-bit variable for?

Are you, by any chance, trying to store a x86 extended precision floating point?
I want to bulk-move 80 bytes of binary data with the FPU (from 8 10-byte registers).

I suspect it would be (and is) a great addition to CPU-intensive applications. Even old CPUs with FPU could move 2 bytes more per operation (and eight 10-byte registers) than with 64-bit instructions.

I already tested it and it's possible (all bits are preserved, or probably unknown ciphers could not be encoded so it can be used at the very least to move raw data or strings).

But you have to disable truncation/rounding, maybe some FPU interrupts and enable full precision.

It needs no special instructions and is even better than a 64-bit data move loop:

Code: Select all

;It can make 0xFFFFFFFF iterations in
;around 1:09.05 minutes in a dual core
;at 3.4GHz (less than 1:12 minutes).
;;


;It could be extended with all GPRs
;to move through the destination pointer
;every 10 bytes (70 bytes for EAX,
;EBX, ECX, EDX, ESI, EDI, EBP and maybe
;ESP with which we address for the
;80-byte FPU stack)
;instead of subtracting a single one, or a
;2-pointer struct for the initial source and
;destination values for each general-purpose
;register.
;
;Param 1 -- Source register value
;Param 2 -- Destination register value
;;
%macro MICRO_LONG__move_80_bytes_with_x87_FPU 2

 ;Load the whole FPU stack:
 ;;
  add %1,10*7       ;Move to the last TWORD of the 8
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]
  sub %1,10
  fld tword[%1]


 ;Copy 10 bytes at a time:
 ;;
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]
  add %2,10
  fstp tword[%2]



%endmacro


  ;;INIT: Initialize the FPU for this program
  ;;INIT: Initialize the FPU for this program
  ;;INIT: Initialize the FPU for this program
  ;;INIT: Initialize the FPU for this program

   ;Initialize the FPU to its default state and configuration
   ;after checking for pending unmasked floating-point exceptions:
   ;;
    finit

   ;Wait for any pending FPU operations
   ;or exceptions and clear any
   ;pending exceptions:
   ;;
    fclex

   ;Load new x87 Control Word
   ;into FPU control register:
   ;;
    fldcw [x87_FPU_New_Control_Word]



  ;;END:  Initialize the FPU for this program
  ;;END:  Initialize the FPU for this program
  ;;END:  Initialize the FPU for this program
  ;;END:  Initialize the FPU for this program






align 4,db 0						 
						 x87_FPU_New_Control_Word equ $+ImageBase-__data_RVA_Localize__
                         dw 0001111110111111b
;                              -__--_ -_-_-_
;                              ||  || ||||||
;                              ||  || ||||||
;                              ||  || ||||||
;                              ||  || ||||||
;                              ||  || ||||| ---- 0 - IM - Invalid Operation Interrupt Mask (exception):
;                              ||  || |||||               0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  || |||||               1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  || |||||
;                              ||  || |||| ----- 1 - DM - Denormalized Interrupt Mask (exception):
;                              ||  || ||||                0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  || ||||                1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  || ||||
;                              ||  || ||| ------ 2 - ZM - Zero Divide Interrupt Mask (exception):
;                              ||  || |||                 0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  || |||                 1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  || |||
;                              ||  || || ------- 3 - OM - Overflow Interrupt Mask (exception):
;                              ||  || ||                  0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  || ||                  1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  || ||
;                              ||  || | -------- 4 - UM - Underflow Interrupt Mask (exception):
;                              ||  || |                   0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  || |                   1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  || |
;                              ||  ||  --------- 5 - PM - Precision Interrupt Mask (exception):
;                              ||  ||                     0: Generate INT/IRQ (disable handling at the FPU).
;                              ||  ||                     1: Do not generate INT/IRQ (selected at initialization, enable handling at the FPU).
;                              ||  ||
;                              ||  | ---------- 7 - IEM - Interrupt Enable Mask (global for INT bits 0-5):
;                              ||  |                      0: Enable interrupts.
;                              ||  |                      1: Disable interrupts (selected at initialization).
;                              ||  |
;                              ||   ---------- 8-9 - PC - Precision Control:
;                              ||                         00b: 24 bits (REAL4).
;                              ||                         01b: Unused.
;                              ||                         10b: 53 bits (REAL8).
;                              ||                         11b: 64 bits (REAL10, selected at initialization).
;                              ||
;                              | ----------- 10-11 - RC - Rounding Control:
;                              |                          00b: Round to nearest, or to even if equidistant (selected at initialization).
;                              |                          01b: Round down (towards -Infinity).
;                              |                          10b: Round up (towards +Infinity).
;                              |                          11b: Truncate (towards 0).
;                              |
;                               --------------- 12 - IC - Infinity Control (more modern CPUs always use -Infinity and +Infinity):
;                                                         0: Use unsigned Infinity (selected at initialization).
;                                                         1: Respect -Infinity and +Infinity.
;
;
;
;
;
;

Code: Select all

;INIT: Main benchmark
;INIT: Main benchmark
;INIT: Main benchmark
;INIT: Main benchmark

  mov widecx,0
  mov widesi,source_10_byte_buffer_or_String_10_byte_end
  move widedi,dest_buffer
  align wideword_sz
  .tttt:

    MICRO_LONG__move_80_bytes_with_x87_FPU widesi,widedi


  dec widecx
  jnz .tttt


;END:  Main benchmark
;END:  Main benchmark
;END:  Main benchmark
;END:  Main benchmark


Re: YASM/NASM define 80-bit variable

Posted: Sat Oct 12, 2019 9:59 pm
by reapersms
If you're on something new enough to run at 3.4 ghz you can use the sse instructions and move 16 bytes at a time.

The rounding issues aside, certain mobile targeted x86 chips (jaguar) really don't like it if you use the old x87 fpu or mms instructions, and reserve register rename slots for them indefinitely.

If you're targeting something from the last 15 years, it is strongly recommended to just use the xmm regs for everything.

Re: YASM/NASM define 80-bit variable

Posted: Sun Oct 13, 2019 1:13 am
by iansjack
The 80-bit floating-point instructions are pretty slow compared to the integer or multimedia move instructions. I suspect that you have discovered the slowest way of moving memory.

Re: YASM/NASM define 80-bit variable

Posted: Sun Oct 13, 2019 1:50 pm
by Octocontrabass
iansjack wrote:I suspect that you have discovered the slowest way of moving memory.
According to these tables, with a bit of optimization it's pretty close to the fastest way to move memory on an 8088. I'm not sure it's possible to beat REP MOVSW though.

It's nowhere near the fastest option on any other CPU.

Re: YASM/NASM define 80-bit variable

Posted: Sun Oct 13, 2019 2:57 pm
by iansjack
But you can't assume that an 8088 has a floating-point unit. Most of them didn't. So, on average, on an 8088 it just wouldn't work.

I have to admit that I wasn't considering obsolete processors.