_syscall2(int,vm86,int,func,structvm86plus_struct*,v86)#defineCOM_BASE_ADDR0x10100voidusage(void){printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n""usage: runcom file.com\n""VM86 Run simple .com DOS executables (linux vm86 test mode)\n");exit(1);}staticinlinevoidset_bit(uint8_t*a,unsignedintbit){a[bit/8]|=(1<<(bit%8));}staticinlineuint8_t*seg_to_linear(unsignedintseg,unsignedintreg){return(uint8_t*)((seg<<4)+(reg&0xffff));}staticinlinevoidpushw(structvm86_regs*r,intval){r->esp=(r->esp&~0xffff)|((r->esp-2)&0xffff);*(uint16_t*)seg_to_linear(r->ss,r->esp)=val;}voiddump_regs(structvm86_regs*r){
/* put return code */set_bit((uint8_t*)&ctx.int_revectored,0x21);*seg_to_linear(r->cs,0)=0xb4;/* mov ah, $0 */*seg_to_linear(r->cs,1)=0x00;*seg_to_linear(r->cs,2)=0xcd;/* int $0x21 */*seg_to_linear(r->cs,3)=0x21;pushw(&ctx.regs,0x0000);/* the value of these registers seem to be assumed by pi_10.com */r->esi=0x100;r->ecx=0xff;r->ebp=0x0900;r->edi=0xfffe;for(;;){ret=vm86(VM86_ENTER,&ctx);switch(VM86_TYPE(ret)){caseVM86_INTx:{intint_num,ah;
int_num=VM86_ARG(ret);if(int_num!=0x21)gotounknown_int;ah=(r->eax>>8)&0xff;switch(ah){case0x00:/* exit */exit(0);case0x02:/* write char */{uint8_tc=r->edx;write(1,&c,1);}break;case0x09:/* write string */{uint8_tc;for(;;){c=*seg_to_linear(r->ds,r->edx);if(c=='$')break;write(1,&c,1);}r->eax=(r->eax&~0xff)|'$';}break;default:unknown_int:fprintf(stderr,"unsupported int 0x%02x\n",int_num);dump_regs(&ctx.regs);//exit(1);}}break;caseVM86_SIGNAL:/* a signal came, we just ignore that */break;caseVM86_STI:break;default:fprintf(stderr,"unhandled vm86 return code (0x%x)\n",ret);dump_regs(&ctx.regs);exit(1);}}}