I'm using MSVC 2015.
I was trying to follow an answer provided here and adapted the program to the following:
#include <iostream>
#include <limits>
inline unsigned long long query_intel_x86_eflags(const unsigned long long query_bit_mask)
{
return __readeflags() & query_bit_mask;
}
int main(int argc,char **argv)
{
int x = std::numeric_limits<int>::max();
int y = std::numeric_limits<int>::max();
int z = x * y;
//auto g{__readeflags() & 0x801}; // sees overflow and carry flags
auto g{query_intel_x86_eflags(0x801)}; // doesn't see overflow and carry flags
std::cout << std::hex << g << '\n';
}
The problem is that the eflags register is reset during the call to query_intel_x86_eflags()
prior to the read of the EFL
register.
The following assembly is emitted and it contains a sub
instruction that resets the EFL
register.
inline unsigned long long query_intel_x86_eflags(const unsigned long long query_bit_mask)
{
00007FF6396D1BF0 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
00007FF6396D1BF5 55 push rbp
00007FF6396D1BF6 57 push rdi
00007FF6396D1BF7 48 81 EC C8 00 00 00 sub rsp,0C8h // changes the flags
00007FF6396D1BFE 48 8B EC mov rbp,rsp
00007FF6396D1C01 48 8B FC mov rdi,rsp
00007FF6396D1C04 B9 32 00 00 00 mov ecx,32h
00007FF6396D1C09 B8 CC CC CC CC mov eax,0CCCCCCCCh
00007FF6396D1C0E F3 AB rep stos dword ptr [rdi]
00007FF6396D1C10 48 8B 8C 24 E8 00 00 00 mov rcx,qword ptr [rsp+0E8h]
return __readeflags() & query_bit_mask;
00007FF6396D1C18 48 9C pushfq
00007FF6396D1C1A 58 pop rax
00007FF6396D1C1B 48 23 85 E0 00 00 00 and rax,qword ptr [query_bit_mask]
}
Why does the compiler generate the additional instructions that end up resetting the register?