|
|
|
Lecture 19 — machine code and x86 assembly
|
|
|
|
|
historical perspective
|
|
|
|
|
early computers were programmed directly in machine code
|
|
|
|
|
instructions has to be simple (single instruction for adding two integers)
|
|
|
|
|
assemblers allowed programming in human readable syntax
|
|
|
|
|
still simple instructions
|
|
|
|
|
languages like C provide a higher level of abstraction
|
|
|
|
|
a single C statement may compile to many assembly instructions
|
|
|
|
|
instruction set architecture (or just architecture)
|
|
|
|
|
the design of a processor
|
|
|
|
|
determines what is visible to software (i.e., the hardware-software interface)
|
|
|
|
|
we will be looking at x86-64
|
|
|
|
|
dominant architecture among modern processors
|
|
|
|
|
why assembly?
|
|
|
|
|
Chances are, you’ll never write a program in assembly code
|
|
|
|
|
Compilers are much better and more patient than you are
|
|
|
|
|
But: understanding assembly is the key to the machine-level execution model
|
|
|
|
|
optimizations (understanding those done by the compiler, doing your own)
|
|
|
|
|
implementing system software
|
|
|
|
|
fighting malicious software
|
|
|
|
|
assembly programmer’s view
|
|
|
|
|
a register is a location in the CPU that stores a small amount of data, which can be accessed very quickly
|
|
|
|
|
registers have names, not addresses
|
|
|
|
|
no types, everything is just bytes
|
|
|
|
|
x86-64 assembly
|
|
|
|
|
three basic kinds of instructions
|
|
|
|
|
transfer data between registers and memory
|
|
|
|
|
perform arithmetic on data from registers or memory
|
|
|
|
|
transfer control: set what instruction to execute next
|
|
|
|
|
moving data
|
|
|
|
|
movx Source, Dest
|
|
|
|
|
where x is one of
|
|
|
|
|
b (byte, movb copies 1 byte)
|
|
|
|
|
w (word, movw copies 2 bytes)
|
|
|
|
|
l (long word, movl copies 4 bytes)
|
|
|
|
|
q (quad word, movq copies 8 bytes)
|
|
|
|
|
operand types
|
|
|
|
|
immediate: constant integer data
|
|
|
|
|
prefix with $
|
|
|
|
|
$0x400, $-533
|
|
|
|
|
register: name of a register
|
|
|
|
|
%rax, %r13
|
|
|
|
|
%rsp reserved for special use
|
|
|
|
|
memory: 8 consecutive bytes of memory at address given by value in a register
|
|
|
|
|
simplest example: (%rax)
|
|
|
|
|
movq operand combinations
|
|
|
|
|
x86 does not allow memory-to-memory in a single instruction — how would you do it?
|
|
|
|
|
two instructions, one from memory to register, then one from register to memory
|
|
|
|
|
basic addressing modes
|
|
|
|
|
indirect: (R) where the value of register R specifies the memory address
|
|
|
|
|
movq (%rcx), %rax
|
|
|
|
|
displacement: D(R) where R specifies memory address and D is a constant offset from that address
|
|
|
|
|
movq 8(%rbp), %rdx
|
|
|
|
|
swap example
|
|
|
|
|
void swap (long *xp, long *yp) { long t0 = *xp; long t1 = *yp; *xp = t1; *yp = t0; }
|
|
|
|
|
swap: movq (%rdi), %rax movq (%rsi), %rdx movq %rdx, (%rdi) movq %rax, (%rsi) ret
|
|
|