模拟dos下面的Debug下子命令D的功能,显示内存数据的程序

来源:互联网 发布:软件开发报价表 编辑:程序博客网 时间:2024/06/03 15:07

模拟dos下面的Debug下子命令D的功能,显示内存数据的程序

还有子命令错误位置提示的功能和 d 命令的 l 参数没有实现;l  后面接数字表示要显示的个数,

在解析子命令的时候本想用语法和此法分析的方法,但功力不够,《the c++ language 》里面的那个词法语法分析的简单计算的代码都看不懂,只能进行字符串判断来处理了。代码写的很冗余·············

#define unit(m,n) (*(unsigned char far *)( m*0x10000 + n))int showNum = 0x80 ;/*要显示的数字的个数*/int sec = 0;/*要现实的段地址,在getToken里面如果没有给定的话,会赋予DS的值*/int offset = 0;/*当前偏移地址*/int dcount = 0,ccount = 0;/*记录已经输出了的内存字节和对应的字符的个数*/int errorppos=1;/*出错位置标记,没有实现*/int str2Hex( char *pstr);/*将十六进制字符串转化为数字*/void show();  /*从当前偏移地址开始,显示showNum个字符*/void showLine( unsigned  int o);/*根据传入的便宜地址显示内存数据,以及对应的ascii值*/int getToken(char *);/*分析d子命令,将结果写给全局变量sec和offset*/void Driver(char *);/*根据用户的输入的字符串,调用子命令分析函数,根据返回结果做出相应的操作*/int valueLegal(char *);/*传入的参数应该是分离出来的段地址或者偏移地址,判断要转换的十六进制字符串是否合法*/main(){char buf[100];sec=_DS;/*默认偏移地址*/offset=0x0080;/*因为按下d,偏移地址会自加 showNum*/printf("-----------------------------------Lee'S  Debug---------------------------------\n");while(1)/*showLine(_DS,0x1009);*/{printf("-");gets(buf);Driver(buf);memset(buf,0,100);}}void Driver(char * pstr){showNum = 0x80 ;if( strlen(pstr) == 0)return;if( getToken(pstr) )show();elseprintf("Error Comand\n");}int getToken(char * pstr){char *pt = pstr;char buf[64] = {0};char secbuf[8] = {0};char offbuf[8] = {0};int i = 0,j = 0,sPos = -1,oPos = -1;int pos[4]={0};int havesec = 0,flag=0;if( pstr == 0)return 0;strcpy(buf,pstr);/*找到第一个符号:命令的位置,排除空格*/while( buf[i]  ){if( buf[i] != ' ' ){pos[j++]=i++;break;}i++;}/**/while( buf[i] && j<4 ){flag=1;while( buf[i] && buf[i] != ' ' && j<4){if( flag ){pos[j++]=i;flag=0;}i++;}i++;}/*如果第一个非空格字符是q 则退出*/if( ('q' == buf[pos[0]] || 'Q' == buf[pos[0]]) )exit(0);/*如果第一个非空格字符不是d,则返回0,error*/if( ! ('d' == buf[pos[0]] || 'D' == buf[pos[0]]) )return 0;/*pos[1]是第二个非空格字符的开始,如果为0表示没有赋值,直接输出DS:0x100*/if( 0 == pos[1] ){offset += showNum;return 1;}/*pos[1]是第二个非空格字符的开始*/i=sPos=oPos=pos[1];/*取地址值*/do{i++;if( buf[i] == ' ' || buf[i] == '\0'){strncpy(&offbuf,&buf[oPos],i-oPos);}if( buf[i] == ':'){strncpy(&secbuf,&buf[sPos],i-sPos);oPos=i+1;}}while( buf[i] != ' ' &&  buf[i] != '\0');sPos=valueLegal(secbuf);oPos=valueLegal(offbuf);if( sPos == -1 || oPos == -1)return 0;if( sPos == 0  && oPos > 0 && oPos < 0xa ){sec = 0x1000;offset = str2Hex(offbuf);return 1;}if(  sPos > 0  && oPos > 0){sec = str2Hex(secbuf);offset = str2Hex(offbuf);return 1;}return 0;}/*传入的参数应该是分离出来的段地址或者偏移地址判断要转换的十六进制字符串是否合法如果是es或者ds就返回0xD或0xE错误的表达式返回-1否则返回表达式的长度返回0表示字符串长度为0*/int valueLegal(char * pstr){int i=0;char *pt=pstr;/*空字符串就返回1,表示可以转换*/if( strlen(pt) == 0 )return 0;if(  0 == strcmp(pt,"ES") ||  0 == strcmp(pt,"es") || 0 == strcmp(pt,"Es") ||  0 == strcmp(pt,"eS") ){return 0x0d;}if(   0 == strcmp(pt,"DS") ||  0 == strcmp(pt,"ds") || 0 == strcmp(pt,"Ds") ||  0 == strcmp(pt,"dS") ){return 0x0e;}while(*pt){if(!( ( *pt >= '0' &&  *pt <= '9' )    || ( *pt >= 'A' && *pt <= 'F' )|| ( *pt >= 'a' && *pt <= 'f' )  ) )return -1;i++;pt++;}if( i > 4)/*如果长度超过四就返回错误代码*/return -1;return i;}/**/void show(){int n = 0;int line = 0;int toff = 0;toff = offset;line =  (toff%16) == 0?8:9;/*判断是否为16的整数,两种显示的行数不一样,一个为8行,一个为9行*/dcount = 0,ccount = 0;for( n = 0 ; n < line  ; n++){showLine(toff);toff +=  0x10 - toff%16;}}/*根据传入的便宜地址显示内存数据,以及对应的ascii值*/void showLine(unsigned int off){unsigned  int m = 0;unsigned   int toff = 0,moff = 0;moff = off ;/*记录实际要开始的内存位置*/toff = off - off%16;/*toff作为内存为16倍数的地址边界的起始位置*/printf("%04X:%04X ",sec,toff);/*显示前面八个,如果要现实的不是从16边界开始,前面显示空格,dcount < showNum 控制显示数据不超过*/for( m = 0; m < 8; m++,toff++){if( toff >=  moff && dcount < showNum ){printf(" %02X",unit(sec,toff));dcount++;}elseprintf("   ");}/*显示中间的横杠,如果开始处是16的边界后八位,则不现实横杠,*/if( off%16 < 8 && dcount<showNum)printf("-");elseprintf(" ");/*显示后面八位,同理,超过范围就显示空格*/for( m = 0; m < 8;  m++, toff++){if( toff >=  moff  && dcount<showNum ){printf("%02X ",unit(sec,toff));dcount++;}elseprintf("   ");}printf("  ");toff = off - off%16;/*数据显示又开始从16边界开始*//*显示内存字节对应的ascii符号,不在范围内就显示空格*/for( m = 0; m < 16;  m++, toff++){/**/if( toff >=  moff && ccount<showNum ){if( unit(sec,toff) > 32 &&  unit(sec,toff) < 126)printf("%c",unit(sec,toff));elseprintf(".");ccount++;}elseprintf(" ");}printf("   ");}/*将十六进制字符串转化为数字*/int str2Hex( char *pstr){    int ans = 0;    char *pt;    pt = pstr;if( 0 == strcmp(pt,"ds") ||  0 == strcmp(pt,"DS") || 0 == strcmp(pt,"Ds") ||  0 == strcmp(pt,"dS") ){return _DS;}else if(  0 == strcmp(pt,"ES") ||  0 == strcmp(pt,"es") || 0 == strcmp(pt,"Es") ||  0 == strcmp(pt,"eS") ){return _ES;}    while( *pt )    {  ans = ans<<4;        if( ( *pt >=  'A' && *pt <=  'F' ) || ( *pt >=  'a' && *pt <=  'f' ) )               ans  = ans | ((*pt & 0x5f) -0x37);        else               ans  = ans | (*pt) -0x30;        pt++;    }    return ans;}


 运行效果

 

原创粉丝点击