1

The description of the lahf instruction is:

This instruction executes as described above in compatibility mode and legacy mode. It is valid in 64-bit mode only if CPUID.80000001H:ECX.LAHF-SAHF[bit 0] = 1

First question: What is compatibility and legacy mode? How are they different from real-mode and protected mode?

Second question: What does CPUID.80000001H:ECX.LAHF-SAHF[bit 0] = 1 mean?

janw
  • 8,758
  • 11
  • 40
  • 62
syacer
  • 157
  • 6
  • 1
    https://en.wikipedia.org/wiki/X86-64#Operating_modes. re 2nd part: that's standard CPUID notation; read Intel's PDF manuals which explains how it describes which inputs to CPUID to use, and which result bit to look at. (Probably the vol.2 manual.) See also https://sandpile.org/x86/cpuid.htm – Peter Cordes Sep 20 '20 at 19:27
  • Is this one of those AMD vs Intel things, like AMD left the opcode reserved in 64-bit mode and Intel chose to keep its previous behavior, or vice versa, so that in the end we have to have a CPUID bit to tell us which kind of machine we are on? – Nate Eldredge Mar 31 '22 at 15:17
  • @NateEldredge: Whatever research I did for [x86 32 bit opcodes that differ in x86-x64 or entirely removed](https://stackoverflow.com/q/32868293) found that it was missing from early AMD (AMD64) *and* Intel (EM64T) CPUs, at least that's what I wrote several years ago. That's consistent with what GCC thinks: `gcc -march=nocona -fverbose-asm` is missing `-msahf`, but its present for `-march=core2`. When fuz wrote on [Is x86 32-bit assembly code valid x86 64-bit assembly code?](https://stackoverflow.com/q/44089163) that early AMD64 CPUs omitted it, perhaps he didn't mean AMD specifically. – Peter Cordes Mar 31 '22 at 16:01
  • https://godbolt.org/z/1zj7sWM57 – Peter Cordes Mar 31 '22 at 16:05
  • Huh, so they took it out and then put it back. I wonder who could possibly have been lobbying for it? – Nate Eldredge Mar 31 '22 at 16:10
  • @NateEldredge: Yeah, IDK; I haven't seen GCC or clang actually emit it, except maybe with legacy x87 with PPro instructions like `fcomi`. But x86-64 guarantees `fcomi` availability. Maybe some legacy hand-written asm for 80-bit FP stuff hadn't been updated for PPro new instructions and still used `fcom` / `fstsw` / `sahf`? Or possibly extended-precision loops saving/restoring CF? Some software was slow to get ported to x86-64, and maybe that was one of the sticking points for some commercially-relevant cases. Totally guessing here, haven't read anything about why. – Peter Cordes Mar 31 '22 at 19:28

1 Answers1

8

what is compatibility and legacy mode. How are they different from real-mode and protected mode

An 80x86 CPU has multiple modes. The ones software developers might care about are real mode, protected mode and long mode; but there's also system management mode (mostly "firmware use only"), "inactive" (waiting to be started), etc.

Protected mode has multiple sub-modes (16-bit, 32-bit, virtual8086).

Long mode has multiple sub-modes (16-bit, 32-bit, 64-bit).

"Legacy mode/s" refers to real mode and protected mode (and all of protected mode's sub-modes), and not long mode or any of its sub-modes; where code is either 16-bit or 32-bit (with other differences between real mode and protected mode that don't matter for most instructions and only matter for things like segment register loads and operating system kernels). The legacy mode/s exist to provide backward compatibility to old software/operating systems (e.g. MS-DOS won't support long mode and will use real mode, Windows95 won't use long mode and will use protected mode, etc).

Compatibility mode/s refers to the 16-bit and 32-bit sub-modes of long mode. The compatibility mode/s (or, the 16-bit and 32-bit sub-modes of long mode) exist to allow a newer OS to execute programs designed for an older OS (e.g. to allow a 64-bit version of Windows to run applications designed for a 32-bit version of Windows). In this case the code is either 16-bit or 32-bit (like legacy modes); but it is unlike legacy modes because it's still using the long mode mechanisms for paging, interrupts, etc. Mostly; for compatibility modes the kernel is expected to be 64-bit even though the currently executing code isn't.

Second question: what does it mean CPUID.80000001H:ECX.LAHF-SAHF[bit 0] = 1

The CPUID instruction returns information about the CPU. Because there's lots of information the information is split into groups/"leaves" where the value in EAX determines which information the CPUID instruction will return (and for some cases ECX also modifies which information is returned). The information is returned in general purpose registers (EAX, EBX, ECX, EDX).

"CPUID.80000001H:ECX.LAHF-SAHF[bit 0]" means "the value returned by the CPUID instruction in the bit 0 of ECX, when CPUID is called with EAX=0x80000001" (and the LAHF-SAHF part is just the name that AMD decided to give that bit).

In other words, your code might look like (Intel syntax assembly):

    mov eax,0x80000001
    cpuid
    test ecx,1           ;Is bit 0 (the "LAHF-SAHF" bit) set?
    je .noLAHF           ; no, LAHF is not supported
Brendan
  • 35,656
  • 2
  • 39
  • 66