1.22. MANIPULATING SPECIFIC BIT(S)
Listing 1.282: Optimizing MSVC 2012
_tmp$ = 8
_i$ = 8
_my_abs PROC
and DWORD PTR _i$[esp-4], 2147483647 ; 7fffffffH
fld DWORD PTR _tmp$[esp-4]
ret 0
_my_abs ENDP
_tmp$ = 8
_i$ = 8
_set_sign PROC
or DWORD PTR _i$[esp-4], -2147483648 ; 80000000H
fld DWORD PTR _tmp$[esp-4]
ret 0
_set_sign ENDP
_tmp$ = 8
_i$ = 8
_negate PROC
xor DWORD PTR _i$[esp-4], -2147483648 ; 80000000H
fld DWORD PTR _tmp$[esp-4]
ret 0
_negate ENDP
An input value of typefloatis taken from the stack, but treated as an integer value.
ANDandORreset and set the desired bit.XORflips it.
Finally, the modified value is loaded intoST0, because floating-point numbers are returned in this register.
Now let’s try optimizing MSVC 2012 for x64:
Listing 1.283: Optimizing MSVC 2012 x64
tmp$ = 8
i$ = 8
my_abs PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
btr eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
my_abs ENDP
_TEXT ENDS
tmp$ = 8
i$ = 8
set_sign PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
bts eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
set_sign ENDP
tmp$ = 8
i$ = 8
negate PROC
movss DWORD PTR [rsp+8], xmm0
mov eax, DWORD PTR i$[rsp]
btc eax, 31
mov DWORD PTR tmp$[rsp], eax
movss xmm0, DWORD PTR tmp$[rsp]
ret 0
negate ENDP
The input value is passed inXMM0, then it is copied into the local stack and then we see some instructions
that are new to us:BTR,BTS,BTC.