簡體   English   中英

舍入為整數-舍入控制字段?

[英]Rounding to an integer - Rounding control field?

我正在嘗試編寫一個名為roundD的函數,該函數根據其第二個參數指定的模式將其第一個參數舍入為整數值。

我將使用gcc的嵌入式匯編程序以匯編語言編寫該函數。 我不想使用任何預定義的函數。

我認為我需要根據第二個參數設置FPU控制字的舍入控制字段。 我還認為我需要在roundD返回之前恢復舍入控制字段的原始值嗎?

我試圖弄清楚如何以正確的順序完成此操作。

我應該使用FPU的控制字嗎?

  1. 我是否將該值加載到FPU中?
  2. 使用控制字-BIT FIELDS進行計算?

例如:RC字段(位11和10)或舍入控制確定FPU將如何舍入結果。

有人可以給我我如何使用RC字段的示例嗎? 還是我需要做什么呢?

我要離開此頁面。.http ://www.website.masmforum.com/tutorials/fptute/fpuchap1.htm

這是一個不錯的頁面嗎? 我還需要Google以獲得什么信息? 非常感謝您的幫助。.我想我只需要對完成此步驟所需的步驟進行詳細分析。

這是我到目前為止所擁有的..

#include <stdio.h>
#include <stdlib.h>

#define PRECISION           3
#define RND_CTL_BIT_SHIFT   10

// floating point rounding modes: IA-32 Manual, Vol. 1, p. 4-20
typedef enum {
ROUND_NEAREST_EVEN =    0 << RND_CTL_BIT_SHIFT,
ROUND_MINUS_INF =       1 << RND_CTL_BIT_SHIFT,
ROUND_PLUS_INF =        2 << RND_CTL_BIT_SHIFT,
ROUND_TOWARD_ZERO =     3 << RND_CTL_BIT_SHIFT
} RoundingMode;

double roundD (double n, RoundingMode roundingMode)
{

return n;


}

int main (int argc, char **argv)
{
double  n = 0.0;

printf("Rounding - Assembly");
if (argc > 1)
    n = atof(argv[1]);

printf("roundD even %.*f = %.*f\n",
       PRECISION, n, PRECISION, roundD(n, ROUND_NEAREST_EVEN));
printf("roundD down %.*f = %.*f\n",
       PRECISION, n, PRECISION, roundD(n, ROUND_MINUS_INF));
printf("roundD up   %.*f = %.*f\n",
       PRECISION, n, PRECISION, roundD(n, ROUND_PLUS_INF));
printf("roundD zero %.*f = %.*f\n",
       PRECISION, n, PRECISION, roundD(n, ROUND_TOWARD_ZERO));

return 0;
}
 __ftol          proc near
 var_C           = qword ptr -0Ch
 var_4           = word ptr -4
 var_2           = word ptr -2
                 push    ebp
                 mov     ebp, esp
                 add     esp, 0FFFFFFF4h
                 fstcw   [ebp+var_2]
                 wait
                 mov     ax, [ebp+var_2]
                 or      ah, 0Ch         ; 00001100
                                         ;
                                         ; ROUNDING CONTROL FIELD
                                         ;     The rounding control (RC) field of the FPU
                                         ;     control register (bits 10 and 11)
                                         ;
                                         ;     Rounding Mode                  RC Field Setting
                                         ;
                                         ;     Round nearest     (even)       00b
                                         ;     Round down        (toward -)   01b
                                         ;     Round up          (toward +)   10b
                                         ;     Round toward zero (Truncate)   11b
                 mov     [ebp+var_4], ax
                 fldcw   [ebp+var_4]
                 fistp   [ebp+var_C]
                 fldcw   [ebp+var_2]
                 mov     eax, dword ptr [ebp+var_C]
                 mov     edx, dword ptr [ebp+var_C+4]
                 leave
                 retn
 __ftol          endp

您是否檢查過您的環境是否包括改進的C99浮點支持? C99定義函數fegetround()fesetround()來獲取和設置當前浮點舍入模式。 然后可以使用rint()函數根據當前的舍入模式進行舍入。

 oldcw   dw   ?

  fstcw oldcw     ;get the current Control Word to retain all setting bits
                  ;not related to the rounding control (RC) bits
  fwait       ;to insure the storage instruction is completed
  mov   ax,oldcw
; and   ax,0F3FFh ;clears only the RC bits, leaving all other bits unchanged
                  ;not necessary here because both bits will be set
  or    ax,0C00h  ;this will set both bits of the RC field to the truncating mode
                  ;without affecting any of the other field's bits
  push  eax       ;use the stack to store the modified Control Word in memory
  fldcw [esp]     ;load the modified Control Word

  fxxxx           ;other FPU instruction(s) needing the truncating mode

  fldcw oldcw     ;restore the previous Control Word
  pop   eax       ;clean-up the stack
                  ;this could also retrieve a 16-bit or 32-bit integer
                  ;possibly returned by the "other FPU instruction(s)"

如果您有一個名為hwcntrlwd的內存變量,並且正確設置了位:(intel語法)

mov eax,[hwcntrlwd]
fstcw ax

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM