Memory is stored in bits, which can be either 0 or 1 (Binary)
Hex is a number system based on 16, so values can be 0-9, or A-F (10-15).
Why use hex? It's easier to parse and it's simple to convert it to binary, unlike decimal.
In binary, the number 15 is represented as 1111
In hex, the number 15 if represented by F
By splitting up binary into groups of 4 bits, you can convert that group into hex by adding the values of the bits ...
... and then joining them back together.
A pointer is a piece of memory that holds the address of a value, and not the value itself.
This can be useful when a program is not sure what the actual address of a value will be until runtime.
Sometimes pointers hold the addresses of other pointers. These are called pointer chains.
In assembly code you can't save values to variables, so arguments to functions are stored and passed around in registers.
What's a register? It's a special piece of memory that's only big enough to store 4 bytes of data, but the processor can access it really quickly.
In x86 architecture, there are 8 usable registers.
... but most instructions will only involve these four.
Most registers have a special function, so you'll see them used in consistent ways across different programs.
For example, EAX
is optimized for calculations, while ESP
is used to reference the top of the stack.
Assembly code is a list of instructions that tell the computer exactly what it needs to do to complete a program.
Each instruction is very specific, and only has a few operands.
Taken one step at a time, it's possible to follow the code exactly as the computer would execute it.
So, how do bytes in memory become code?
Each instruction is a direct translation of bits in memory
These bits indicate this an add instruction, adding a constant to a register.
These bits indicate which register is being added to.
And these bits are the value being added.
Based on the bits, the computer will translate them into an instruction.
add ESP, 08
There are 4 ways to provide arguments to assembly instructions:
add EAX,1
constants - these can be addresses or values of any type.
add EAX,EBX
registers - the value currently in register EBX is used.
add EAX,[EBX]
addressing - the value in memory at the address in register EBX is used.
add EAX,[EBX+C]
address displacement - add C to the address in register EBX and use what is stored in memory there.
INC operand
operand += 1
DEC operand
operand -= 1
NOT operand
negates each bit in operand
ADD destination, source
destination += source
SUB destination, source
destination -= source
AND destination, source
destination &= source
OR destination, source
destination |= source
MOV destination, operand
copies operand value to destination
CMP value1, value2
compares value1 to value2 (<, =, >) without modifying either
PUSH operand
places operand value on top of stack
POP destination
removes value on top of stack and copies it to destination
CALL operand
calls a subroutine at address or label
JMP destination
jumps execution to address or label
JE destination
jumps if previous CMP was equal
JNE destination
jumps if previous CMP was not equal
JG destination
jumps if previous CMP determined value1 > value2
JL destination
jumps if previous CMP determined value1 < value2