操作系统全局描述符表编译错误

时间:2013-12-14 22:32:11

标签: c++ c operating-system c++builder

我是操作系统开发的新手,我找到了一个半简单的操作系统来帮助启动,操作系统是"Test Os kernel",我下载并使用bochs运行它,所以我决定进入下一个级别并尝试编译,实际上我使用MinGW Developer Studio 2.05,而且我的操作系统是vista而不是linux。

当我尝试编译项目时,我收到以下段错误:

kern\.\memory\gdt.c:113: error: conflicting types for 'GDT_set_descriptor'

kern\.\memory\gdt.c:85: error: previous implicit declaration of 'GDT_set_descriptor' was here

kern\.\memory\gdt.c:145: error: conflicting types for 'GDT_install'

kern\.\memory\gdt.c:93: error: previous implicit declaration of 'GDT_install' was here
kern\kernel.c: In function `_start':

kern\kernel.c:29: warning: implicit declaration of function `main'
kern\kernel.c: In function `main':

kern\kernel.c:36: warning: unused variable `cmd'

tos.exe - 4 error(s), 38 warning(s)

这里的文件包含错误:

#include "../../kernel_components/libc/types.h" 

/*
1-gdtdescriptor structure : the feilds of a gdt descriptor
2-gdt itelf is an array of gdtdescriptors, it contains all the gdtdescriptors
3-gdtpointer is a structure that indicates the place of the gdt in memory, this pointer is needed by the gdt register,
*/

#define GDTSIZE 16  //only 16 segments are mapped by the GDT


/*! 
 * gdtDescriptor :  each gdt descriptor represents a segment in memory
 */
typedef struct gdtDescriptor
{
    u16 segmentLimit_0_15;  //the first 16bit of the segment limit (its length)
    u16 segmentBase_0_15;   //the first 16bit of the segment Base (its beginning)
    u8  segmentBase_16_23;  //8bits in the midle for the segment base (its length)
    u8  segmentType : 4;    //data segment or code segment or stack segment
    u8  segmentOrSystemCall :1;//to revise the name of this after you know what it does
    u8  Ring:2; //ring0 is kernel segment and ring=3 for user mode segment,this used for protection
    u8  presentOrSwaped:1;  //to indicate if the segment is present in memory or it has been swaped to the HDD
    u8  segmentLimit_16_19:4;
    u8  NotUsed:2;      //this 2 bits feild is not used , so just put it to 0
    u8  instructionSize:1;  //instructionSize=1 for 32bit instructions
    u8  limitUnit:1;    //0 if the limit is expressed in bytes or 1 if the limit is in pages
    u8  segmentBase_24_31;
} __attribute__ ((packed)); //__attribute__((packed)) so that the compiler doesn't change this structure and optimize it

struct gdtDescriptor GDT[GDTSIZE];//the global descriptor table,is an array of gdtDescriptors (segment entries)

/*!
 * the folowing are used to indicate the type of segment, we use afrendly names instead of using binary parameters
 * they are used as parameters of the function GDT_set_descriptor(.....)
 */
#define segmentType_CS  0xB //the segment is a code segment
#define segmentType_DS  0x3 //to indicate that the segment being created is a data segment
#define kernelMode  0x0 //ring0, a segment used to contain kernel code
#define userMode    0x3 //ring3, used for ordinary applications that dont belong to the lernel
#define presentInMemory 0x1 //the segment is present in memory or is swapped to a backbone (a disk for exmple)
#define _32bitInstructions 0x1  //instructions in the segment are 32 bit instructions
#define _16bitInstructions 0x0
#define limitInBytes    0x0 //the limit of the segment is expressed in bytes (limit=0x100 means 0x100 bytes)  
#define limitInPages    0x1 //(limit=0x100 means 0x100 pages with each page can be 4k or 4M (on intel!)


/*! 
 * gdtPointer :  the gdt pointer is used to indicate the place of the gdt in memory
 */
typedef struct gdtPointer
{
    u16 limit;
    u32 base;
} __attribute__ ((packed));



u32 GDT_descriptors_number=0;   //the number of descriptors in the GDT
struct gdtPointer gdtr;


/*! 
 * GDT_init :  initialize the gdt table : insert the code and data segment and copy the gdt to a new place 
 */
 void GDT_init()
{
    //the first GDT is null
    **===============ERROR 2** GDT_set_descriptor(1,0x0,0xfffff,segmentType_CS,0x1,kernelMode,presentInMemory,_32bitInstructions,limitInPages);
    GDT_set_descriptor(2,0x0,0xfffff,segmentType_DS,0x1,kernelMode,presentInMemory,_32bitInstructions,limitInPages);

    //initialize the GDT pointer
    gdtr.base=GDT;
    gdtr.limit = sizeof(struct  gdtDescriptor)*GDTSIZE; 

    //make this GDT the system GDT by loading it to tne gdtr regiter
    GDT_install(); **===============ERROR 4**
}


/*! 
 * GDT_set_descriptor :  set a GDT descriptor,
 *  u32 descriptor  : witch descriptor to set (the descriptor 0 is not used),1 means the first descriptor
    u8  segmentType : 4;    //data segment or code segment or stack segment
    u8  segmentOrSystemCall :1;//to revise the name of this after you know what it does
    u8  Ring:2; //ring0 is kernel segment and ring=3 for user mode segment,this used for protection
    u8  presentOrSwaped:1;  //to indicate if the segment is present in memory or it has been swaped to the HDD
    u8  segmentLimit_16_19:4;
    u8  NotUsed:2;      //this 2 bits feild is not used , so just put it to 0
    u8  instructionSize:1;  //instructionSize=1 for 32bit instructions
    u8  limitUnit:1;    //0 if the limit is expressed in bytes or 1 if the limit is in pages
    u32  segmentBase : adresse of the beginnig of the segment
    u32 limit :size of the descriptor, if limitUnit=limitInBytes so this limit is expressed in byte not in pages
 * 
 */
void GDT_set_descriptor(u32 descriptor,u32 base,u32 limit,u8 segmentType,u8 segmentOrSystemCall,u8 ring,u8 presentOrSwaped, u8 instructionSize, u8 limitUnit)
{**===============ERROR 1**
    struct gdtDescriptor gd;

    //set gdt base
    gd.segmentBase_0_15=(base & 0xffff);
    gd.segmentBase_16_23=((base>>16) & 0xff);
    gd.segmentBase_24_31=((base>>24) & 0xff);

    //set gdt limit
    gd.segmentLimit_0_15= (limit & 0xffff);
    gd.segmentLimit_16_19=((limit>>16)  & 0xf);

    //other descriptor bits
    gd.segmentType=segmentType;
    gd.segmentOrSystemCall=segmentOrSystemCall;
    gd.Ring=ring;
    gd.presentOrSwaped=presentOrSwaped;
    gd.NotUsed=0;
    gd.instructionSize=instructionSize;
    gd.limitUnit=limitUnit;

    //add this gd descriptor to the GDT table
    GDT[descriptor]=gd;

}



/*! 
 * GDT_install :  load the new GDT to the gdtr register, that means 
 */     
void GDT_install()**===============ERROR 3**
{
    //we need assembly here ! to make the GDTR register points our new GDT 
    asm("lgdt (gdtr)");
}


/*! 
 * GDT_install :  load the new GDT to the gdtr register, that means 
 */     
void GDT_load_descriptor(u32 descriptor)
{
    //this function must be edited so that we can add a  code descriptor or a data descriptor
    //for exemple  GDT_load_descriptor_CS(2) this will load the second descriptor as a CS segment ie cs<--descriptor(2) 
}

4个错误我在代码中的位置进行了分配 =============== ERROR number

那么可能是什么问题?

1 个答案:

答案 0 :(得分:2)

问题是GDT_set_descriptor的定义在引用之后发生

如果在没有前面的定义或声明的情况下调用函数,编译器会做出某些假设(“隐式声明”) - 这些假设对应于原始C语言实现中的默认假设:返回值假定为整数,整数小于“int”的-type参数被提升为int等。在这种情况下,编译器稍后会遇到具有不同返回值和参数的函数的实际定义。这个错误基本上告诉你“我已经假设了,但现在你告诉我这个”。

易于修复。或者:
(a)反转源中函数的顺序,使得被调用函数在文件中出现的时间早于调用代码 (b)提供文件顶部附近函数的前向声明(或通常通过单独的头文件完成)。

(a)通常工作量较少,但(b)通常是一种更通用的解决方案 - 特别是如果您预计需要从多个源模块调用相应的函数,通常最容易将声明放入标题中。 / p>