How to decompile this x87 assembly?

The program I am changing does a simple multiplication between a floating point number and an 8 byte integer:

section .data va: dt 1.4426950408889634074 vb: dd 0x42424242 dd 0x41414141 section .text global main main: fld tword[va] fmul qword[vb] ret 

Result under gdb:

 Breakpoint 1, 0x08048360 in main () (gdb) x/i $eip 0x8048360 <main>: fld TBYTE PTR ds:0x804953c 0x8048366 <main+6>: fmul QWORD PTR ds:0x8049546 0x804836c <main+12>: ret (gdb) x/gx 0x8049546 0x8049546 <vb>: 0x4141414142424242 (gdb) si 0x08048366 in main () 0x0804836c in main () (gdb) info float =>R7: Valid 0x4014c726039c95268dc4 +3262848.902912714389 

I am trying to recreate this program in C (same 32-bit environment):

 #include <stdio.h> int main() { unsigned long long vb = 0x4141414142424242LL; float r, va = 1.4426950408889634074F; r = va * vb; printf("%f\n", r); } 

... but I get very different results:

 $ ./test 6783712964982603776.000000 

What am I doing wrong in my C program?

+5
source share
2 answers

In asm code, you actually multiply two double by the fmul command, not by float and int . To do something like this in C:

 #include <stdio.h> #include <stdint.h> #include <string.h> int main() { uint64_t vbi = 0x4141414142424242ULL; // hex representation of double double r, vb, va = 1.4426950408889634074; memcpy(&vb, &vbi, sizeof(vb)); // copy hex to double r = va * vb; printf("va = %f, vb = %f, r = %f\n", va, vb, r); return 0; } 

Result = va = 1.442695, vb = 2261634.517647, r = 3262848.902913 .

Live demo

+8
source

This assembler code does not do what you think it does:

 main: fld tword[va] fmul qword[vb] ret 

You suggest a simple multiplication between a floating point number and an 8-byte integer. This is actually a multiplication of a 10-byte extended double floating-point value by an 8-byte double (not an 8-byte integer) represented by 0x414141414242424242. 0x414141414242424242 is considered as a bit of an 8-byte double-floating-point value by your code, not an 8-byte integer converted to a double floating-point value.

The code for what you thought was going on might look something like this:

 main: fild qword[vb] ; Convert 64-bit integer to an extended precision double in st0 fld tword[va] ; st(0)=>st(1) st(0) = 10-byte float(va) fmulp ; Multiply st(0) and st(1). Result in st(0). 

This just clears your misinterpretation of the assembler code.

+3
source

Source: https://habr.com/ru/post/1242217/


All Articles