这是一个子函数,参数为一个浮点数

请问这个汇编子函数到底是用什么规则将目标浮点数取整的?

汇编代码如下(以49.019577举例)

PUSH EBP                       ; 将浮点数49.019577压栈
MOV EBP,ESP                     
ADD ESP,-0C                     
WAIT
FSTCW WORD PTR SS:[EBP-2]      ; 将FPU控制字(027F)保存
WAIT
MOV AX,WORD PTR SS:[EBP-2]     ; 将FPU控制字(027F)保存到AX
OR AH,0C                       ; AH(02:0010)与C:1100或运算->1110(0E7F)
MOV WORD PTR SS:[EBP-4],AX     ; 0E7F保存到堆栈
FLDCW WORD PTR SS:[EBP-4]      ; 设置控制寄存器的值(0E7F)
FISTP QWORD PTR SS:[EBP-C]     ; 将栈顶数据49.019577舍入整型传送到后面
FLDCW WORD PTR SS:[EBP-2]      ; 恢复控制寄存器027F
MOV EAX,DWORD PTR SS:[EBP-C]  
MOV EDX,DWORD PTR SS:[EBP-8]
RTN


谢谢了,我查了很久资料了。还是不知道。

  • 标 题: 答复
  • 作 者:liuzewei
  • 时 间:2006-11-01 15:25

解决了,VC6中实验,代码如下:

int CTestDlg::ToInt(double f_in)
{
  int i_out;
  unsigned short int cr_0,cr_t;
  __asm
  {
      // FPU控制字的意义
      // 027F:四舍五入取整     15.555 -> 16
      // 0E7F:抹去小数部分取整 15.555 -> 15
      FLD f_in       // f_in 压栈
      WAIT
      FSTCW cr_0     // FPU控制字(027F) -> cr_0
      WAIT
      MOV AX,cr_0    // cr_0 -> AX
      OR AH,0xC      // AH(0010) or 0xC(1100) -> AH(1110)
      MOV cr_t,AX    // AX(0E7F) -> cr_t
      FLDCW cr_t     // cr_t(0E7F) -> 浮点控制寄存器
      FISTP i_out    // 将栈顶的数据取整
      FLDCW cr_0     // cr_0(027F) -> 浮点控制寄存器
  }
  return i_out;


继续实验,代码如下:
int i_out;
double f_in;
for(f_in=15;f_in<16;f_in+=0.000000001)
{
     i_out = ToInt(f_in);
     if(i_out != (int)(f_in))
        ::AfxMessageBox("不等价于(int)(f_in)!!");
}
结果是FPU控制字为0E7F时,完全等价于C++中的(int)() 

呵呵。舒服ing.