【发布时间】:2016-01-18 12:06:33
【问题描述】:
我一直在研究如何通过反汇编 C 代码在 x86 架构中处理浮点运算。使用的操作系统是 64 位 linux,而代码是为 32 位机器编译的。
这里是C源代码:
#include <stdio.h>
#include <float.h>
int main(int argc, char *argv[])
{
float a, b;
float c, d;
printf("%u\n",sizeof(float));
a = FLT_MAX;
b = 5;
c = a / b;
d = (float) a / (float) b;
printf("%f %f \n",c,d);
return 0;
}
这里是32位exe主要功能的反汇编版本:
804841c: 55 push ebp
804841d: 89 e5 mov ebp,esp
804841f: 83 e4 f0 and esp,0xfffffff0
8048422: 83 ec 30 sub esp,0x30
8048425: c7 44 24 04 04 00 00 mov DWORD PTR [esp+0x4],0x4
804842c: 00
804842d: c7 04 24 20 85 04 08 mov DWORD PTR [esp],0x8048520
8048434: e8 b7 fe ff ff call 80482f0 <printf@plt>
8048439: a1 2c 85 04 08 mov eax,ds:0x804852c
804843e: 89 44 24 2c mov DWORD PTR [esp+0x2c],eax
8048442: a1 30 85 04 08 mov eax,ds:0x8048530
8048447: 89 44 24 28 mov DWORD PTR [esp+0x28],eax
804844b: d9 44 24 2c fld DWORD PTR [esp+0x2c]
804844f: d8 74 24 28 fdiv DWORD PTR [esp+0x28]
8048453: d9 5c 24 24 fstp DWORD PTR [esp+0x24]
8048457: d9 44 24 2c fld DWORD PTR [esp+0x2c]
804845b: d8 74 24 28 fdiv DWORD PTR [esp+0x28]
804845f: d9 5c 24 20 fstp DWORD PTR [esp+0x20]
8048463: d9 44 24 20 fld DWORD PTR [esp+0x20]
8048467: d9 44 24 24 fld DWORD PTR [esp+0x24]
804846b: d9 c9 fxch st(1)
804846d: dd 5c 24 0c fstp QWORD PTR [esp+0xc]
8048471: dd 5c 24 04 fstp QWORD PTR [esp+0x4]
8048475: c7 04 24 24 85 04 08 mov DWORD PTR [esp],0x8048524
804847c: e8 6f fe ff ff call 80482f0 <printf@plt>
8048481: b8 00 00 00 00 mov eax,0x0
8048486: c9 leave
8048487: c3 ret
8048488: 66 90 xchg ax,ax
804848a: 66 90 xchg ax,ax
804848c: 66 90 xchg ax,ax
804848e: 66 90 xchg ax,ax
我难以理解的是浮点值传输到寄存器的行。具体来说:
mov eax,ds:0x804852c
mov eax,ds:0x8048530
在我的理解中,指令应该分别等于 mov eax,[0x804852c] 和 mov eax,[0x8048530] 因为在 32 位模式下 ds 寄存器通常指向整个 32 位空间并且通常为 0。但是当我检查寄存器值 ds 不是 0。它有值
ds 0x2b
给定这个值,计算不应该是
0x2b *0x10 + 0x8048520
但是浮点数存储在 0x8048520 和 0x8048530 中,这就像在 DS 中的值为 0。谁能向我解释这是为什么?
【问题讨论】:
标签: assembly x86 disassembly objdump memory-segmentation