Another incorrect disassembly
trufae <trufaegmailcom> Wednesday, April 9 2008 04:52.08 CDT


A friend of me which is working on a fpu-based crackme noticed a slighty operational difference, where the same opcode performs two different results with the same values...

Oops! different bytes producing the same opcode?

This bug happened to be a bug in many disassemblers like the one in ollydbg, IDA or udis86 (which I use in radare).

I get some interest on the problem and started to play a bit with radare:

Using objdump-based disassembler:


; Write the 4 bytes
[0x00000000]> wx dcc0 d8c0

; Disassembly using udis86
[0x00000000]> pD 4
0x00000000           dcc0            fadd st0, st0          
0x00000002           d8c0            fadd st0, st0  

; Using objdump-based disassembler:
[0x00000000]> pd 4
   0:   dc c0                   fadd   st(0),st
   2:   d8 c0                   fadd   st,st(0)


Having a closer look to the x86 specs:


D8 0 FADD ST m32real
DC 0 FADD ST m64real
DC 0 FADD STi ST


So, looks like d8 opcode is for 32 bits and the 'dc' one for 64 bits, so the result of the operation differs by the precission.

I have notified the udis86 to fix the problem. And I plan to have this fixed in radare today.

Have fun

Comments
igorsk Posted: Wednesday, April 9 2008 06:41.05 CDT
I wouldn't be too hasty. Let's check in Windbg.

dcc0            fadd    st(0),st
d8c0            fadd    st,st(0)

This page agrees too:
http://www.ews.uiuc.edu/~cjiang/reference/vc83.htm

trufae Posted: Wednesday, April 9 2008 10:08.22 CDT
You are right. these opcodes have nothing to do with the m32/m64 stuff. I was a bit hasty ;)

I think that windbg and gnu binutils are performing the result properly.

But ST == ST(0), and the result differs by precission, so the most logical reply is that it is a bug in the FPU (in my current box. both operations perform the same result +6.283185307179586477). but in another one does not :/


.global main
.text
main:
        fldpi
.byte 0xdc, 0xc0   // fadd %st(0), %st
        int3
        fldpi
.byte 0xd8, 0xc0   // fadd %st, %st(0)
        int3


A funny bug :)

MazeGen Posted: Thursday, April 10 2008 03:04.57 CDT
Just a bit of advertisement: You can point to that opcodes directly and use coder32 edition, which is clearer at first sight:

http://ref.x86asm.net/coder32.html#xD8_0 FADD m32real / FADD ST, STi

http://ref.x86asm.net/coder32.html#xDC_0 FADD m64real / FADD STi, ST