0

I'm trying to use the asm function in C to insert redundant xor instructions:

    int main (int argc, char** argv) {
        asm(".rept 100 ; xor %eax, %eax; .endr");
        return 0;
    }

which actually works but I want to know if there is a way to encode specific xor encodings. The assembler defaults to using opcode 0x31, but I want to encode xor opcodes 0x81 and 0x35. (As seen here: https://www.felixcloutier.com/x86/xor)

I have tried replacing xor directly with the opcode:

asm(".rept 100 ; \x35 %eax, %eax; .endr");

But the assembler throws an invalid character error. Any help would be appreciated.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    As I interpret the table, the opcode depends on the parameters. `0x81` is used when the second parameter is an immediate value, `0x31` is used when it's a register. – Barmar Jan 12 '22 at 17:23
  • That's what things like *imm16* and *r16* mean in the specifications of each instruction. You can't use arbitrary opcodes the way you want. – Barmar Jan 12 '22 at 17:26
  • 1
    You can use a `.byte` directive to emit a specific byte. There are also ways to select specific encodings in case there are multiple; refer to the GNU as manual for details. But as @Barmer already said, opcodes `31` and `81` cannot be used in this case. – fuz Jan 12 '22 at 17:33
  • Ah man, that's disappointing to learn. However, it will save me time in the long run to know it won't possible this way. – Connor Peper Jan 12 '22 at 17:43
  • @fuz: [How do GNU assembler x86 instruction suffixes like ".s" in "mov.s" work?](https://stackoverflow.com/q/47673177) details the old-style `.s` suffix to swap opcode, and the new-style `{load}` and `{store}` overrides, for selecting between `0x31` and `0x33` which are both valid choices, unlike any of the other opcodes. You could add a REX prefix for xor rax,rax. Or even a REX prefix with no bits set to not change the insn, assuming it's 64-bit mode. – Peter Cordes Jan 12 '22 at 18:10
  • 2
    Don't forget to declare the clobber of `eax` / `rax`! – Nate Eldredge Jan 12 '22 at 18:14
  • 1
    This inline asm is unsafe; it writes EAX without telling the compiler about it. You need `asm("xor %%eax,%%eax" ::: "eax")`. There are other ways to zero a register, e.g. `sub reg,reg` or `mov reg,0`, but xor is the most efficient choice; sub isn't special-cased on some CPUs. – Peter Cordes Jan 12 '22 at 18:15
  • @ConnorPeper If you let me know what you are trying to achieve, perhaps I might be able to propose a better overall approach. – fuz Jan 12 '22 at 19:40

0 Answers0