Sometimes it is necessary to find out the functionality available in a processor. In your program, you can, for example, look for the presence or absence of a certain version of SSE. In the next chapter, we will use programs with SSE instructions, so we need to find out first which version of SSE is supported by our processor. There is an instruction for checking the CPU characteristics: cpuid.
Using cpuid
You first put a specific parameter in eax, then execute the instruction cpuid, and finally check the returned value in ecx and edx. Indeed, cpuid uses 32-bit registers.
The amount of information you can find out with cpuid is staggering. Go to the Intel manuals ( https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf ) and look up the cpuid instruction in Volume 2A. You will find several tables that show what is returned in ecx when you start cpuid with certain value in eax. This is only part of the information you can retrieve; another table shows the information returned in edx. Browse the Intel manual to see the possibilities.
Let’s see an example of looking for SSE functionality that we will need in the next chapter. In the Intel manual, you find that you can use ecx bits 0, 19, and 20 and ecx bits 25 and 26 to find out which version of SSE is implemented in a processor.
cpu.asm
The main program calls only one function, cpu_sse, and if the return value is 1, the processor supports some version of SSE. If the return value is 0, you can forget about using SSE on that computer. In the function cpu_sse, we find out which SSE versions are supported. Put 1 in eax and execute the instruction cupid; as mentioned, the results will be returned in ecx and edx.
Using the test Instruction
The ecx and edx registers will be evaluated with a test instruction, which is a bit-wise logical and of the two operands. We could have used the cmp instruction, but test has a performance advantage. Of course, you can also use the instruction bt (see Chapter 17).
The important flag in our case is ZF. If ZF=0, then the result is nonzero; the SSE bit is 1, and the CPU supports that version of SSE. The instruction jz evaluates if ZF=1, and if so, the SSE version is not supported, and the execution jumps to the next part. Otherwise, the program prints a confirmation message.
Remember, you can find plenty of binary to hexadecimal conversion tools on the Internet.
The execution “cascades” through the program, and if no SSE is supported, r12 will remain 0. We did not use the return value, but you could check rax, the return value, to conclude whether any SSE is supported. Or you could modify the program to return the highest version of SSE.
You could build a similar function to find out other CPU information and, depending on the returned result, choose to use certain functionality on this CPU and other functionality on another CPU.
In a later chapter, when we discuss AVX, we will again have to find out whether the CPU supports AVX.
Summary
How to find out what functionality is supported by the CPU with cpuid
How to use bits with the test instruction