8086汇编和c语言混合实现操作系统_第1页
8086汇编和c语言混合实现操作系统_第2页
8086汇编和c语言混合实现操作系统_第3页
8086汇编和c语言混合实现操作系统_第4页
8086汇编和c语言混合实现操作系统_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、实验三一、实验目的1. 掌握TASM汇编语言与TURBO C语言汇合编程的方法。2. 实现内核与引导程序分离,掌握软盘上引导操作系统方法。3. 设计并实现一种简单的作业控制语言,建立具有较友好的控制命令的批处理原型操作系统,掌握操作系统提供用户界面和内部功能的实现方法。二、实验内容在实验二的基础上,进化你的原型操作系统,增加下列操作系统功能:(1)将原型操作系统分离为引导程序和MYOS内核,由引导程序加载内核;(2)内核由汇编语言kernal.asm和c语言kernal.c二个模块生成;(3)利用C语言实现作业控制语言mJCB,原型操作系统在当前行显示一个指示符(可以是简单的一个字符或你的学号

2、之类),允许用户输入一行命令(回车结束,语法由你设计),操作系统解释命令并完成相应的功能(3个以上的内置功能,如time、date、asc等,而且能执行软盘上的某个用户程序),并在你的实验报告中详细介绍你的mJCB语言的语法格式和功能。三、实验报告1、涉及的基础知识和实验环境工具综述、你的解决方案包括程序算法原理或流程图、程序模块说明、变量定义与作用说明、数据结构组织等A 实验环境工具综述:本次试验环境为VMware9平台上搭建的8086虚拟机,编译器为tasm,tcc,链接器为tlink,通过Winhex剪辑2进制文件,并用DiskWriter工具将主程序写入虚拟软盘,通过虚拟机加载软盘实现

3、裸机运行。B 算法原理:a) 计算机启动后,通过引导扇区加载软盘上余下的有效扇区。b) 引导扇区安装必要的中断,如8号中断用以动态显示时间,21号中断用以用户程序的返回,设置栈指针,数据段指针,建立c语言运行环境,设置计数器,用以动态显示时间。配置完成后,转入基于c语言的控制程序的运行。c) 基于c语言的控制程序无限重复向输入端请求命令,解析命令,跳转调用对应程序,但接收到重启命令时重启,接到关机命令时进行关机。d) 系统总的实现为引导程序(osa.asm),汇编实现的c语言函数库(clib.asm),汇编实现的中断程序库(oslib.asm),c语言实现的控制台程序(osc.c)。e) 由于

4、系统已搭建c语言运行环境,并提供了相应的库,再提供一个供用户用于链接c语言程序的启动程序,用户程序即可完全由c语言实现。启动程序指定用户程序的偏移(如c9000.asm指定了用户的c程序偏移为9000h,可更改启动程序中的org来更改目标程序的偏移),并能够返回控制台(通过调用自己安装的int 21H返回)。C 程序模块说明:a) clib.asm中汇编实现的c函数库extern char cls();功能:清屏,清空第0页的显存输入:无返回:无extern int puts(const char * str);功能:向当前光标位置输出字符串输入:字符串首地址返回:输出字符个数extern c

5、har* gets(char* str);功能:读取字符串输入:字符串首地址返回:字符串首地址extern int strlen(const char *str);功能:求以0结束的字符串的长度输入:字符串首地址返回:字符从长度extern int getchar(void);功能:读取字符输入:无返回:字符的ascii码extern int putchar(int c);功能:输出字符输入:字符c返回:字符cextern unsigned int port_in8(unsigned int port);功能:从port端口读入8位数据输入:端口号返回:读取的数据extern unsigned

6、 int port_in16(unsigned int port); 功能:从port端口读入16位数据输入:端口号返回:读取的数据extern void port_out8(unsigned int port, unsigned int value); 功能:向port端口输出8位数据value输入:端口号和数据返回:无 extern void port_out16(unsigned int port, unsigned int value); 功能:从port端口输出16位数据value输入:端口号和数据返回:无extern void setp_cursor(unsigned int bh

7、, unsigned int dh, unsigned int dl); 功能:将第bh页的指针置于dh行dl列 输入:页号bh,行号dh,列号dl 返回:无extern void run_pro(int ord); 功能:运行程序地址表中第ord号程序输入:程序序号返回:无b) 主控制程序:osc.cextern char cls(); extern int puts(const char * str);extern char* gets(char* str);extern int strlen(const char *str);extern int getchar(void);extern

8、 int putchar(int c);extern unsigned int port_in8(unsigned int port);extern unsigned int port_in16(unsigned int port);extern void port_out8(unsigned int port, unsigned int value);extern void port_out16(unsigned int port, unsigned int value);extern void setp_cursor(unsigned int bh, unsigned int dh, un

9、signed int dl);extern void run_pro(int ord);void inttostr(int x, char *str);int strtoint(char *str);unsigned int bcdtodex(unsigned int x);void get_date(char* buf);/*yy-mm-dd*/void set_date(char *buf);void get_time(char* buf);/*hh:mm:ss*/void set_time(char *buf);void pre_time();void interface();int s

10、trcmp(char str1, char str2);void atoA(char *buf);int deal(char *buf);int inside(int min, int max, int x);int change_time(int paras);int islegal(int y, int m, int d);int change_date(int paras);int shutdown(int paras);int reboot(int paras);int jc(int paras, char *buf);char buffer80;int control = 1;cha

11、r Exit_Message30 = "nPress any key to exit."unsigned int add_Table30 = 0x9000, 0, 0xa000, 0, 0xb000, 0;cmain()int paras;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.c

12、 cx1.c2、实验步骤、操作的主要过程、运行结果、屏幕画面截图等A 实验步骤a) 编写代码b) 在dosbox上执行批处理文件0.bat,得到,执行9000.bat得到用户程序1,执行a000.bat得到用户程序2c) 使用WinHex将中7e00h到结束的所有数据写到虚拟软盘文件Tinix.img偏移为0的位置处,将用户程序1和用户程序2对应的代码写到1400h和2400h处。d) 从软盘启动虚拟机B 屏幕截图a) 开机界面b) 时间设置c) 日期设置 d) 运行程序地址表中的用户程序e) 指令参数错误检查f) 执行重启命令,由于重启时无法截图,只提供命令输入界面g) 关机指令C 指令总结

13、a) Time 修改cmos时间,不需要参数b) Date 修改cmos日期,不需要参数c) Run x执行第x号用户程序,1<=x<=2,安装新程序x需扩展。d) Reboot 重启,不需要参数e) Shutdown 关机,不需要参数四、实验心得体会A. 程序c语言环境的配置和实现,应基于编译器tcc默认的调用规范cdecl。a) cdecl在8086上对c语言参数的入栈顺序为从右向左入栈,对栈的恢复由程序调用者caller实现,汇编实现c语言函数库时,不需要在函数中对栈进行恢复。在汇编程序中调用c实现的函数,对参数压栈和对函数返回后要注意恢复。b) cdecl对函数的返回值,8

14、位,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时,会取出错误的值,

15、产生乱码。解决方法:通过在引导程序中配置c语言环境时ds和ss设置相同的值,成功解决产生乱码的问题。C. 由于8086程序在dos上运行是使用int 21h的4ch号功能返回控制台,本次实验对安装了仅有单个iret指令的21h中断,来实现初步对dos程序的小的兼容,用于与用户的c语言链接的启动程序使用int 21h调用安装的iret进行返回控制台。Osc.cextern char cls(); extern int puts(const char * str);extern char* gets(char* str);extern int strlen(const char *str);ext

16、ern int getchar(void);extern int putchar(int c);extern unsigned int port_in8(unsigned int port);extern unsigned int port_in16(unsigned int port);extern void port_out8(unsigned int port, unsigned int value);extern void port_out16(unsigned int port, unsigned int value);extern void setp_cursor(unsigned

17、 int bh, unsigned int dh, unsigned int dl);extern void run_pro(int ord);void inttostr(int x, char *str);int strtoint(char *str);unsigned int bcdtodex(unsigned int x);void get_date(char* buf);/*yy-mm-dd*/void set_date(char *buf);void get_time(char* buf);/*hh:mm:ss*/void set_time(char *buf);void pre_t

18、ime();void interface();int strcmp(char str1, char str2);void atoA(char *buf);int deal(char *buf);int inside(int min, int max, int x);int change_time(int paras);int islegal(int y, int m, int d);int change_date(int paras);int shutdown(int paras);int reboot(int paras);int jc(int paras, char *buf);char

19、buffer80;int control = 1;char Exit_Message30 = "nPress any key to exit."unsigned int add_Table30 = 0x9000, 0, 0xa000, 0, 0xb000, 0;cmain()int paras;control = 0;while (1)cls();interface();gets(buffer);setp_cursor(0, 6, 0);paras = deal(buffer);if (paras != 0) jc(paras, buffer);puts(Exit_Mess

20、age);getchar();/*control = 1;*/void inttostr(int x, char *str)int l = 0;int i, offset;char buf10;if (x = 0) str0 = '0'str1 = 0;return;if (x < 0)x = -x;offset = 1;str0 = '-'elseoffset = 0;while (x > 0)bufl = x % 10 + '0'x = x / 10;l+;for (i = 0; i < l; +i)strl - i - 1

21、 + offset = bufi;strl + offset = 0;int strtoint(char *str)int len = strlen(str);int i;int sou;int p;int ans; if (str0 = '-')sou = 1;p = -1;elsesou = 0;p = 1;ans = 0;for (i = sou; i < len; +i)ans = ans * 10 + (stri - '0');return ans * p;unsigned int bcdtodex(unsigned int x)return (

22、x >> 4) * 10 + (x & 0xf);void get_date(char* buf)/*yy-mm-dd*/unsigned int y, m, d;port_out8(0x70, 9); /*获取年*/y = port_in8(0x71) & 0xff;buf0 = (y >> 4) + '0'buf1 = (y & 0xf) + '0'buf2 = '-'port_out8(0x70, 8);/*获取月*/m = port_in8(0x71) & 0xff;buf3 = (

23、m >> 4) + '0'buf4 = (m & 0xf) + '0'buf5 = '-'port_out8(0x70, 7);/*获取日*/d = port_in8(0x71) & 0xff;buf6 = (d >> 4) + '0'buf7 = (d & 0xf) + '0'buf8 = 0;void set_date(char *buf)unsigned int y, m, d;y = (buf0 - '0') << 4) + buf

24、1 - '0'port_out8(0x70, 9); port_out8(0x71, y);m = (buf3 - '0') << 4) + buf4 - '0'port_out8(0x70, 8);port_out8(0x71, m);d = (buf6 - '0') << 4) + buf7 - '0'port_out8(0x70, 7);port_out8(0x71, d);void get_time(char* buf)/*hh:mm:ss*/unsigned int h, m, s

25、;port_out8(0x70, 4); /*获取时*/h = port_in8(0x71) & 0xff;buf0 = (h >> 4) + '0'buf1 = (h & 0xf) + '0'buf2 = ':'port_out8(0x70, 2);/*获取分*/m = port_in8(0x71) & 0xff;buf3 = (m >> 4) + '0'buf4 = (m & 0xf) + '0'buf5 = ':'port_out8(0x

26、70, 0);/*获取秒*/s = port_in8(0x71) & 0xff;buf6 = (s >> 4) + '0'buf7 = (s & 0xf) + '0'buf8 = 0;void set_time(char *buf)unsigned int h, m, s;h = (buf0 - '0') << 4) + buf1 - '0'port_out8(0x70, 4); port_out8(0x71, h);m = (buf3 - '0') << 4)

27、+ buf4 - '0'port_out8(0x70, 2);port_out8(0x71, m);s = (buf6 - '0') << 4) + buf7 - '0'port_out8(0x70, 0);port_out8(0x71, s);void pre_time()char buf20;/*setp_cursor(0, 1, 62);*/*puts("Time:");*/setp_cursor(0, 1, 70);get_time(buf);puts(buf);/*setp_cursor(0, 2, 62

28、);*/*puts("Date:");*/setp_cursor(0, 2, 70);get_date(buf);puts(buf);void interface()int i;int pos4;pos0 = 0;pos1 = 8;pos2 = 60;pos3 = 79;cls();setp_cursor(0, 0, 0);for (i = 0; i < 80; +i)putchar('=');for (i = 0; i < 4; +i)setp_cursor(0, 1, posi);putchar('|');for (i = 0

29、; i < 4; +i)setp_cursor(0, 2, posi);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_tim

30、e();setp_cursor(0, 2, 30);puts("MYOS 3.0");setp_cursor(0, 4, 0);puts("Input command:");setp_cursor(0, 5, 0);for (i = 0; i < 80; +i)putchar('-');setp_cursor(0, 4, 14);int strcmp(char str1, char str2)int len1 = strlen(str1);int len2 = strlen(str2);int i = 0, j = 0;while

31、(i < len1 && j < len2 && str1i = str2j)i+;j+;return (str2j - str1i);void atoA(char *buf)int len = strlen(buf);int i;for (i = 0; i < len; +i)if ('a' <= bufi && bufi <= 'z') bufi -= 'a' - 'A'int deal(char *buf)int len = strlen(buf)

32、;int pos = 0;int pos0 = 0;int paras;paras = 0;atoA(buf);while (pos < len)while (bufpos = ' ') pos+;if (pos < len) paras+;while (pos < len && bufpos != ' ')bufpos0 = bufpos;pos0+;pos+;bufpos0 = 0;pos0+;pos+;return paras;int inside(int min, int max, int x)return (min &

33、lt;= x && x <= max);int change_time(int paras)char t10;int h, m, s;int tx6;int x, i;tx0 = 0; tx1 = 1; tx2 = 3; tx3 = 4; tx4 = 6; tx5 = 7;if (paras != 1) puts("-2: Parameter is wrong!");return -2;puts("Input time "hh:mm:ss": ");gets(t);x = 0;for (i = 0; i <

34、 6; +i)if (!inside('0', '9', ttxi) x = 1; if (x = 0 && strlen(t) = 8 && t2 = ':' && t5 = ':')t2 = 0; t5 = 0;h = strtoint(t + 0);m = strtoint(t + 3);s = strtoint(t + 6);if (inside(0, 23, h) && inside(0, 59, m) && inside(0, 59, s)

35、set_time(t);elsex = 1;if (x = 1)puts("-3: The time you inputed is wrong!");return -3;puts("0: Success!");return 0;int islegal(int y, int m, int d)if (m = 1 | m = 3 | m = 5 | m = 7 | m = 8 | m = 10 | m = 12) && (1 <= d && d <= 31) return 1;if (m = 4 | m = 6 |

36、 m = 9 | m = 11) && (1 <= d && d <= 30)return 1;if (m = 2 && ( (y % 4 = 0) && (y % 100 != 0) | (y % 400 = 0) && (1 <= d && d <= 29) ) | (1 <= d && d <= 28) return 1;return 0;int change_date(int paras)char t10;int y, m, d;int t

37、x6;int x, i;tx0 = 0; tx1 = 1; tx2 = 3; tx3 = 4; tx4 = 6; tx5 = 7;if (paras != 1) puts("-2: Parameter is wrong!");return -2;puts("Input date "YY-MM-DD": ");gets(t);x = 0;for (i = 0; i < 6; +i)if (!inside('0', '9', ttxi) x = 1; if (x = 0 && strl

38、en(t) = 8 && t2 = '-' && t5 = '-')t2 = 0; t5 = 0;y = strtoint(t + 0);m = strtoint(t + 3);d = strtoint(t + 6);if (islegal(y, m, d)set_date(t);elsex = 1;if (x = 1)puts("-3: The date you inputed is wrong!");return -3;puts("0: Success!");return 0;int r

39、un(int paras, char buf)int ord;/*buf整理后前3个字符为run,第4个为0,第五个开始为序号*/if (paras != 2 | !inside('1', '2', buf4)puts("-2: Parameter is wrong!");return -2;ord = strtoint(buf + 4);run_pro(ord - 1);return 0;int shutdown(int paras)if (paras != 1)puts("-2: Parameter is wrong!"

40、;);return -2;puts("Shutting down.");port_out16(0x1004, 0x2001);int reboot(int paras)if (paras != 1)puts("-2: Parameter is wrong!");return -2;port_out8(0x64, 0xfe);int jc(int paras, char *buf)int i;if (strcmp(buf, "TIME") = 0) return change_time(paras);if (strcmp(buf, &q

41、uot;DATE") = 0) return change_date(paras);if (strcmp(buf, "SHUTDOWN") = 0) return shutdown(paras);if (strcmp(buf, "REBOOT") = 0) return reboot(paras);if (strcmp(buf, "RUN") = 0) return run(paras, buf);puts("Command is wrong!");return -1;Oas.asmextern macr

42、o %1 extrn %1endmextern _cmain:nearextern _pre_time:nearextern _add_Table:near.8086_TEXT segment byte public 'CODE'assume cs:_TEXTDGROUP group _TEXT,_DATA,_BSS ;让所有的标号都有基于DGROUP的偏移org 7c00Hstart:mov ax,csmov ds,ax; DS = CSmov es,ax; ES = CSmov ss, ax; SS = csmov sp, 0h mov ax, csmov es, axmo

43、v bx, 7e00Hmov ah, 2mov al, 30mov dl, 0mov dh, 0mov ch, 0mov cl, 2int 13H;安装新的8号中断clipush esxor ax, axmov es, axmov ax, offset int_8mov word ptr es:20h, axmov ax, csmov es:22h, axpop essti;安装供运行中程序返回的iret指令到21H中clipush esxor ax, axmov es, axmov ax, offset int_21mov word ptr es:4 * 21h, axmov ax, csm

44、ov es:4 * 21h + 2, axpop essticall near ptr set_Timercall near ptr _cmainmov ax, 4c00Hint 21Hinclude clib.asminclude oslib.asmtest_x:push axpush bxpush esmov ax, 0b800hmov es, axmov bx, 160mov ax, es:bxinc axmov es:bx, axpop espop bxmov al, 20hout 20h, alout 0a0h, alpop axiret_TEXT ends_DATA segment

45、 word public 'DATA'_DATA ends_BSSsegment word public 'BSS'_BSS endsend startclib.asm; +; clib.asm; +; 以下的函数,有c语言函数标志的默认不对通用寄存器进行保护; 没有c语言函数标志的有实现对通用寄存器的保护;*; char *gets(char *str) *;*;读取到换行符时结束,get使用charstack结构来保存读取的字符;单次读取的字符有限,默认为charstack的topmax,加上最后的NULL为topmax+1public _gets_gets

46、 procpush bpmov bp, sp ;bp/ip/strpush simov ah, 4call near ptr charstackmov si, ss:bp + 4mov ah, 3;读取光标位置,供charstack显示字符串mov bh, 0int 10Hmov bx, 0007H_gets_1:mov ah, 0int 16hcmp al, 13je _gets_return;是否为回车符,yes>结束cmp al, 08je _gets_2;是否为Backspace;yes>删除字符2cmp al, 32jb _gets_1;是否为可视字符cmp al, 12

47、6ja _gets_1;是否为可视字符mov ah, 0call near ptr charstack;入栈处理jmp _gets_3;>显示字符串3_gets_2:;删除字符2mov ah, 1call near ptr charstack;出栈处理_gets_3:;显示字符串mov ah, 2call near ptr charstackjmp _gets_1;继续读取字符_gets_return:mov ah, 0mov al, 0call near ptr charstackmov ax, 10push axcall near ptr _putcharpop cxmov ax,

48、si;返回字符串地址pop sipop bpret_gets endp;函数名称:charstack;功能:存放最多topmax个字符;函数输入:ah=功能号,0表示入栈,1表示出栈,2表示显示,3返回栈当前大小;4表示清空栈;ds:si指向字符栈空间起始地址;上升型空栈;对于0号功能:al=入栈字符;对于1号功能:al=返回字符;对于2号功能:dh、dl分别表示行和列号,bh为页号,bl为属性;对于3号功能:ax返回top值;对于4号功能:清空栈top、len = 0; bug 由于int 10H 在窗口右下角,输出字符串长于有限位数时,; 会自动将显存中内容向上挪动一行,并且不会回退,跟d

49、os一样,; 所有不太好看,没了topmax equ 65charstack procjmp short charstack_startptabledw charstack_push, charstack_popdw charstack_show, charstack_sizedw charstack_cleartopdw 0lendw 0charstack_start:push bxpush cxpush dxpush bppush escmp ah, 4ja charstack_returnmov cl, ahmov ch, 0add cx, cxmov bp, cxjmp word pt

50、r cs:bp + ptablecharstack_push:cmp word ptr cs:top, topmaxjne charstack_push_1sub word ptr cs:top, 1charstack_push_1:mov bx, cs:topmov si + bx, aladd word ptr cs:top, 1jmp short charstack_returncharstack_pop:cmp word ptr cs:top, 0je charstack_returndec word ptr cs:topmov bx, cs:topmov al, si + bxjmp short charstack_returncharstack_show:push axmov cx, cs:lenmo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论