Multiple Register Return in Inline Assembly

I’m trying to implement x86 cpuid in Zig, and the inline assembly feature doesn’t seem to be very well documented. How can I return EDX:ECX to a packed struct?

It is included in the standard library, but it is not public:

const CpuidLeaf = packed struct {
    eax: u32,
    ebx: u32,
    ecx: u32,
    edx: u32,
};

fn cpuid(leaf_id: u32, subid: u32) CpuidLeaf {
    // valid for both x86 and x86_64
    var eax: u32 = undefined;
    var ebx: u32 = undefined;
    var ecx: u32 = undefined;
    var edx: u32 = undefined;

    asm volatile ("cpuid"
        : [_] "={eax}" (eax),
          [_] "={ebx}" (ebx),
          [_] "={ecx}" (ecx),
          [_] "={edx}" (edx),
        : [_] "{eax}" (leaf_id),
          [_] "{ecx}" (subid),
    );
    return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx };
}

https://codeberg.org/ziglang/zig/src/commit/8709f53d440ed8479f711d871a2d6c2c35dc1014/lib/std/zig/system/x86.zig#L755-L761

2 Likes