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

被折叠的 条评论
为什么被折叠?



