[os]main-2

本文深入探讨了在自定义系统中使用printf函数打印内存大小时遇到的问题,发现是由于内存映射关系未正确设置导致堆栈段与数据段地址不同。通过分析堆栈情况和汇编代码,解释了为何即使memory_end不为0,打印结果仍显示为0。最终揭示了解决方案,确保内存映射关系的正确性。

刚刚进入内核后,开始在main中进行代码实现。

想试一下在main中实现一个printf打印功能,代码类似如下:

//main.c
int printf(char *fmt,...)
{
	va_list args;
	int i;
	va_start(args,fmt);
//	write(1,printbuf,i=vsprintf(printbuf,fmt,args));
	write(printbuf,i=vsprintf(printbuf,fmt,args));
	va_end(args);	
	return i;
}

void main(void)
{
	printf("total memory = %x",memory_end);《------------原来想打印出机器的内存大小,但是发现即使memory_end!=0,打印结果也为0

	return;
// vsprintf.c
int vsprintf(char *buf,char *fmt,va_list args)
{
   ......
	case 'x':
		case 'X':
			tmpn=va_arg(args,int);
			i=0;
			if(tmpn==0){
				*buf++='0';
				ret++;
			}
...
}


结果发现,在VS和linux下,都能正常输出字符串,但是在自己引导的系统中,却只能输出以下内容

total memory = 0

※已知memory_end不为0

经过调查,发现原来原因是刚刚进入main后,内存的映射关系还没设置,由于堆栈段的实际段地址和数据段的段地址不同导致

[原因详细]

①之前head.s里的设置里面,堆栈段描述符如下

.quad 0x00c0920900000fff /* 16Mb */ #堆栈段最大长度16M。

数据段

.quad 0x00c0920000000fff /* 16Mb */ # 数据段最大长度16M。

②在调用vsprintf后,执行到

tmpn=va_arg(args,int);

汇编代码为:

(0) [0x000000000000a4e0] 0008:000000000000a4e0 (unk. ctxt): lea eax, dword ptr s
s:[esp+36] ; 8d442424


这句话时候的堆栈情况

| STACK 0x0009fec0 [0x00000407]
| STACK 0x0009fec4 [0xfee0c000]
| STACK 0x0009fec8 [0x00314d54]
| STACK 0x0009fecc [0x900044b0]
| STACK 0x0009fed0 [0x9000feee]
| STACK 0x0009fed4 [0xfee00000]
| STACK 0x0009fed8 [0x00000000]
| STACK 0x0009fedc [0x0000a550]<---------printf函数返回地址
| STACK 0x0009fee0 [0x0000a784]<---------字符串total memory = %x
| STACK 0x0009fee4 [0x00003039]<---------memory_end的值
| STACK 0x0009fee8 [0x0000ff00]
| STACK 0x0009feec [0x00000000]
| STACK 0x0009fef0 [0x0c000607]
| STACK 0x0009fef4 [0x90009000]
| STACK 0x0009fef8 [0x0000a515]
| STACK 0x0009fefc [0x0000940c]



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值