flat assembler
Message board for the users of flat assembler.

 Index > Main > load 128 bit signed integer to st0
Author
petelomax

Joined: 19 Jan 2013
Posts: 11
Location: London
petelomax 31 Jul 2017, 09:44
OK, I am starting to feel a little stupid now.. I have a 128-bit signed integer in rdx:rax, how do I get it (or a reasonable representation of it) into st0?

It is in an error handler, so neither speed nor pin-point accuracy is an issue, but getting 0 or -Infinity, the best I have yet managed, just because it is 65 bits (about 3e19) is not on!

Pete
31 Jul 2017, 09:44
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 20242
revolution 31 Jul 2017, 10:23
I guess the process could be like this:
1. Scan the integer for the most significant bit (note that negative numbers make this a little bit tricky).
2. Shift it left to move out the higher bits.
3. Load the highest 64-bit part of the integer into st0.
4. Scale st0 into range by the amount you shifted in step 2.
31 Jul 2017, 10:23
Furs

Joined: 04 Mar 2016
Posts: 2473
Furs 31 Jul 2017, 12:28
Load rax into st1, rdx into st0, multiply st0 by 2^64 (adjusting exponent only really), add st0 and st1 and pop?

EDIT: hmm seems the numbers are signed, I guess you'll have to convert them to abs value somehow (not individually) or the simple method won't work
31 Jul 2017, 12:28
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 8347
Location: Kraków, Poland
Tomasz Grysztar 31 Jul 2017, 15:25
The 80-bit format used by FPU is actually quite simple and you can do such conversion without any FPU instructions. I quickly scribbled this version:
Code:
```int128_to_float80:
; in: rdx:rax = singed 128-bit integer
; out: dx:rax = 80-bit float
test    rdx,rdx
jns     uint128_to_float80
not     rdx     ;\
not     rax     ; \  this is just a
add     rax,1   ; /  neg rdx:rax
call    uint128_to_float80
or      dx,8000h
retn
uint128_to_float80:
; in: rdx:rax = unsigned 128-bit integer
; out: dx:rax = 80-bit float
bsr     r8,rdx
jz      .low
mov     cl,63
sub     cl,r8l
shld    rdx,rax,cl
mov     rax,rdx
lea     rdx,[16383+64+r8]
retn
.low:
bsr     r8,rax
jz      .zero
mov     cl,63
sub     cl,r8l
shl     rax,cl
lea     rdx,[16383+r8]
retn
.zero:
xor     eax,eax
xor     edx,edx
retn    ```
Since you need the result in ST0, you'd have to use it like this:
Code:
```        call    int128_to_float80
mov     qword [tmp],rax
mov     word [tmp+8],dx
fld     tword [tmp]    ```
31 Jul 2017, 15:25
Furs

Joined: 04 Mar 2016
Posts: 2473
Furs 31 Jul 2017, 15:56
You could shave off a few instructions with lzcnt instead of bsr (check the carry flag instead of zero though).

(also if optimizing for size -- xor eax, eax/xor edx, edx can be replaced by xor eax, eax/cdq)
31 Jul 2017, 15:56
petelomax

Joined: 19 Jan 2013
Posts: 11
Location: London
petelomax 31 Jul 2017, 19:49
Tomasz Grysztar wrote:
I quickly scribbled this version:

Excellent stuff, works perfectly.

As a bonus, I don't feel quite so stupid for asking now!

Many thanks,
Pete
31 Jul 2017, 19:49
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum