Skip to content

Latest commit

 

History

History
84 lines (65 loc) · 1.97 KB

cpuid.md

File metadata and controls

84 lines (65 loc) · 1.97 KB

cpuid

In this example we will create a JavaScript function that calls X64 cpuid method with different arguments and returns results.

First write our X64 assembly that calls cpuid instruction with given arguments:

const tpl = _ => {
    // Save rbx, rcx, and rdx registers on stack.
    _('push', 'rbx');
    _('push', 'rcx');
    _('push', 'rdx');

    // Use first two arguments (eax and ecx) to our function as
    // parameters to CPUID call.
    _('mov', ['eax', 'edi']);
    _('mov', ['ecx', 'esi']);

    // Execute CPUID call.
    _('cpuid');

    const resultEax = _.lbl('result_eax');
    const resultEbx = _.lbl('result_ebx');
    const resultEdx = _.lbl('result_edx');
    const resultEcx = _.lbl('result_ecx');

    // Store results in memory.
    _('mov', [rip.disp(resultEax), 'eax']);
    _('mov', [rip.disp(resultEbx), 'ebx']);
    _('mov', [rip.disp(resultEdx), 'edx']);
    _('mov', [rip.disp(resultEcx), 'ecx']);

    // Restore registers we saved on the stack.
    _('pop', 'rdx');
    _('pop', 'rcx');
    _('pop', 'rbx');

    // Return
    _('ret');

    _('align', 4);

    _.insert(resultEax);
    _('dd', 0);
    _.insert(resultEbx);
    _('dd', 0);
    _.insert(resultEdx);
    _('dd', 0);
    _.insert(resultEcx);
    _('dd', 0);
};

Above in assembly we have written a "function" that receives two arguments and uses those to call cpuid instruction. After the call it stores the results in a space allocated right after the return ret instruction of the function.

Now compile our code:

const asm = X64();
asm.code(tpl);

const bin = asm.compile([]);

And create a JavaScript wrapper function that receives two arguments and executes the cpuid instruction:

function cpuid (eax, ecx) {
    const sb = StaticBuffer.from(bin, 'rwe');

    sb.call([eax, ecx]);

    return [
        sb.readInt32LE(sb.length - 16),
        sb.readInt32LE(sb.length - 12),
        sb.readInt32LE(sb.length - 8),
        sb.readInt32LE(sb.length - 4),
    ];
}