[英]Rounding to an integer - Rounding control field?
我正在嘗試編寫一個名為roundD的函數,該函數根據其第二個參數指定的模式將其第一個參數舍入為整數值。
我將使用gcc的嵌入式匯編程序以匯編語言編寫該函數。 我不想使用任何預定義的函數。
我認為我需要根據第二個參數設置FPU控制字的舍入控制字段。 我還認為我需要在roundD返回之前恢復舍入控制字段的原始值嗎?
我試圖弄清楚如何以正確的順序完成此操作。
我應該使用FPU的控制字嗎?
例如: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.