Home > Net >  What's the purpose of xchg ax,ax prior to the break instruction int 3 in DebugBreak()?
What's the purpose of xchg ax,ax prior to the break instruction int 3 in DebugBreak()?

Time:10-28

In MASM, I've always inserted a standalone break instruction

00007ff7`63141120 cc              int     3

However, replacing that instruction with the MSVC DebugBreak function generates

KERNELBASE!DebugBreak:
00007ff8`6b159b90 6690            xchg    ax,ax
00007ff8`6b159b92 cc              int     3
00007ff8`6b159b93 c3              ret

I was surprised to see the xchg instruction prior to the break instruction

xchg    ax,ax

As noted from another S.O. article:

Actually, xchg ax,ax is just how MS disassembles "66 90". 66 is the operand size override, so it supposedly operates on ax instead of eax. However, the CPU still executes it as a nop. The 66 prefix is used here to make the instruction two bytes in size, usually for alignment purposes.

MSVC, like most compilers, aligns functions to 16 byte boundaries.

Question What is the purpose of that xchg instruction?

CodePudding user response:

MSVC generates 2 byte nop before any single-byte instruction at the beginning of a function (except ret in empty functions). I've tried __halt, _enable, _disable intrinsics and seen the same effect.

Apparently it is for patching. /hotpatch option gives the same change for x86, and /hotpatch option is not recognized on x64. According to the /hotpatch documentation, it is expected behavior (emphasis mine):

Because instructions are always two bytes or larger on the ARM architecture, and because x64 compilation is always treated as if /hotpatch has been specified, you don't have to specify /hotpatch when you compile for these targets;

So hotpatching support is unconditional for x64, and its result is seen in DebugBreak implementation.

See here: https://godbolt.org/z/1G737cErf

See this post on why it is needed for hotpatching: Why do Windows functions all begin with a pointless MOV EDI, EDI instruction?. Looks like that currently hotpatching is smart enough to use any two bytes or more instruction, not just MOV EDI, EDI, still it cannot use single-byte instruction, as two-byte backward jump may be written at exact moment when the instruction pointer points at the second instruction.

  • Related