YASM/NASM define 80-bit variable

Programming, for all ages and all languages.
Post Reply
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

YASM/NASM define 80-bit variable

Post 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?
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
User avatar
iansjack
Member
Member
Posts: 4689
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: YASM/NASM define 80-bit variable

Post by iansjack »

variable: rest 1
alexfru
Member
Member
Posts: 1111
Joined: Tue Mar 04, 2014 5:27 am

Re: YASM/NASM define 80-bit variable

Post 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
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: YASM/NASM define 80-bit variable

Post 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.
YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: YASM/NASM define 80-bit variable

Post 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?
Every good solution is obvious once you've found it.
dseller
Member
Member
Posts: 84
Joined: Thu Jul 03, 2014 5:18 am
Location: The Netherlands
Contact:

Re: YASM/NASM define 80-bit variable

Post by dseller »

Code: Select all

resb 80
User avatar
iansjack
Member
Member
Posts: 4689
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: YASM/NASM define 80-bit variable

Post by iansjack »

I think you mean

resb 10
dseller
Member
Member
Posts: 84
Joined: Thu Jul 03, 2014 5:18 am
Location: The Netherlands
Contact:

Re: YASM/NASM define 80-bit variable

Post by dseller »

iansjack wrote:I think you mean

resb 10
You're right! For some reason I read 80 bytes. #-o
User avatar
~
Member
Member
Posts: 1226
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: YASM/NASM define 80-bit variable

Post 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

YouTube:
http://youtube.com/@AltComp126

My x86 emulator/kernel project and software tools/documentation:
http://master.dl.sourceforge.net/projec ... 7z?viasf=1
reapersms
Member
Member
Posts: 48
Joined: Fri Oct 04, 2019 10:10 am

Re: YASM/NASM define 80-bit variable

Post 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.
User avatar
iansjack
Member
Member
Posts: 4689
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: YASM/NASM define 80-bit variable

Post 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.
Octocontrabass
Member
Member
Posts: 5517
Joined: Mon Mar 25, 2013 7:01 pm

Re: YASM/NASM define 80-bit variable

Post 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.
User avatar
iansjack
Member
Member
Posts: 4689
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: YASM/NASM define 80-bit variable

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