// helper for tests: load a program into memory from a textual representation
// of its bytes, and run it
voidrun(conststring&text_bytes){
load_program(text_bytes);
EIP=1;// preserve null pointer
while(EIP<Memory.size())
run_one_instruction();
}
voidload_program(conststring&text_bytes){
assert(Memory.empty());
// initialize address 0
Memory.push_back(0);
// now, to read the hex bytes in ASCII, we'll use C's strtol
// strtol needs a char*, so we grab the buffer backing the string object
char*curr=const_cast<char*>(&text_bytes[0]);// non-standard approach, but blessed by Herb Sutter (http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483)
char*max=curr+strlen(curr);
while(true){
if(curr>=max)return;
// skip whitespace
while(*curr==''||*curr=='\n')++curr;
// skip comments
if(*curr=='#'){
while(*curr!='\n'){
++curr;
if(curr>=max)return;
}
++curr;
if(curr>=max)return;
}
Memory.push_back(strtol(curr,&curr,/*hex*/16));
trace(99,"load")<<HEXBYTE<<static_cast<unsignedint>(Memory.back())<<end();// ugly that iostream doesn't print uint8_t as an integer
}
}
// skeleton of how x86 instructions are decoded
voidrun_one_instruction(){
uint8_top=0,op2=0,op3=0;
switch(op=next()){
// our first opcode
case0x05:{// add EAX, imm32
int32_targ2=imm32();
trace(2,"run")<<"add to EAX immediate 0x"<<HEXWORD<<arg2<<end();
PERFORM_ARITHMETIC_BINOP(+,R[EAX].i,arg2);
trace(98,"reg")<<"storing 0x"<<HEXWORD<<R[EAX].i<<" in register EAX"<<end();