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

该博客介绍了一个程序,旨在模拟DOS下的Debug工具的D子命令,用于显示内存数据。虽然未实现错误位置提示和'l'参数功能,但通过字符串判断处理命令。代码存在冗余问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模拟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();
	else
		printf("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++;
			}
			else
				printf("   ");
	}
	
	/*显示中间的横杠,如果开始处是16的边界后八位,则不现实横杠,*/
	if( off%16 < 8 && dcount<showNum)
		printf("-");
	else
		printf(" ");
		
	/*显示后面八位,同理,超过范围就显示空格*/	
	for( m = 0; m < 8;  m++, toff++)
	{
			if( toff >=  moff  && dcount<showNum )
			{
				printf("%02X ",unit(sec,toff));
				dcount++;
			}
			else
				printf("   ");
	}
	
	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));
				else
					printf(".");
				ccount++;
			}
			else
				printf(" ");
	}
	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;
}


 运行效果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值