News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Convert SDWORD to real8 in asm file

Started by Gaurav, March 04, 2010, 04:52:27 PM

Previous topic - Next topic

Gaurav

Hi, Im new here.  :bg
Im taking an assembly class and the code I need to do is very complex (to me)
:eek

TITLE Power in Floating Point Values
; This code is supposed to n1absolute value(n2) and store it in power
; I've managed to declare, initialize float variables and print them successfully


.386
.model flat, stdcall
option casemap :none

include \masm32\include\masm32rt.inc

.data
; all these variables used to be SDWORD
n1 real8 0.0 ; declaring and initializing a floating-point value with 8 bytes
n2 real8 0.0 ; same^
power real8 1.0 ; same^
n2prnt real8 0.0 ; used for printing the value of n2 b/c n2 changes in the code

.code
start:

; change to float values errors start here
mov n1, sval(input("Enter a value for n1: ")) ; how to move?
mov n2, sval(input("Enter a value for n2: "))
mov ebx, n2
mov n2prnt, ebx

cmp n2, 0.0 ; how to compare?
jl movtoabs
jmp wileloop

movtoabs:
    xor eax, eax
    sub eax, n2 ; how to subtract?
    mov n2, eax
    xor eax, eax

wileloop:
    cmp n2, 0
    jg powerade
    jmp done

powerade:
    mov eax, power
    imul n1 ; how to multiply?
    mov power, eax
    xor eax, eax
    dec n2 ; how to decrement?
    jmp wileloop
; errors done here


done:
    invoke crt_printf,chr$("The value of n1 is: %f%c"),n1,10
    invoke crt_printf,chr$("The value of n2 is: %f%c"),n2,10
    invoke crt_printf,chr$("The power of the two values is: %f%c"),power,10

inkey
exit
end start

Can someone help to fix this code?

clive

The CPU registers don't work with floating point values, you need to be using the floating point unit (FPU). The opcodes begin with Fxxxx

The FPU might also be referred to as a floating point coprocessor, 8087, x87

-Clive
It could be a random act of randomness. Those happen a lot as well.

Gaurav


oex

x86
mov
add

FPU
fld
fadd
fstp

Look under Help->FPU Lib Help Menu in Quick Editor
We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

Gaurav

(big ! circle)Navigation to the webpage was canceled

What you can try:
-  Retype the address

I tried going to FPU Help but this is what I got

but I can see the available functions like
FpuAbs
FpuAdd

and stuff
help?

oex

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

dedndave

it should work
but, the same thing is available online
Ray is our resident FPU guru...

http://www.ray.masmcode.com/tutorial/index.html

oex

We are all of us insane, just to varying degrees and intelligently balanced through networking

http://www.hereford.tv

dedndave


GregL

#9
Gaurav,

Just to get you started in the right direction. I think you can figure out the rest from Simply FPU.


.DATA

    n1    SDWORD -5
    r1    REAL8  0.0

.CODE

  start:
 
    finit
    fild n1
    fstp r1



This converts an SDWORD to a REAL8.

clive

Now if n2 can be a 32-bit integer, we can use this method. Still you're not going to learn anything if other people do all the thinking.
-Clive


..

        fld1                    ; x = 1 Load 1 into the 80x87

        mov     eax,n2          ; Where n2 is an integer
        cdq                     ; ABS(eax)
        xor     eax,edx
        sub     eax,edx
        jz      label_40        ; is zero, n1**0 = 1

        fld     qword ptr n1    ; y = n1

label_10:

        test    al,1            ; Is LSB set
        jz      label_20

        fmul    st(1),st        ; x = x * y

label_20:

        shr     eax,1
        jz      label_30        ; Continue if non zero

        fmul    st,st(0)        ; y = y * y

        jmp     label_10

label_30:

        fstp    st              ; Pop y

label_40:

        fstp    qword ptr power ; Pop x

..

n1      real8   10.0
n2      dd      -3
power   real8   ?
It could be a random act of randomness. Those happen a lot as well.

clive

Somehow I think the value of n1 should be the absolute value, as it needs to be positive.
Referring to a couple of books and manuals, the following seems to be a semi workable solution where both n1 and n2 are doubles, and n1 is positive.
-Clive

; x**y = 2**(y*log2(x))
; x**y = 1 + (2**(y*log2(x)) - 1)
; x**y = (1 + (2**(frac(y*log2(x)) - 1))) * 2**int(y*log2(x))

fld qword ptr n2 ; y
fabs ; y = abs(y)
fld qword ptr n1 ; x
fyl2x ; b = y*log2(x)
fld st(0) ; dup(b)
frndint         ; int = int(b)
fsub    st(1),st(0) ; frac = b - int
fld1 ; 1
fscale         ; 1 << int (2**int)
fstp    st(1)   ; discard int
fxch ; swap st(0) and st(1)
f2xm1 ; a = (2**frac - 1) where  0 <= frac <= 0.5
fld1 ; 1
fadd ; += 1
fmul ; * 2**int
fstp qword ptr power
It could be a random act of randomness. Those happen a lot as well.

raymond

Gaurav,

If you are taking a newbie class in assembly, I doubt very much that the teacher is expecting the students to know all the details of programming floating point math. Using macros and/or libraries should thus be very acceptable to him.

I would suggest you download the latest version of the Fpulib which is more liberal with the float size you can use (older versions only allowed REAL10).
http://www.ray.masmcode.com/fpu.html#fpulib

Unzip the content into your existing MASM32/fpulib folder, overwriting all the files if prompted.
Then run the MAKE.BAT file.
Also transfer the Fpulib.chm file to the MASM32/help folder, overwriting the existing one. You don't need to be connected to the Internet to access that file.

One of your questions which has not been answered was how to convert your input to a float. One possibility is to store the input as a string and use the FpuAtoFL function from the Fpulib to convert that string to a float and store it wherever you want.

As clive mentioned, the n1 value must be positive. If the input is a negative number, it must NOT be processed but a message returned to indicate that such a number is not acceptable as input. Converting it to a positive number and processing it would be wrong since the returned value would thus not reflect reality. (The Fpulib contains a function FpuXexpY to raise any positive number to any power.

If you really want to understand what you are doing, I would strongly suggest that you study the source code of the functions you will be using. And, while at the above link, you can also download the FPU tutorial. Be sure to read the first two chapters which describe (i) the FPU internals and (ii) the floating point format with its limitations.

Wish you the best in your studies.
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com

Gaurav

Hey raymond,

I transferred the fpulib.chm to the MASM32/help folder and i also opened it but it still says the navigation to the webpage was canceled for some odd reason...
I also opened it from the original zip file and it works.. Idk what the problem is

Also, I am taking a newbie college course and the floating point math is just extra credit for a project that I already finished and probably not due in a month or so.

But the assignment was to do ~n1abs(n2) = power~ so... is there such a function to do that?

Btw clive, I'm using q-editor and the command prompt cant assemble st(0)/st(1) code... what is it?

What datatype is a string?

clive

Quote from: Gaurav on March 05, 2010, 04:34:45 PM
But the assignment was to do ~n1abs(n2) = power~ so... is there such a function to do that?

No, the 80x87 is a binary machine, it does not directly support 10**x, e**x, log10(x) or ln(x), it performs operations like 2**x and log2(x). You have to use these more limited functions, along with constants and other optimized instructions to achieve the work. The core operates efficiently with simple operations, you have to perform more individual operations to do more complex operations.

The following book by the designers of the 8087 is a good reference on the part, and explains some of the functions, trade-offs, precision and optimizations used.
http://www.amazon.com/8087-Primer-John-F-Palmer/dp/0471875694/ref=sr_1_1?ie=UTF8&s=books&qid=1267809630&sr=1-1

The code provided is a fairly concise expression of your function, although probably not optimal. In C you could use "power = pow(n1, fabs(n2));", but all you are doing is abstracting the underlying complexity into the library code doing pretty much what is being described here.

QuoteBtw clive, I'm using q-editor and the command prompt cant assemble st(0)/st(1) code... what is it?

They refer to the stack top relative registers within the 80x87 floating point unit, it contains 8 extended precision floating point registers (80-bit) which work on a stacked basis. For example fabs takes the top register off the stack, and pushes back the absolute value. The fadd will by default pull off the top two values, and push back the sum of the two.

I was using the inline assembler within Microsoft C, but it also works in MASM. I also tried a slightly different encoding my disassembler spits out, which also works.

-Clive

Microsoft (R) Macro Assembler Version 6.15.8803     03/05/10 11:09:08
test2.asm      Page 1 - 1


        .486
        .MODEL FLAT

00000000         .CODE

00000000 test2: ; Code fragment, will need additional harness

00000000  DD 05 00000008 R              fld     qword ptr [n2]
00000006  D9 E1              fabs
00000008  DD 05 00000000 R              fld     qword ptr [n1]
0000000E  D9 F1              fyl2x
00000010  D9 C0              fld     st(0)
00000012  D9 FC              frndint
00000014  DC E9              fsub    st(1),st
00000016  D9 E8              fld1
00000018  D9 FD              fscale
0000001A  DD D9              fstp    st(1)
0000001C  D9 C9              fxch    st(1)
0000001E  D9 F0              f2xm1
00000020  D9 E8              fld1
00000022  DE C1              faddp   st(1),st
00000024  DE C9              fmulp   st(1),st
00000026  DD 1D 00000010 R              fstp    qword ptr [power]

00000000         .DATA

00000000 n1      real8   2.5
   4004000000000000
00000008 n2      real8   2.5
   4004000000000000
00000010 power   real8   ?
   0000000000000000

        END     test2

Microsoft (R) Macro Assembler Version 6.15.8803     03/05/10 11:09:08
test2.asm      Symbols 2 - 1




Segments and Groups:

                N a m e                 Size     Length   Align   Combine Class

FLAT . . . . . . . . . . . . . . GROUP
_DATA  . . . . . . . . . . . . . 32 Bit 00000018 Para   Public  'DATA'
_TEXT  . . . . . . . . . . . . . 32 Bit 0000002C Para   Public  'CODE'


Symbols:

                N a m e                 Type     Value    Attr

@CodeSize  . . . . . . . . . . . Number 00000000h
@DataSize  . . . . . . . . . . . Number 00000000h
@Interface . . . . . . . . . . . Number 00000000h
@Model . . . . . . . . . . . . . Number 00000007h
@code  . . . . . . . . . . . . . Text    _TEXT
@data  . . . . . . . . . . . . . Text    FLAT
@fardata?  . . . . . . . . . . . Text    FLAT
@fardata . . . . . . . . . . . . Text    FLAT
@stack . . . . . . . . . . . . . Text    FLAT
n1 . . . . . . . . . . . . . . . QWord 00000000 _DATA
n2 . . . . . . . . . . . . . . . QWord 00000008 _DATA
power  . . . . . . . . . . . . . QWord 00000010 _DATA
test2  . . . . . . . . . . . . . L Near 00000000 _TEXT

   0 Warnings
   0 Errors
It could be a random act of randomness. Those happen a lot as well.