You should read the Intel manuals, it explains how to do that. For a simpler reference, read this. The way x86 instructions are encoded is fairly straightforward, but the number of possibilities can be a bit overwhelming.
In a nutshell, an x86 instruction comprises the following parts, where every part except the opcode may be missing:
prefix opcode operands immediate
The prefix
field may modify the behaviour of the instruction, which doesn't apply to your use case. You can look up the opcode
in a reference (I like this one), for example, mov r/m32, imm32
is C7 /0
which means: The opcode is C7
and one of the two operands is zero as an extended operand. This instruction takes a 32 bit immediate, so the instruction has the form
C7 operand/0 imm32
The operand/extended opcode is encoded as a modr/m byte with an optional sib (scale index base) byte for some addressing modes and an optional 8 bit or 32 bit displacement. You can look up what value you need in the reference. So in your case, you want to encode a memory operand [rbp]
with a one byte displacement and a register operand of 0, leading to the modr/m byte 45
. So the encoding is:
C7 45 disp8 imm32
Now we encode the 8 bit displacement in two's complement. -4
corresponds to FC
, so this is
C7 45 FC imm32
Lastly, we encode the 32 bit immediate, which you want to be 2
. Note that it is in little endian:
C7 45 FC 02 00 00 00
And that's how the instruction is encoded.
int b = 2;
is NOT Assembly language. The difference is, that C is compiled language, so the lineint b = 2;
may be implemented in many different ways (even removed completely by optimizer), depending on what compiler will decide, how to produce machine code which will produce results as defined by C language standard. Assembly language is different in a way, that Assembler is not compiler of this kind, when you write in Assemblyadd rax,rbx
, it will be compiled as that, not changing the instruction, or removing by some kind of optimizer, so that's more like "1:1 transformation". – Ped7g