for(;;){ run next instruction }
enum { Data = 0x378+0 Status = 0x378+1, Notbusy = 0x80, Ctl = 0x378+2, Strobe = 0x01, }; lptputc(c) { while((inb(Status)&Notbusy) == 0) ; outb(Data, c) outb(Ctl, Strobe) outb(Ctl, 0) }
AT&T syntax | "C"-ish equivalent |
movl %eax, %edx | edx = eax; |
movl $0x123, %edx | edx = 0x123; |
movl 0x123, %edx | edx = *(int32_t*)0x123; |
movl (%ebx), %edx | edx = *(int32_t*)ebx; |
movl 4(%ebx), %edx | edx = *(int32_t*)(ebx+4); |
Example instruction | What it does |
pushl %eax |
subl $4, %esp movl %eax, (%esp) |
popl %eax |
movl (%esp), %eax addl $4, %esp |
call $0x12345 |
pushl %eip (*) movl $0x12345, %eip (*) |
ret | popl %eip (*) |
+------------+ | | arg 2 | \ +------------+ >- previous function's stack frame | arg 1 | / +------------+ | | ret %eip | / +============+ | saved %ebp | \ %ebp-> +------------+ | | | | | local | \ | variables, | >- current function's stack frame | etc. | / | | | | | | %esp-> +------------+ /
pushl %ebp movl %esp, %ebp
movl %ebp, %esp popl %ebpor
leave
int main(void) { return f(8)+1; } int f(int x) { return g(x); } int g(int x) { return x+3; }
_main: prologue pushl %ebp movl %esp, %ebp body pushl $8 call _f addl $1, %eax epilogue movl %ebp, %esp popl %ebp ret _f: prologue pushl %ebp movl %esp, %ebp body pushl 8(%esp) call _g epilogue movl %ebp, %esp popl %ebp ret _g: prologue pushl %ebp movl %esp, %ebp save %ebx pushl %ebx body movl 8(%ebp), %ebx addl $3, %ebx movl %ebx, %eax restore %ebx popl %ebx epilogue movl %ebp, %esp popl %ebp ret
_g: movl 4(%esp), %eax addl $3, %eax ret
int32_t regs[8]; #define REG_EAX 1; #define REG_EBX 2; #define REG_ECX 3; ... int32_t eip; int16_t segregs[4]; ...
for (;;) { read_instruction(); switch (decode_instruction_opcode()) { case OPCODE_ADD: int src = decode_src_reg(); int dst = decode_dst_reg(); regs[dst] = regs[dst] + regs[src]; break; case OPCODE_SUB: int src = decode_src_reg(); int dst = decode_dst_reg(); regs[dst] = regs[dst] - regs[src]; break; ... } eip += instruction_length; }
#define KB 1024 #define MB 1024*1024 #define LOW_MEMORY 640*KB #define EXT_MEMORY 10*MB uint8_t low_mem[LOW_MEMORY]; uint8_t ext_mem[EXT_MEMORY]; uint8_t bios_rom[64*KB]; uint8_t read_byte(uint32_t phys_addr) { if (phys_addr < LOW_MEMORY) return low_mem[phys_addr]; else if (phys_addr >= 960*KB && phys_addr < 1*MB) return rom_bios[phys_addr - 960*KB]; else if (phys_addr >= 1*MB && phys_addr < 1*MB+EXT_MEMORY) { return ext_mem[phys_addr-1*MB]; else ... } void write_byte(uint32_t phys_addr, uint8_t val) { if (phys_addr < LOW_MEMORY) low_mem[phys_addr] = val; else if (phys_addr >= 960*KB && phys_addr < 1*MB) ; /* ignore attempted write to ROM! */ else if (phys_addr >= 1*MB && phys_addr < 1*MB+EXT_MEMORY) { ext_mem[phys_addr-1*MB] = val; else ... }