计算机科学与技术学院系统软件开发实践报告姓名:王冬升容易偏重目录1借助Flex进行词法分析 (2)1.1实验内容 (2)1.2实验要求 (2)1.3程序代码 (2)1.4实验结果 (4)2借助Flex/Bison进行语法分析 (5)2.1实验内容 (5)2.2实验要求 (5)8参考文献……………………………………………………………………1借助Flex进行词法分析1.1实验内容给定C语言的一个子集,具体内容如下:1.下面是语言的关键字:elseifswitchforintfloatreturnvoidwhile所有的关键字都是保留字,并且必须是小写。
2.下面是专用符号:+-*/<<=>>===!==;,()[]{}/**/3.其他标记是标识符(ID)和数字(NU),通过下列正则表达式定义:ID=letterletter*NUM=digitdigit*letter=a|..|z|A|..|Zdigit=0|..|9注:小写和大写字母是有区别的。
4.空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
(即注digit[0-9]id{letter}+number{digit}+enter[\n]spchar("{"|"}"|"["|"]"|"("|")"|";"|"="|","|"+"|"-"|"*"|"/"|"<"|"<="|">"|">="|"=="|"!=")comment\/\*(\*[^/]|[^*])*\*\/kwd(else|if|switch|for|int|float|return|void|while)%%{ws}{}{comment}{}{enter}{lineno++;}{kwd}{fprintf(yyout,"%d行\tkeywod\t%s\n",lineno,yytext);}usingnamespacestd;intmain(){inta;intd=123456;floatb=123.45;inte=9;a=(1+2-1)*4/2;if(a>b)cout<<"a>b"<<endl;elsecout<<"a<=b"<<endl;cout<<a<<endl;cout<<b<<endl;cout<<"Welcometoc++"<<endl;return0;} typedefunsignedintuint;uintxx;uintyy;2.4实验步骤yyparse(void)#elseintyyparse();#endif#endif改为intyyparse()或者intyyparse(void)4、yyin=stdin;5、解析之前,设置yyin为输入文件指针externFILE*yyin;if(!(yyin=fopen(filename,"r"))){printf("thefilenotexist\n");exit(0);}2.5实验结果avgCal.l源码%{#include"cal.tab.h"%}%optionnoyywrapinteger[0-9]+dreal([0-9]*"."[0-9]+)ereal([0-9]*"."[0-9]+[EedD][+-]?[0-9]+)real{dreal}|{ereal}nl\nplus"+"minus"-"times"*"divide"/"lp"("rp")"module"%"power"^"%token<integer>INTEGER%startlines%tokenNUMBERNL%tokenPLUSMINUSTIMESDIVIDEMODULEPOWERLPRP%type<real>rexpr%type<integer>iexpr%leftPLUSMINUS/*leftassociative*/%leftTIMESDIVIDEMODULE/*leftassociative*/%leftPOWER%leftUNARYMINUS%%lines:/*nothing*/|lineslineNL|lineserrorNL {yyerror();yyerrok;};line:iexpr {printf("%d\n",$1);}|rexpr{printf("%lf\n",$1);};iexpr:INTEGER{$$=$2;};rexpr:REAL{$$=$1;}|rexprPLUSrexpr{$$=$1+$3;}|rexprMINUSrexpr{$$=$1-$3;}|rexprTIMESrexpr{$$=$1*$3;}|rexprDIVIDErexpr{if($3)$$=$1/$3;else{$$=$1;printf(stderr,"%d.%d-%d.%d:divisionbyzero", @3.first_line,@3.first_column,@st_line,@st_column);}}|rexprPOWERrexpr{$$=pow($1,$3);}|LPrexprRP{$$=$2;}|rexprTIMESiexpr{$$=$1*(double)$3;}|rexprDIVIDEiexpr{if($3)$$=$1/(double)$3;else{$$=$1;printf(stderr,"%d.%d-%d.%d:divisionbyzero", @3.first_line,@3.first_column,@st_line,@st_column);}}|rexprPOWERiexpr{$$=pow($1,(double)$3);};%%voidmain(){yyparse();}intyyerror(char*msg){printf("Error:%sencountered\n",msg);}3.5实验结果intmain(void){printf("hello!\n");return0;}在实验环境中右键->从模板创建->空文件,将上述示例代码输入1)保存为hello.c打开命令行,输入以下命令:2)编译:gcc-Wallhello.c-ohello3)执行:./hello操作及结果截图:4.4GDB调试练习1)输入命令:gcc-ohellohello.c–g进行编译2)输入命令:gdb进入调试3)依次输入以下命令熟悉gdb调试filehello:进入hello文件操作系统是一个软件,也需要通过某种机制加载并运行它。
在这里我们将通过另外一个更加简单的软件-bootloader来完成这些工作。
为此,我们需要完成一个能够切换到x86的保护模式并显示字符的bootloader,为启动操作系统ucore做准备。
lab1提供了一个非常小的bootloader和ucoreOS,整个bootloader执行代码小于512个字节,这样才能放到硬盘的主引导扇区中。
通过分析和实现这个bootloader和ucoreOS,读者可以了解到:1)计算机原理CPU的编址与寻址:基于分段机制的内存管理CPU的中断机制外设:串口/并口/CGA,时钟,硬盘2)Bootloader软件编译运行bootloader的过程调试bootloader的方法PC启动bootloader的过程ELF执行文件的格式和加载外设访问:读硬盘,在CGA上显示字符串3)ucoreOS软件编译运行ucoreOS的过程ucoreOS的启动过程调试ucoreOS的方法continue(继续执行)ctrl+c(中断)quit(推出5.4操作系统启动过程当X86一开始加电时候,启动是实模式(实地址寻址模式)(早期的为了ss向下兼容以前的80X86一开始启动是16位的实模式)第一条地址:段地址寄存器CSCS和EIP结合在一起来决定它启动的第一条地址:按实模式的寻址方式:cs(base)基址+EIP->bios(指向bios)这个bios固件会去加载磁盘或者硬盘的第一个主引导扇区(即执行0号扇区lab1中的bootloader)它完成来对我们说的这个操作系统uCore的进一步加载Bootloader的工作:1)要从实模式切换到保护模式,就是从实模式的16位的寻址空间切换到了32位的寻址空间寻址空间:从1M(物理地址=左移4位的段地址+偏移地址)变为4G,段机制可以正常工作了。
对系统寄存器CRO(或者叫控制寄存器)把它的第0号bit置成1那么就意味着以理解基于段页式内存地址的转换机制理解页表的建立和使用方法理解物理内存的管理方法6.2实验内容本次实验包含三个部分。
首先了解如何发现系统中的物理内存;然后了解如何建立对物理内存的初步管理,即了解连续物理内存管理;最后了解页表相关的操作,即如何建立页表来实现虚拟内存到物理内存之间的映射,对段页式内存管理机制有一个比较全面的了解。
本实验里面实现的内存管理还是非常基本的,并没有涉及到对实际机器的优化,比如针对cache的优化等7实验体会在老师的指导下和与同学之间互相讨论学习,经过六周的时间终于完成了有关系统软件开发实践课程的学习,感觉无论从专业知识还是个人能力上都收获很多。
首先是有关本实验课程六个小实验的收获与总结,第一部分编译原理实验中第一个flex词法分析器的实验相对比较简单,完成的相对顺利,第二个bison语法分析器实验比较难,虽然实验指导中已经给出了源码链接,第三个编译综合实验计算器也只完成了部分基础运算符的功能,有关自定义函数的功能部分没有完成;第二部分操作系统实验因为有详细的实验指导书和相关的视频,通过视频课程的学习和参考实验指导书完成了基本的实。