8086汇编和c语言混合实现操作系统.docx

上传人:b****6 文档编号:7528149 上传时间:2023-01-24 格式:DOCX 页数:46 大小:310.05KB
下载 相关 举报
8086汇编和c语言混合实现操作系统.docx_第1页
第1页 / 共46页
8086汇编和c语言混合实现操作系统.docx_第2页
第2页 / 共46页
8086汇编和c语言混合实现操作系统.docx_第3页
第3页 / 共46页
8086汇编和c语言混合实现操作系统.docx_第4页
第4页 / 共46页
8086汇编和c语言混合实现操作系统.docx_第5页
第5页 / 共46页
点击查看更多>>
下载资源
资源描述

8086汇编和c语言混合实现操作系统.docx

《8086汇编和c语言混合实现操作系统.docx》由会员分享,可在线阅读,更多相关《8086汇编和c语言混合实现操作系统.docx(46页珍藏版)》请在冰豆网上搜索。

8086汇编和c语言混合实现操作系统.docx

8086汇编和c语言混合实现操作系统

实验三

一、实验目的

1.掌握TASM汇编语言与TURBOC语言汇合编程的方法。

2.实现内核与引导程序分离,掌握软盘上引导操作系统方法。

3.设计并实现一种简单的作业控制语言,建立具有较友好的控制命令的批处理原型操作系统,掌握操作系统提供用户界面和内部功能的实现方法。

二、实验内容

在实验二的基础上,进化你的原型操作系统,增加下列操作系统功能:

(1)将原型操作系统分离为引导程序和MYOS内核,由引导程序加载内核;

(2)内核由汇编语言kernal.asm和c语言kernal.c二个模块生成;

(3)利用C语言实现作业控制语言mJCB,原型操作系统在当前行显示一个指示符(可以是简单的一个字符或你的学号之类),允许用户输入一行命令(回车结束,语法由你设计),操作系统解释命令并完成相应的功能(3个以上的内置功能,如time、date、asc等,而且能执行软盘上的某个用户程序),并在你的实验报告中详细介绍你的mJCB语言的语法格式和功能。

三、实验报告

1、涉及的基础知识和实验环境工具综述、你的解决方案包括程序算法原理或流程图、程序模块说明、变量定义与作用说明、数据结构组织等

A.实验环境工具综述:

本次试验环境为VMware9平台上搭建的8086虚拟机,编译器为tasm,tcc,链接器为tlink,通过Winhex剪辑2进制文件,并用DiskWriter工具将主程序写入虚拟软盘,通过虚拟机加载软盘实现裸机运行。

B.算法原理:

a)计算机启动后,通过引导扇区加载软盘上余下的有效扇区。

b)引导扇区安装必要的中断,如8号中断用以动态显示时间,21号中断用以用户程序的返回,设置栈指针,数据段指针,建立c语言运行环境,设置计数器,用以动态显示时间。

配置完成后,转入基于c语言的控制程序的运行。

c)基于c语言的控制程序无限重复向输入端请求命令,解析命令,跳转调用对应程序,但接收到重启命令时重启,接到关机命令时进行关机。

d)系统总的实现为引导程序(osa.asm),汇编实现的c语言函数库(clib.asm),汇编实现的中断程序库(oslib.asm),c语言实现的控制台程序(osc.c)。

e)由于系统已搭建c语言运行环境,并提供了相应的库,再提供一个供用户用于链接c语言程序的启动程序,用户程序即可完全由c语言实现。

启动程序指定用户程序的偏移(如c9000.asm指定了用户的c程序偏移为9000h,可更改启动程序中的org来更改目标程序的偏移),并能够返回控制台(通过调用自己安装的int21H返回)。

C.程序模块说明:

a)clib.asm中汇编实现的c函数库

externcharcls();

功能:

清屏,清空第0页的显存

输入:

返回:

externintputs(constchar*str);

功能:

向当前光标位置输出字符串

输入:

字符串首地址

返回:

输出字符个数

externchar*gets(char*str);

功能:

读取字符串

输入:

字符串首地址

返回:

字符串首地址

externintstrlen(constchar*str);

功能:

求以0结束的字符串的长度

输入:

字符串首地址

返回:

字符从长度

externintgetchar(void);

功能:

读取字符

输入:

返回:

字符的ascii码

externintputchar(intc);

功能:

输出字符

输入:

字符c

返回:

字符c

externunsignedintport_in8(unsignedintport);

功能:

从port端口读入8位数据

输入:

端口号

返回:

读取的数据

externunsignedintport_in16(unsignedintport);

功能:

从port端口读入16位数据

输入:

端口号

返回:

读取的数据

externvoidport_out8(unsignedintport,unsignedintvalue);

功能:

向port端口输出8位数据value

输入:

端口号和数据

返回:

externvoidport_out16(unsignedintport,unsignedintvalue);

功能:

从port端口输出16位数据value

输入:

端口号和数据

返回:

externvoidsetp_cursor(unsignedintbh,unsignedintdh,unsignedintdl);

功能:

将第bh页的指针置于dh行dl列

输入:

页号bh,行号dh,列号dl

返回:

externvoidrun_pro(intord);

功能:

运行程序地址表中第ord号程序

输入:

程序序号

返回:

b)主控制程序:

osc.c

externcharcls();externintputs(constchar*str);

externchar*gets(char*str);

externintstrlen(constchar*str);

externintgetchar(void);

externintputchar(intc);

externunsignedintport_in8(unsignedintport);

externunsignedintport_in16(unsignedintport);

externvoidport_out8(unsignedintport,unsignedintvalue);

externvoidport_out16(unsignedintport,unsignedintvalue);

externvoidsetp_cursor(unsignedintbh,unsignedintdh,unsignedintdl);

externvoidrun_pro(intord);

voidinttostr(intx,char*str);

intstrtoint(char*str);

unsignedintbcdtodex(unsignedintx);

voidget_date(char*buf);/*yy-mm-dd*/

voidset_date(char*buf);

voidget_time(char*buf);/*hh:

mm:

ss*/

voidset_time(char*buf);

voidpre_time();

voidinterface();

intstrcmp(charstr1[],charstr2[]);

voidatoA(char*buf);

intdeal(char*buf);

intinside(intmin,intmax,intx);

intchange_time(intparas);

intislegal(inty,intm,intd);

intchange_date(intparas);

intshutdown(intparas);

intreboot(intparas);

intjc(intparas,char*buf);

charbuffer[80];

intcontrol=1;

charExit_Message[30]="\nPressanykeytoexit...";

unsignedintadd_Table[30]={0x9000,0,0xa000,0,0xb000,0};

cmain(){

intparas;

control=0;

while

(1)

{

cls();

interface();

gets(buffer);

setp_cursor(0,6,0);

paras=deal(buffer);

if(paras!

=0)

{

jc(paras,buffer);

puts(Exit_Message);

getchar();

}

}

}

c)用户程序:

cx0.ccx1.c

2、实验步骤、操作的主要过程、运行结果、屏幕画面截图等

A.实验步骤

a)编写代码

b)在dosbox上执行批处理文件0.bat,得到,执行9000.bat得到用户程序1,执行a000.bat得到用户程序2

c)使用WinHex将中7e00h到结束的所有数据写到虚拟软盘文件Tinix.img偏移为0的位置处,将用户程序1和用户程序2对应的代码写到1400h和2400h处。

d)从软盘启动虚拟机

B.屏幕截图

a)开机界面

b)时间设置

c)日期设置

d)运行程序地址表中的用户程序

e)指令参数错误检查

f)执行重启命令,由于重启时无法截图,只提供命令输入界面

g)关机指令

C.指令总结

a)Time修改cmos时间,不需要参数

b)Date修改cmos日期,不需要参数

c)Runx执行第x号用户程序,1<=x<=2,安装新程序x需扩展。

d)Reboot重启,不需要参数

e)Shutdown关机,不需要参数

四、实验心得体会

A.程序c语言环境的配置和实现,应基于编译器tcc默认的调用规范cdecl。

a)cdecl在8086上对c语言参数的入栈顺序为从右向左入栈,对栈的恢复由程序调用者caller实现,汇编实现c语言函数库时,不需要在函数中对栈进行恢复。

在汇编程序中调用c实现的函数,对参数压栈和对函数返回后要注意恢复。

b)cdecl对函数的返回值,8位,16位和32位分别存放于al、ax、dx和ax中,汇编中调用c实现的函数时返回值的获取为以上寄存器。

c)cdecl只对ds,ss,bp,si,di等寄存器进行保护。

当在汇编中调用c实现的函数时,若通用寄存器ax,bx,cx,dx中存在有意义的值,要自行进行压栈保护。

B.实现tcc的过程中,发现tcc在栈的处理上存在bug。

tcc编译tcc_bug文件得到的二进制文件,通过debug反汇编解析,发现,tcc对函数中的临时字符串buf的取值从[bx+offset]中取(产生错误的位置在tcc_bug.c文件中有标注),而bx默认的段地址为ds而不是ss。

当ds不等于ss时,会取出错误的值,产生乱码。

解决方法:

通过在引导程序中配置c语言环境时ds和ss设置相同的值,成功解决产生乱码的问题。

C.由于8086程序在dos上运行是使用int21h的4ch号功能返回控制台,本次实验对安装了仅有单个iret指令的21h中断,来实现初步对dos程序的小的兼容,用于与用户的c语言链接的启动程序使用int21h调用安装的iret进行返回控制台。

 

Osc.c

externcharcls();externintputs(constchar*str);

externchar*gets(char*str);

externintstrlen(constchar*str);

externintgetchar(void);

externintputchar(intc);

externunsignedintport_in8(unsignedintport);

externunsignedintport_in16(unsignedintport);

externvoidport_out8(unsignedintport,unsignedintvalue);

externvoidport_out16(unsignedintport,unsignedintvalue);

externvoidsetp_cursor(unsignedintbh,unsignedintdh,unsignedintdl);

externvoidrun_pro(intord);

voidinttostr(intx,char*str);

intstrtoint(char*str);

unsignedintbcdtodex(unsignedintx);

voidget_date(char*buf);/*yy-mm-dd*/

voidset_date(char*buf);

voidget_time(char*buf);/*hh:

mm:

ss*/

voidset_time(char*buf);

voidpre_time();

voidinterface();

intstrcmp(charstr1[],charstr2[]);

voidatoA(char*buf);

intdeal(char*buf);

intinside(intmin,intmax,intx);

intchange_time(intparas);

intislegal(inty,intm,intd);

intchange_date(intparas);

intshutdown(intparas);

intreboot(intparas);

intjc(intparas,char*buf);

charbuffer[80];

intcontrol=1;

charExit_Message[30]="\nPressanykeytoexit...";

unsignedintadd_Table[30]={0x9000,0,0xa000,0,0xb000,0};

cmain(){

intparas;

control=0;

while

(1)

{

cls();

interface();

gets(buffer);

setp_cursor(0,6,0);

paras=deal(buffer);

if(paras!

=0)

{

jc(paras,buffer);

puts(Exit_Message);

getchar();

}

}

/*control=1;*/

}

voidinttostr(intx,char*str)

{

intl=0;

inti,offset;

charbuf[10];

if(x==0)

{

str[0]='0';

str[1]=0;

return;

}

if(x<0)

{

x=-x;

offset=1;

str[0]='-';

}

else

offset=0;

while(x>0)

{

buf[l]=x%10+'0';

x=x/10;

l++;

}

for(i=0;i

str[l-i-1+offset]=buf[i];

str[l+offset]=0;

}

intstrtoint(char*str)

{

intlen=strlen(str);

inti;

intsou;

intp;

intans;

if(str[0]=='-')

{

sou=1;

p=-1;

}

else

{

sou=0;

p=1;

}

ans=0;

for(i=sou;i

ans=ans*10+(str[i]-'0');

returnans*p;

}

 

unsignedintbcdtodex(unsignedintx)

{

return(x>>4)*10+(x&0xf);

}

voidget_date(char*buf)/*yy-mm-dd*/

{

unsignedinty,m,d;

port_out8(0x70,9);/*获取年*/

y=port_in8(0x71)&0xff;

buf[0]=(y>>4)+'0';

buf[1]=(y&0xf)+'0';

buf[2]='-';

port_out8(0x70,8);/*获取月*/

m=port_in8(0x71)&0xff;

buf[3]=(m>>4)+'0';

buf[4]=(m&0xf)+'0';

buf[5]='-';

port_out8(0x70,7);/*获取日*/

d=port_in8(0x71)&0xff;

buf[6]=(d>>4)+'0';

buf[7]=(d&0xf)+'0';

buf[8]=0;

}

voidset_date(char*buf)

{

unsignedinty,m,d;

y=((buf[0]-'0')<<4)+buf[1]-'0';

port_out8(0x70,9);

port_out8(0x71,y);

m=((buf[3]-'0')<<4)+buf[4]-'0';

port_out8(0x70,8);

port_out8(0x71,m);

d=((buf[6]-'0')<<4)+buf[7]-'0';

port_out8(0x70,7);

port_out8(0x71,d);

}

voidget_time(char*buf)/*hh:

mm:

ss*/

{

unsignedinth,m,s;

port_out8(0x70,4);/*获取时*/

h=port_in8(0x71)&0xff;

buf[0]=(h>>4)+'0';

buf[1]=(h&0xf)+'0';

buf[2]=':

';

port_out8(0x70,2);/*获取分*/

m=port_in8(0x71)&0xff;

buf[3]=(m>>4)+'0';

buf[4]=(m&0xf)+'0';

buf[5]=':

';

port_out8(0x70,0);/*获取秒*/

s=port_in8(0x71)&0xff;

buf[6]=(s>>4)+'0';

buf[7]=(s&0xf)+'0';

buf[8]=0;

}

voidset_time(char*buf)

{

unsignedinth,m,s;

h=((buf[0]-'0')<<4)+buf[1]-'0';

port_out8(0x70,4);

port_out8(0x71,h);

m=((buf[3]-'0')<<4)+buf[4]-'0';

port_out8(0x70,2);

port_out8(0x71,m);

s=((buf[6]-'0')<<4)+buf[7]-'0';

port_out8(0x70,0);

port_out8(0x71,s);

}

voidpre_time()

{

charbuf[20];

{

/*setp_cursor(0,1,62);*/

/*puts("Time:

");*/

setp_cursor(0,1,70);

get_time(buf);

puts(buf);

/*setp_cursor(0,2,62);*/

/*puts("Date:

");*/

setp_cursor(0,2,70);

get_date(buf);

puts(buf);

}

}

voidinterface()

{

inti;

intpos[4];

pos[0]=0;

pos[1]=8;

pos[2]=60;

pos[3]=79;

cls();

setp_cursor(0,0,0);

for(i=0;i<80;++i)

putchar('=');

for(i=0;i<4;++i)

{

setp_cursor(0,1,pos[i]);

putchar('|');

}

for(i=0;i<4;++i)

{

setp_cursor(0,2,pos[i]);

putchar('|');

}

setp_cursor(0,3,0);

for(i=0;i<80;++i)

putchar('=');

setp_cursor(0,1,2);

puts("Lab03");

setp_cursor(0,1,62);

/*把以下部分放到pre_time,乱码,寻址问题?

*/

puts("Time:

");

setp_cursor(0,2,62);

puts("Date:

");

pre_time();

setp_cursor(0,2,30);

puts("MYOS3.0");

setp_cursor(0,4,0);

puts("Inputcommand:

");

setp_cursor(0,5,0);

for(i=0;i<80;++i)

putchar('-');

setp_cursor(0,4,14);

}

 

intstrcmp(charstr1[],charstr2[])

{

intlen1=strlen(str1);

intlen2=strlen(str2);

inti=0,j=0;

while(i

{

i++;

j++;

}

return(str2[j]-str1[i]);

}

voidatoA(char*buf)

{

intlen=strlen(buf);

inti;

for(i=0;i

if('a'<=buf[i]&&buf[i]<='z')buf[

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1