So, musings on how assembly can be represented . . .
commitdd110767bf25037e71be4d3970e1eb0e21cbb603
authorstrange <kawk256@gmail.com>
Wed, 30 Dec 2009 00:54:32 +0000 (29 16:54 -0800)
committerstrange <kawk256@gmail.com>
Wed, 30 Dec 2009 00:54:32 +0000 (29 16:54 -0800)
treeca88f8983aee288d03e557016743ba9fb04f4f9d
parent87b0804b95ab73d747f7f74d7a505b2ba998a9c0
So, musings on how assembly can be represented . . .

For x86 and x86-64 assembly, intel format (I am personally most familliar with
intel assembly), an instruction consists of an opcode and a series of
operands, like so:

mov     rax,    0xff00
 ^       ^        ^
 |       \---v---/
opcode   operands

In x86 assembly, an operand can have a maximum of three operands -- two
registers and one constant, to be exact. In other words, a std::vector<> of
operands should do nicely.

Operands are one of four things: a register, a constant, a dereferenced
constant, or a dereferenced offset from a register. Think of it this way:

mov     rax, 0xff00

Consists of a register and a constant. The instruction:

mov     rax, [rbp-16]

Consists of a register and a dereferenced register offset.

Therefore, an operand can be represented as a single class, with an enum
describing what type it is.

The tricky part here is representing the opcodes. For example, the mov
instruction in x86_64 isn't just "mov", it can be "movzx", "movzx", "movq",
"movsx", and more, all representing slightly different versions of the basic
command to move a value from one place to another.

So . . . what if it was represented as a tree of sorts? "Instructions/Memory
Operations/Move/With Sign-Extension" for "movsx"?

Something to think on, anyhow.