Мне интересно узнать, как очистить биты, чтобы я мог использовать часть двоичного значения вместо целого. Я надеюсь использовать это для получения подписанного бита, показателя степени и значения из формы с плавающей запятой IEEE с одинарной точностью.
Однако я не совсем знаком с шестнадцатеричной системой, и мне было интересно, смогу ли я получить вашу помощь.
Вот мои мысли до сих пор:
Бит со знаком — побитовое И-двоичное значение на 0x100000000, чтобы получить только первый бит
Экспонент — сдвиньте значение влево один раз, а затем — и новое значение на 0xFF000000, чтобы получить
первые восемь битов для показателя степени
Significand — сдвинуть значение влево в 23 раза
Поскольку каждый из них потребует выполнения работы с исходным значением, я планирую также сохранить значение в другом регистре. Таким образом, я все еще могу работать с ценностью, не «вредя» оригиналу. Значение бит со знаком, экспоненты и signficand будут сохранены в отдельных регистрах.
ПРИМЕЧАНИЕ. Я имею в виду формат с плавающей запятой IEEE-754 с одинарной точностью для этого ответа:
Знак: И-маску свой номер с 0x80000000
, Если результат равен 0, число положительное, иначе отрицательное.
Экспонент: И-маску свой номер с 0x7F800000
, затем сдвиньте 23 бита вправо.
Мантисса: И-маскируй свой номер 0x007FFFFF
,
Чтобы понять, почему я использовал эти числа, просто преобразуйте каждую маску в двоичную форму и поместите ее под двоичное представление вашего числа с плавающей запятой:
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM = format of a floating point number: S=sign,
E=exponent,
M=mantisa
10000000000000000000000000000000 = 80000000h (isolate sign bit)
01111111100000000000000000000000 = 7F800000h (isolate exponent, 8 bits)
00000000011111111111111111111111 = 007FFFFFh (isolate mantissa, 23 bits)
Чтобы преобразовать двоичное число в шестнадцатеричное, просто сгруппируйте его в 4-битные группы и преобразуйте каждую группу в шестнадцатеричное число:
Например:
01111111100000000000000000000000 is arranged as:
0111 1111 1000 0000 0000 0000 0000 0000 which is translated into hex as this:
7 F 8 0 0 0 0 0
Вот немного синтаксиса NASM 32 бит
MOV eax, DWORD [ssValue]
MOV ebx, DWORD [signMask] ;; 80000000h
MOV ecx, DWORD [expoMask] ;; 7F800000h
MOV edx, DWORD [sigfMask] ;; 007FFFFFh
AND ebx, eax
AND ecx, eax
AND edx, eax ;; edx is the significand
SHR ebx, 31 ;; ebx is the sign
SHR ecx, 23 ;; ecx is the exponent
В C это было бы что-то вроде
int sign = value & 0x80000000;
int expo = value & 0x7F800000;
int sigf = value & 0x007FFFFF;
sign >>= 31;
expo >>= 23;
РЕДАКТИРОВАТЬ, если вы хотите исправить показатель, который имеет смещение 127 (7Fh)
if(expo == 0x0) {
// denormal
} else if(expo == 0xFF) {
// +inf or nan depending on sigf
} else { // -126 to 127 range
expo -= 0x7F;
}
РЕДАКТИРОВАТЬ 2
В других языках, таких как Java, «>>» является оператором сдвига со знаком.
sign >>= 31; // would result in 0 or -1 (0xFFFFFFFF) if the sign bit was 1
sign >>>= 31; // would result in 0 or 1