The program I'm reversing does simple multiplication between float number and 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'm trying to recreate this program in C (same 32bit 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 I'm doing wrong in my C program?
In the asm code you're actually multiplying two double
s with the fmul
instruction, not a float
and an int
. To do something similar 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
This assembler code is not doing what you think it is doing:
main:
fld tword[va]
fmul qword[vb]
ret
You suggest simple multiplication between float number and 8 byte integer . This is actually multiplication of a 10-byte extended double floating point value by the 8-byte double (not 8-byte integer) represented by 0x4141414142424242 . 0x4141414142424242 is treated as the bits 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 believed was happening could have looked something like:
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 up your misinterpretation of the assembler code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With