├── .gitattributes ├── .gitignore ├── Lab01 ├── README.md ├── disk │ └── lab1.flp ├── doc │ └── 实验说明.doc └── src │ └── Lab1.asm ├── Lab02 ├── README.md ├── disk │ └── Lab2.img ├── doc │ └── 实验说明.doc └── src │ ├── boot.asm │ ├── myos.asm │ ├── pro1.asm │ ├── pro2.asm │ └── pro3.asm ├── Lab03 ├── README.md ├── disk │ └── Lab03.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── function.asm │ ├── pro1.asm │ ├── pro2.asm │ └── pro3.asm ├── Lab04 ├── README.md ├── disk │ └── Lab04.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── function.asm │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ └── services.asm ├── Lab05 ├── README.md ├── disk │ └── Lab05.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── c_lib.asm │ ├── function.asm │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ └── services.asm ├── Lab06 ├── README.md ├── bat │ ├── run1.bat │ ├── run2.bat │ └── run3.bat ├── disk │ └── Lab06.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── c_lib.asm │ ├── function.asm │ ├── process.h │ ├── services.asm │ └── 用户程序 │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ ├── process1.asm │ ├── process2.asm │ ├── process3.asm │ └── process4.asm ├── Lab07 ├── README.md ├── disk │ └── Lab07.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── c_lib.asm │ ├── function.asm │ ├── process.h │ ├── services.asm │ └── 用户程序 │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ ├── process1.asm │ ├── process2.asm │ ├── process3.asm │ ├── process4.asm │ ├── user.asm │ ├── user.c │ ├── user_lib.asm │ └── user_lib.h ├── Lab08 ├── README.md ├── disk │ └── Lab08.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── boot.asm │ ├── c_lib.asm │ ├── file.asm │ ├── function.asm │ ├── process.h │ ├── sema.h │ ├── services.asm │ └── 用户程序 │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ ├── process1.asm │ ├── process2.asm │ ├── process3.asm │ ├── process4.asm │ ├── user.asm │ ├── user1.c │ ├── user2.c │ ├── user_lib.asm │ └── user_lib.h ├── Lab09 ├── README.md ├── disk │ └── Lab09.img ├── doc │ └── 实验说明.doc └── src │ ├── MyOs.asm │ ├── MyOs.c │ ├── bat 文件 │ ├── run1.bat │ ├── run2.bat │ └── run3.bat │ ├── boot.asm │ ├── c_lib.asm │ ├── file.asm │ ├── function.asm │ ├── process.h │ ├── services.asm │ └── 用户程序 │ ├── pro1.asm │ ├── pro2.asm │ ├── pro3.asm │ ├── process1.asm │ ├── process2.asm │ ├── process3.asm │ ├── process4.asm │ ├── user.asm │ ├── user.c │ ├── user_lib.asm │ └── user_lib.h ├── README.md └── tools ├── LINK.EXE ├── TASM.EXE ├── TCC.EXE ├── TLINK.EXE └── nasm.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /Lab01/README.md: -------------------------------------------------------------------------------- 1 | 设计一个引导扇区程序,程序功能是:用字符‘A’从屏幕左边某行位置45度角下斜射出,保持一个可观察的适当速度直线运动,碰到下边后反射,如此类推,不断运动 2 | -------------------------------------------------------------------------------- /Lab01/disk/lab1.flp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab01/disk/lab1.flp -------------------------------------------------------------------------------- /Lab01/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab01/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab01/src/Lab1.asm: -------------------------------------------------------------------------------- 1 | Init: ;程序初始化 2 | delayTime equ 5000 ;定义 delayTime 代表 50 3 | org 7c00h ;程序装载到 7c00h 4 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 5 | mov ds,ax 6 | mov es, ax 7 | 8 | main: ;可视为主函数 9 | mov ax,24 ;置 ax 为立即数 24 10 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 11 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 12 | mov ax,0 ;在 ax 中放 0 13 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 14 | je UptoDown ;上述条件成立则跳转至 UptoDown 15 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 16 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 17 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 18 | mov ax,0 ;在 ax 中置 0 19 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 20 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 21 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 22 | 23 | Usual: ;在没有触发边界时执行的代码块 24 | mov ax,0 ;ax 置零 25 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 26 | je Down ;相等时跳转到 Down ,向下运动 27 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 28 | 29 | DownToUp: ;触底反弹 30 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 31 | cmp byte[x],0 ;是否到达左下角 32 | je LeftToRight 33 | cmp byte[x],79 ;是否到达右下角 34 | je RightToLeft 35 | jmp Up ;无条件跳转至 Up 36 | 37 | UptoDown: ;触顶反弹 38 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 39 | cmp byte[x],0 ;是否到达左上角 40 | je LeftToRight 41 | cmp byte[x],79 ;是否到达右上角 42 | je RightToLeft 43 | jmp Down ;无条件跳转至 Down 44 | 45 | RightToLeft: ;在最右反弹 46 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 47 | mov ax,0 ;把 ax 置 0 48 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 49 | je Down ;是则跳转到 Down ,向下 50 | jmp Up ;否则跳转到 Up ,向上 51 | 52 | LeftToRight: ;在最左反弹 53 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 54 | mov ax,0 ;将 ax 置 0 55 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 56 | je Down ;是则跳转到 Down 57 | jmp Up ;否则跳转到 Up 58 | 59 | Up: ;向上运动 60 | dec word[y] ;y-- ,把纵坐标减 1,向上 61 | mov ax,0 ;ax 置 0 62 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 63 | je R ;是的话跳转到 R 64 | jmp L ;不是的话跳转到 L 65 | 66 | Down: ;向下运动 67 | inc word[y] ;y++,把纵坐标加 1 ,向下 68 | mov ax,0 ;置 ax 为 0 69 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 70 | je R ;是的话跳转到 R 71 | jmp L ;不是的话跳转到 L 72 | 73 | R: ;向右运动 74 | inc word[x] ; x++,横坐标加 1,向右 75 | jmp Show ;跳转至 Show 代码段 76 | 77 | L: ;向左运动 78 | dec word[x] ;x--,横坐标减 1,向左 79 | jmp Show ;跳转至 Show 代码段 80 | 81 | Show: ;显示字符 82 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 83 | mov es,ax ;把 ax 的值加载到 es,作为存放字符的基址 84 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 85 | mul word[y] ;计算 160*y ,结果放在 ax 中 86 | mov word[t],ax ;把 ax 的值放到 t 87 | mov ax,word[x] ;把 x 放到 ax 88 | add ax,ax ;ax *= 2 89 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 90 | mov bx,ax ;置 bx 等于 ax ,即为 t 91 | mov al,'A' ;在 al 中放字符 'A' 92 | mov ah,0ch ;在 ah 中放 0ch,表示黑底红字 93 | mov [es:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 94 | mov cx,delayTime ;初始化 cx 为 5000 95 | jmp delay ;跳转到 delay ,进行延迟 96 | 97 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 98 | mov word[t],cx ;把 cx 的值保存到 t 中 99 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 100 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 101 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 102 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 103 | jmp main ;无条件跳转至 main ,继续执行 104 | 105 | data: ;数据声明部分 106 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 107 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 108 | t dw 0 ;声明变量 t ,并初始化 t 为 0 109 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 110 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 111 | times 510-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 112 | db 55h,0aah ; 引导扇区的结束标志,也可以改为:dw 0aa55h 113 | -------------------------------------------------------------------------------- /Lab02/README.md: -------------------------------------------------------------------------------- 1 | 设计满足下列要求的原型操作系统: 2 | 1.用户程序大小不等,但最大不超过5个扇区。 3 | 2.允许用控制台命令指定一组要执行的用户程序。比如,磁盘上有3个用户程序,可以用命令指定按某顺序运行其中1个、2个或3个程序。 4 | 5 | -------------------------------------------------------------------------------- /Lab02/disk/Lab2.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab02/disk/Lab2.img -------------------------------------------------------------------------------- /Lab02/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab02/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab02/src/boot.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为引导程序的源码文件。 3 | ; 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00h处,并开始执行 5 | START: 6 | mov ax,cs ; 用 cs 的值初始化 ds,es 7 | mov ds,ax 8 | mov es,ax 9 | 10 | call ReadOS ; 装载操作系统 11 | call dword 9000h; ; 跳转到操作系统的执行 12 | 13 | ReadOS: ; 读入软盘第2和第3个扇区到7E00H处 14 | xor ax,ax ; 相当于mov ax,0 15 | mov es,ax ; ES=0 16 | mov bx,9000H ; ES:BX=读入数据到内存中的存储地址 17 | mov ah,2 ; 功能号 18 | mov al,2 ; 要读入的扇区数 19 | mov dl,0 ; 软盘驱动器号(对硬盘和U盘,此处的值应改为80H) 20 | mov dh,0 ; 磁头号 21 | mov ch,0 ; 柱面号 22 | mov cl,2 ; 起始扇区号(编号从1开始) 23 | int 13H ; 调用13H号中断 24 | ret ; 从例程返回 25 | 26 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 27 | db 55h, 0aah ; 引导扇区结束标志 28 | -------------------------------------------------------------------------------- /Lab02/src/myos.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为引导后启动的操作系统的源码文件。 3 | ; 4 | org 9000h ; 告诉编译器程序加载到7C00H处 5 | mov ax,cs ; 初始化数据段与附加段寄存器与代码段的相同 6 | mov ds,ax 7 | mov es,ax 8 | 9 | call Main ; 读取主函数 10 | 11 | Main: ; 可视为主函数 12 | call Clear ; 清屏 13 | call ReInit ; 将变量重新初始化 14 | call DispStr ; 调用显示字符串 15 | jmp Keyin ; 等待用户进行输入选择 16 | 17 | DispStr: ; 显示字符串 18 | ; 显示字符串1 "Chen-OS 1.0"(开始) 19 | mov ah,13h ; 功能号 20 | mov al,1 ; 光标放到串尾 21 | mov bl,0ah ; 亮绿 22 | mov bh,0 ; 第0页 23 | mov dh,05h ; 第5行 24 | mov dl,20h ; 第32列 25 | mov bp,str1 ; BP=串地址 26 | mov cx,Length1 ; 串长为 Length1 27 | int 10h ; 调用10H号中断 28 | ; 显示字符串1(结束) 29 | ; 显示字符串2 "(C) 2014 liaojch3"(开始) 30 | mov ah,13h ; 功能号 31 | mov al,1 ; 光标放到串尾 32 | mov bl,0dh ; 黑底品红字 33 | mov bh,0 ; 第0页 34 | mov dh,07h ; 第7行 35 | mov dl,1eh ; 第 30 列 36 | mov bp,str2 ; BP=串地址 37 | mov cx,Length2 ; 串长为 Length2 38 | int 10h ; 调用10H号中断 39 | ; 显示字符串2(结束) 40 | ; 显示字符串3 41 | mov ah,13h ; 功能号 42 | mov al,1 ; 光标放到串尾 43 | mov bl,0ch ; 黑底红字 44 | mov bh,0 ; 第0页 45 | mov dh,0ah ; 第10行 46 | mov dl,0 ; 第 0 列 47 | mov bp,str3 ; BP=串地址 48 | mov cx,Length3 ; 串长为 Length3 49 | int 10h ; 调用10H号中断 50 | ; 显示字符串3(结束) 51 | ret ; 返回调用处 52 | 53 | 54 | ReadPro: ; 读入程序(软盘第4 或 第5 或 第6个扇区)到内存7E00H处) 55 | xor ax,ax ; 相当于mov ax,0 56 | mov es,ax ; ES=0 57 | mov bx,7e00H ; ES:BX=读入数据到内存中的存储地址 58 | mov ah,2 ; 功能号 59 | mov al,1 ; 要读入的扇区数 1 60 | mov dl,0 ; 软盘驱动器号(对硬盘和U盘,此处的值应改为80H) 61 | mov dh,0 ; 磁头号 62 | mov ch,0 ; 柱面号 63 | mov cl,byte[p] ; 起始扇区号(编号从1开始) 64 | int 13H ; 调用13H号中断 65 | ret ; 返回 66 | 67 | 68 | Keyin: 69 | mov ah,0 ; 功能号 70 | int 16h ; 调用16H号中断 71 | cmp al,0dh ; 判断是否是回车,回车的 Ascii 码为 0dh(13) 72 | je Excute ; 开始执行用户选择的程序顺序 73 | jmp showch ; 没有回车,则显示用户键入的字符 74 | 75 | showch: ; 显示键入字符 76 | mov ah,0eh ; 功能号 77 | mov bl,0 ; 对文本方式置0 78 | int 10h ; 调用10H号中断 79 | jmp Continue 80 | 81 | Continue: ; 继续执行 82 | inc word[i] ; i++ 83 | mov ah,0 ; ah 置零 84 | cmp word[i],4 ; 判断用户是否键入超过 3 个字符 85 | je Main ; 超过 3 个则进行刷新显示 86 | cmp word[i],2 ; 是否是输入的第二个字符(i = 2) 87 | je I2 ; 跳转到 I2,存储第二个字符到 y 88 | cmp word[i],3 ; 是否是输入的第三个字符 89 | je I3 ; 跳转到 I3,存储第三个字符到 z 90 | mov word[x],ax ; 以上不成立,则是第一个字符,存入 x 91 | jmp Keyin ; 跳转到准备接受下一个输入处 92 | I2: mov word[y],ax ; 存储第二个字符到 y 93 | jmp Keyin ; 跳转到准备接受下一个输入处 94 | I3: mov word[z],ax ; 存储第三个字符到 z 95 | jmp Keyin ; 跳转到准备接受下一个输入处 96 | 97 | Excute: ; 开始执行用户选择的程序 98 | mov ax,0 ; ax 置零 99 | CMP1: ;判断用户选择的第一个程序是否执行 100 | cmp word[x],ax ; 判断 x 是否为 0,0 代表执行过 101 | je CMP2 ; x 为 0 则开始判断 y 102 | jmp Ex1 ; x 不为 0 开始执行用户选择的第一个程序 103 | Ex1: ;执行用户选择的第一个程序 104 | mov ax,word[x] ; 把 x 放到 ax 105 | mov word[cur],ax; 把 ax 放到 cur 变量 106 | mov ax,0 ; ax 置零 107 | mov word[x],ax ; ax 放到 x, 将 x 清零 108 | call Run ; 开始执行 109 | jmp Excute ; 执行完继续跳转到 Excute 110 | CMP2: ;判断用户选择的第二个程序是否执行 111 | cmp word[y],ax ; 判断 y 是否为 0,0 代表执行过 112 | je CMP3 ; y 为 0 开始判断 z 113 | jmp Ex2 ; y 不为 0 开始执行用户选择的第二个程序 114 | Ex2: ;执行用户选择的第二个程序 115 | mov ax,word[y] ; 把 y 放到 ax 116 | mov word[cur],ax; ax 放到 cur 117 | mov ax,0 ; ax 置零 118 | mov word[y],ax ; ax 放到 y ,将 y 置零 119 | call Run ; 开始调用 120 | jmp Excute ; 执行完继续跳转到 Excute 121 | CMP3: ;判断用户选择的第三个程序是否执行 122 | cmp word[z],ax ; z 是否为 0 123 | je END ; 若 z 也为 0,则没有程序等待执行,结束本次调用 124 | jmp Ex3 ; 执行用户选择的第三个程序 125 | Ex3: ;执行用户选择的第三个程序 126 | mov ax,word[z] ; z 放到 ax 127 | mov word[cur],ax; ax 放到 cur 128 | mov ax,0 ; ax 置零 129 | mov word[z],ax ; z 置零,标记为执行过 130 | call Run ; 开始执行 131 | jmp Excute ; 执行完继续跳转到 Excute 132 | END: ;本次用户选择的程序已调用完 133 | call Clear ; 清屏 134 | jmp Main ; 回到主函数,相当于把控制权交给操作系统 135 | 136 | Run: ; 执行当前用户程序 137 | mov bx,48 ; bx 置为 48 138 | mov ax,word[cur]; 把 cur 装载到 ax 139 | sub ax,bx ; 让 ax = ax-bx 140 | add ax,3 ; ax += 3 找到对应扇区号 141 | mov byte[p],al ; 把扇区号放到 p 142 | call ReadPro ; 装载程序到 7e00h 143 | call dword 7e00h; 调用程序 144 | ret 145 | 146 | Clear: ; 清屏 147 | mov ax,0003H ; 设置清屏属性 148 | int 10H ; 功能号 149 | ret ; 返回 150 | 151 | ReInit: ;对变量进行重新初始化 152 | mov ax,0 ; ax 置零 153 | mov word[x],ax ; x 置零 154 | mov word[y],ax ; y 置零 155 | mov word[z],ax ; z 置零 156 | mov word[i],ax ; i 置零 157 | mov word[cur],ax; cur 置零 158 | ret ; 返回 159 | 160 | Data: ; 数据定义 161 | x dw 0 ; 声明 x ,x 代表用户输入第一个字符 162 | y dw 0 ; 声明 y , y 代表用户输入的第二个字符 163 | z dw 0 ; 声明 z , z 代表用户输入的第三个字符 164 | i dw 0 ; 声明 i , i 为用户已经输入的字符数 165 | cur dw 0 ; 声明 cur ,cur 为当前应该调用的程序 166 | p db 0 167 | 168 | str1: ; 字符串1 169 | db "Chen-OS 1.0" 170 | Length1: equ ($-str1) ; 字符串 1 的长度 171 | str2: ; 字符串2 172 | db "(C) 2014 liaojch3" 173 | Length2: equ ($-str2) ; 字符串 2 的长度 174 | str3: ; 字符串3 175 | db " We have total 3 program: Program 1 program 2 Program 3" 176 | db 0ah,0dh ; 换行 177 | db 0ah,0dh 178 | db " Please choose one, two or three program with the order you want" 179 | db 0ah,0dh 180 | db " Then press the Enter" 181 | db 0ah,0dh 182 | db 0ah,0dh 183 | db " Notice that input with no space,like key in 12 or 231." 184 | db 0ah,0dh 185 | db " Then the os will excute it." 186 | db 0ah,0dh 187 | db 0ah,0dh 188 | db " Please Key in here:" 189 | Length3: equ ($-str3) ; 字符串 3 的长度 190 | times 1024-($-$$) db 0 ; 用0填充剩余部分 191 | ; ($=当前地址、$$=当前节地址) 192 | ;db 55h,0aah ; 启动扇区的结束标志 193 | 194 | -------------------------------------------------------------------------------- /Lab02/src/pro1.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | call Keyin ; 接受用户任意输入 12 | retf ; 段间返回 13 | 14 | DispStr: ; 显示字符串 15 | ; 显示字符串 "Hello, Here is Program 1 ~"(开始) 16 | mov ah,13h ; 功能号 17 | mov al,1 ; 光标放到串尾 18 | mov bl,0ch ; 黑底红字 19 | mov bh,0 ; 第0页 20 | mov dh,05h ; 第5行 21 | mov dl,1ch ; 第28列 22 | mov bp,BootMsg ; BP=串地址 23 | mov cx,Length1 ; 串长为length1 24 | int 10h ; 调用10H号中断 25 | ; 显示字符串(结束) 26 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 27 | mov ah,13h ; 功能号 28 | mov al,1 ; 光标放到串尾 29 | mov bl,0dh ; 黑底品红字 30 | mov bh,0 ; 第0页 31 | mov dh,07h ; 第7行 32 | mov dl,1ch ; 第28列 33 | mov bp,Tips ; BP=串地址 34 | mov cx,Length2 ; 串长 35 | int 10h ; 调用10H号中断 36 | ; 显示字符串2(结束) 37 | ret 38 | 39 | Keyin: ; 读按键 40 | mov ah,0 ; 功能号 41 | int 16h ; 调用16H号中断 42 | ret ; 退出 43 | 44 | Clear: ;清屏 45 | mov ax,0003H ; 清屏属性 46 | int 10H ; 调用中断 47 | ret ; 返回 48 | 49 | BootMsg: ; 引导字符串 50 | db "Hello. Here is Program 1 ~ " 51 | Length1: equ ($-BootMsg) ; 欢迎字符串的长度 52 | Tips: ; 退出提示 53 | db "Press Key to quit..." 54 | Length2: equ ($-Tips) ; 提示的长度 55 | 56 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 57 | ;db 55h,0aah ; 启动扇区的结束标志 58 | -------------------------------------------------------------------------------- /Lab02/src/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序2的源码文件 3 | ; 4 | org 7e00h ; 加载到 8000h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | call Keyin ; 等待用户输入任意键 12 | retf ; 无限循环 13 | 14 | DispStr: ; 显示字符串 15 | ; 显示字符串 "Haha. This is Program 2 ~"(开始) 16 | mov ah,13h ; 功能号 17 | mov al,1 ; 光标放到串尾 18 | mov bl,0ch ; 黑底红字 19 | mov bh,0 ; 第0页 20 | mov dh,05h ; 第5行 21 | mov dl,1ch ; 第28列 22 | mov bp,BootMsg ; BP=串地址 23 | mov cx,Length1 ; 串长为 Length1 24 | int 10h ; 调用10H号中断 25 | ; 显示字符串(结束) 26 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 27 | mov ah,13h ; 功能号 28 | mov al,1 ; 光标放到串尾 29 | mov bl,0dh ; 黑底品红字 30 | mov bh,0 ; 第0页 31 | mov dh,07h ; 第7行 32 | mov dl,1ch ; 第28列 33 | mov bp,Tips ; BP=串地址 34 | mov cx,Length2 ; 串长 35 | int 10h ; 调用10H号中断 36 | ; 显示字符串2(结束) 37 | ret 38 | 39 | Keyin: ; 读按键 40 | mov ah,0 ; 功能号 41 | int 16h ; 调用16H号中断 42 | ret ; 退出 43 | 44 | Clear: ;清屏 45 | MOV AX,0003H 46 | INT 10H 47 | ret 48 | 49 | BootMsg: ; 引导字符串 50 | db "Haha. This is Program 2 ~ " 51 | Length1: equ ($-BootMsg) 52 | Tips: ; 退出提示 53 | db "Press key to quit..." 54 | Length2: equ ($-Tips) 55 | 56 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 57 | ;db 55h,0aah ; 启动扇区的结束标志 58 | 59 | -------------------------------------------------------------------------------- /Lab02/src/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序3的源码文件 3 | ; 4 | org 7e00h ; 加载到8200h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | call Keyin ; 读取用户输入的任意键 12 | retf ; 退出 13 | 14 | DispStr: ; 显示字符串 15 | ; 显示字符串 "Hi, I'm Program 3 ~ "(开始) 16 | mov ah,13h ; 功能号 17 | mov al,1 ; 光标放到串尾 18 | mov bl,0ch ; 黑底红字 19 | mov bh,0 ; 第0页 20 | mov dh,05h ; 第5行 21 | mov dl,1ch ; 第28列 22 | mov bp,BootMsg ; BP=串地址 23 | mov cx,Length1 ; 串长 Length1 24 | int 10h ; 调用10H号中断 25 | ; 显示字符串(结束) 26 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 27 | mov ah,13h ; 功能号 28 | mov al,1 ; 光标放到串尾 29 | mov bl,0dh ; 黑底品红字 30 | mov bh,0 ; 第0页 31 | mov dh,07h ; 第 7 行 32 | mov dl,1ch ; 第 28 列 33 | mov bp,Tips ; BP=串地址 34 | mov cx,Length2 ; 串长 35 | int 10h ; 调用10H号中断 36 | ; 显示字符串2(结束) 37 | ret 38 | 39 | Keyin: ; 读按键 40 | mov ah,0 ; 功能号 41 | int 16h ; 调用16H号中断 42 | ret ; 退出 43 | 44 | Clear: ;清屏 45 | MOV AX,0003H 46 | INT 10H 47 | ret 48 | 49 | BootMsg: ; 引导字符串 50 | db "Hi, I'm Program 3 ~ " 51 | Length1: equ ($-BootMsg) 52 | Tips: ; 退出提示 53 | db "Press Key to quit..." 54 | Length2: equ ($-Tips) 55 | 56 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 57 | ;db 55h,0aah ; 启动扇区的结束标志 58 | 59 | -------------------------------------------------------------------------------- /Lab03/README.md: -------------------------------------------------------------------------------- 1 | 设计满足下列要求的原型操作系统: 2 | 3 | (1)用引导程序加载的MYOS内核 4 | 5 | (2)内核由汇编语言kernal.asm和c语言kernal.c二个模块生成; 6 | 7 | (3)实现作业控制语言mJCB,原型操作系统在当前行显示一个指示符(可以是简单的一个字符或你的学号之类),允许用户输入一行命令(回车结束,语法由你设计),操作系统解释命令并完成相应的功能(3个以上的内置功能,如time、date、asc等,而且能执行软盘上的某个用户程序)。 8 | 9 | -------------------------------------------------------------------------------- /Lab03/disk/Lab03.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab03/disk/Lab03.img -------------------------------------------------------------------------------- /Lab03/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab03/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab03/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | extrn _cmain:near ; 声明一个c程序函数cmain() 5 | extrn _in:near ; C 中的变量,用于存储读入的字符 6 | extrn _ch1:near ; C 中变量,存放临时字符 7 | extrn _ch2:near ; C 中变量,存放临时字符 8 | extrn _ch3:near ; C 中变量,存放临时字符 9 | extrn _ch4:near ; C 中变量,存放临时字符 10 | extrn _p:near ; C 中变量,代表 应该读入的扇区号 11 | 12 | .8086 13 | _TEXT segment byte public 'CODE' 14 | assume cs:_TEXT 15 | DGROUP group _TEXT,_DATA,_BSS 16 | org 100h 17 | start: 18 | mov ax, cs 19 | mov ds, ax ; DS = CS 20 | mov es, ax ; ES = CS 21 | mov ss, ax ; SS = cs 22 | mov sp, 64*1024-4 ; SP指向本段高端-4 23 | call near ptr _cmain ; 调用C语言程序cmain() 24 | jmp $ 25 | 26 | include function.asm ; 包含内核库过程 function.asm 27 | 28 | _TEXT ends 29 | _DATA segment word public 'DATA' 30 | _DATA ends 31 | _BSS segment word public 'BSS' 32 | _BSS ends 33 | end start 34 | 35 | -------------------------------------------------------------------------------- /Lab03/src/boot.asm: -------------------------------------------------------------------------------- 1 | ;程序源代码(boot.asm) 2 | ;用NASM汇编此程序 3 | ;nasm –f bin boot.asm –o boot.bin 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00处,并开始执行 5 | Start: 6 | mov ax, cs ; 置其他段寄存器值与CS相同 7 | mov ds, ax ; 数据段 8 | mov bp, Message ; BP=当前串的偏移地址 9 | mov ax, ds ; ES:BP = 串地址 10 | mov es, ax ; 置ES=DS 11 | mov cx, MessageLength ; CX = 串长(=9) 12 | mov ax, 1301h ; AH = 13h(功能号)、AL = 01h(光标置于串尾) 13 | mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) 14 | mov dh, 0 ; 行号=0 15 | mov dl, 0 ; 列号=0 16 | int 10h ; BIOS的10h功能:显示一行字符 17 | LoadKernal: 18 | ;读软盘或硬盘上的kernal到内存的ES:BX处: 19 | mov ax, SegOfKernal ; 段地址 ; 存放数据的内存基地址 20 | mov es,ax ; 设置段地址(不能直接mov es,段地址) 21 | mov bx, OffSetOfKernal ; 偏移地址; 存放数据的内存偏移地址 22 | mov ah,2 ; 功能号 23 | mov al, QTYofBlockOfKernal ; 扇区数 24 | mov dl,0 ; 驱动器号 ; 软盘为0,硬盘和U盘为80H 25 | mov dh,0 ; 磁头号 ; 起始编号为0 26 | mov ch,0 ; 柱面号 ; 起始编号为0 27 | mov cl,2 ; 起始扇区号 ; 起始编号为1 28 | int 13H ; 调用中断 29 | ;内核已加载到指定内存区域中 30 | jmp SegOfKernal : OffSetOfKernal 31 | jmp $ ;无限循环 32 | 33 | Message: 34 | db 'Loading MyOs kernal...' 35 | MessageLength equ ($-Message) ; 字符串长度 36 | OffSetOfKernal equ 100h ; 偏移量 37 | SegOfKernal equ 64*1024/16 ; 第二个64k内存的段地址 38 | QTYofBlockOfKernal equ 9 ; 内核占用扇区数 39 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 40 | db 55h, 0aah ; 引导扇区结束标志 41 | 42 | -------------------------------------------------------------------------------- /Lab03/src/function.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 内核库过程版本信息 * 3 | ;************************************************** 4 | 5 | ;************ ***************************** 6 | ; *SCOPY@ * 7 | ;****************** *********************** 8 | ; 实参为局部字符串带初始化异常问题的补钉程序 9 | public SCOPY@ 10 | SCOPY@ proc 11 | arg_0 = dword ptr 6 12 | arg_4 = dword ptr 0ah 13 | push bp 14 | mov bp,sp 15 | push si 16 | push di 17 | push ds 18 | lds si,[bp+arg_0] 19 | les di,[bp+arg_4] 20 | cld 21 | shr cx,1 22 | rep movsw 23 | adc cx,cx 24 | rep movsb 25 | pop ds 26 | pop di 27 | pop si 28 | pop bp 29 | retf 8 30 | SCOPY@ endp 31 | 32 | ;*************** ******************** 33 | ;* void _cls() * 34 | ;**************** ******************* 35 | ; 清屏 36 | public _cls 37 | _cls proc 38 | ; 清屏 39 | mov ax,0003H 40 | int 10h ; 显示中断 41 | ret 42 | _cls endp 43 | 44 | ;**** *********************************** 45 | ;* void _PrintChar() * 46 | ;******* ******************************** 47 | ; 字符输出 48 | public _printChar 49 | _printChar proc 50 | push bp 51 | mov bp,sp 52 | ;*** 53 | mov al,[bp+4] 54 | mov bl,0 55 | mov ah,0eh 56 | int 10h 57 | ;*** 58 | mov sp,bp 59 | pop bp 60 | ret 61 | _printChar endp 62 | 63 | ;*********** **************************** 64 | ;* void _GetChar() * 65 | ;****************** ********************* 66 | ; 读入一个字符 67 | public _getChar 68 | _getChar proc 69 | mov ah,0 70 | int 16h 71 | mov byte ptr[_in],al 72 | ret 73 | _getChar endp 74 | 75 | ;*************** ******************** 76 | ;* void _getdate() * 77 | ;**************** ******************* 78 | ; 获取日期 79 | public _getdate 80 | _getdate proc 81 | push ax 82 | push bx 83 | push cx 84 | push dx 85 | 86 | mov ah,4h 87 | int 1ah 88 | 89 | mov byte ptr[_ch1],ch ; 将年高位放到 ch1 90 | mov byte ptr[_ch2],cl ; 将年低位放到 ch2 91 | mov byte ptr[_ch3],dh ; 将月放到 ch3 92 | mov byte ptr[_ch4],dl ; 将日放到 ch4 93 | 94 | pop dx 95 | pop cx 96 | pop bx 97 | pop ax 98 | ret 99 | _getdate endp 100 | 101 | ;*************** ******************** 102 | ;* void _gettime() * 103 | ;**************** ******************* 104 | ; 获取时间 105 | public _gettime 106 | _gettime proc 107 | push ax 108 | push bx 109 | push cx 110 | push dx 111 | 112 | mov ah,2h 113 | int 1ah 114 | 115 | mov byte ptr[_ch1],ch ; 将时放到 ch1 116 | mov byte ptr[_ch2],cl ; 将分放到 ch2 117 | mov byte ptr[_ch3],dh ; 将秒放到 ch3 118 | 119 | pop dx 120 | pop cx 121 | pop bx 122 | pop ax 123 | ret 124 | _gettime endp 125 | 126 | ;*************** ******************** 127 | ;* void _run() * 128 | ;**************** ******************* 129 | ; 加载并运行程序 130 | public _run 131 | _run proc 132 | push ax 133 | push bx 134 | push cx 135 | push dx 136 | push es 137 | 138 | mov ax,1000h 139 | mov es,ax ; ES=0 140 | mov bx,1400h ; ES:BX=读入数据到内存中的存储地址 141 | mov ah,2 ; 功能号 142 | mov al,1 ; 要读入的扇区数 1 143 | mov dl,0 ; 软盘驱动器号(对硬盘和U盘,此处的值应改为80H) 144 | mov dh,0 ; 磁头号 145 | mov ch,0 ; 柱面号 146 | mov cl,byte ptr[_p] ; 起始扇区号(编号从1开始) 147 | int 13H ; 调用13H号中断 148 | 149 | mov bx,1400h ; 将偏移量放到 bx 150 | call 1000h:bx ; 跳转到该内存地址 151 | 152 | pop es 153 | pop dx 154 | pop cx 155 | pop bx 156 | pop ax 157 | ret 158 | _run endp 159 | 160 | -------------------------------------------------------------------------------- /Lab03/src/pro1.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 1400h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | call Keyin ; 接受用户任意输入 12 | ret ; 段间返回 13 | 14 | DispStr: ; 显示字符串 15 | ; 显示字符串 "Hello, Here is Program 1 ~"(开始) 16 | mov ah,13h ; 功能号 17 | mov al,1 ; 光标放到串尾 18 | mov bl,0ch ; 黑底红字 19 | mov bh,0 ; 第0页 20 | mov dh,05h ; 第5行 21 | mov dl,1ch ; 第28列 22 | mov bp,BootMsg ; BP=串地址 23 | mov cx,Length1 ; 串长为length1 24 | int 10h ; 调用10H号中断 25 | ; 显示字符串(结束) 26 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 27 | mov ah,13h ; 功能号 28 | mov al,1 ; 光标放到串尾 29 | mov bl,0dh ; 黑底品红字 30 | mov bh,0 ; 第0页 31 | mov dh,07h ; 第7行 32 | mov dl,1ch ; 第28列 33 | mov bp,Tips ; BP=串地址 34 | mov cx,Length2 ; 串长 35 | int 10h ; 调用10H号中断 36 | ; 显示字符串2(结束) 37 | ret 38 | 39 | Keyin: ; 读按键 40 | mov ah,0 ; 功能号 41 | int 16h ; 调用16H号中断 42 | ret ; 退出 43 | 44 | Clear: ;清屏 45 | mov ax,0003H ; 清屏属性 46 | int 10H ; 调用中断 47 | ret ; 返回 48 | 49 | BootMsg: ; 引导字符串 50 | db "Hello. Here is Program 1 ~ " 51 | Length1: equ ($-BootMsg) ; 欢迎字符串的长度 52 | Tips: ; 退出提示 53 | db "Press Key to quit..." 54 | Length2: equ ($-Tips) ; 提示的长度 55 | 56 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 57 | ;db 55h,0aah ; 启动扇区的结束标志 58 | -------------------------------------------------------------------------------- /Lab03/src/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序2的源码文件 3 | ; 4 | org 1400h ; 加载到 8000h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | call Keyin ; 等待用户输入任意键 12 | ret ; 无限循环 13 | 14 | DispStr: ; 显示字符串 15 | ; 显示字符串 "Haha. This is Program 2 ~"(开始) 16 | mov ah,13h ; 功能号 17 | mov al,1 ; 光标放到串尾 18 | mov bl,0ch ; 黑底红字 19 | mov bh,0 ; 第0页 20 | mov dh,05h ; 第5行 21 | mov dl,1ch ; 第28列 22 | mov bp,BootMsg ; BP=串地址 23 | mov cx,Length1 ; 串长为 Length1 24 | int 10h ; 调用10H号中断 25 | ; 显示字符串(结束) 26 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 27 | mov ah,13h ; 功能号 28 | mov al,1 ; 光标放到串尾 29 | mov bl,0dh ; 黑底品红字 30 | mov bh,0 ; 第0页 31 | mov dh,07h ; 第7行 32 | mov dl,1ch ; 第28列 33 | mov bp,Tips ; BP=串地址 34 | mov cx,Length2 ; 串长 35 | int 10h ; 调用10H号中断 36 | ; 显示字符串2(结束) 37 | ret 38 | 39 | Keyin: ; 读按键 40 | mov ah,0 ; 功能号 41 | int 16h ; 调用16H号中断 42 | ret ; 退出 43 | 44 | Clear: ;清屏 45 | MOV AX,0003H 46 | INT 10H 47 | ret 48 | 49 | BootMsg: ; 引导字符串 50 | db "Haha. This is Program 2 ~ " 51 | Length1: equ ($-BootMsg) 52 | Tips: ; 退出提示 53 | db "Press key to quit..." 54 | Length2: equ ($-Tips) 55 | 56 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 57 | ;db 55h,0aah ; 启动扇区的结束标志 58 | 59 | -------------------------------------------------------------------------------- /Lab03/src/pro3.asm: -------------------------------------------------------------------------------- 1 | ;演示程序 3 2 | Init: ;程序初始化 3 | delayTime equ 4000 ;定义 delayTime 代表 50 4 | org 1400h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,150 88 | je quit 89 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 90 | mov es,ax ;把 ax 的值加载到 es,作为存放字符的基址 91 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 92 | mul word[y] ;计算 160*y ,结果放在 ax 中 93 | mov word[t],ax ;把 ax 的值放到 t 94 | mov ax,word[x] ;把 x 放到 ax 95 | add ax,ax ;ax *= 2 96 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 97 | mov bx,ax ;置 bx 等于 ax ,即为 t 98 | mov al,'A' ;在 al 中放字符 'A' 99 | mov ah,0ch ;在 ah 中放 0ch,表示黑底红字 100 | mov [es:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 101 | mov cx,delayTime ;初始化 cx 为 5000 102 | jmp delay ;跳转到 delay ,进行延迟 103 | 104 | 105 | Clear: ;清屏 106 | MOV AX,0003H 107 | INT 10H 108 | ret 109 | 110 | quit: 111 | ret 112 | 113 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 114 | mov word[t],cx ;把 cx 的值保存到 t 中 115 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 116 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 117 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 118 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 119 | jmp main ;无条件跳转至 main ,继续执行 120 | 121 | data: ;数据声明部分 122 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 123 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 124 | t dw 0 ;声明变量 t ,并初始化 t 为 0 125 | num dw 0 126 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 127 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 128 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 129 | -------------------------------------------------------------------------------- /Lab04/README.md: -------------------------------------------------------------------------------- 1 | 设计满足下列要求的原型操作系统: 2 | (1)操作系统工作期间,在屏幕24行79列位置轮流显示’|’、’/’和’\’,适当控制显示速度,以方便观察效果。 3 | 4 | (2)用户程序运行时,键盘事件有事反应:当键盘有按键时,屏幕适当位置显示”OUCH! OUCH!”。 5 | 6 | (3)在内核中,对33号、34号、35号和36号中断编写中断服务程序,程序服务是分别在屏幕1/4区域内显示一些个性化信息。再编写一个汇编语言的程序,利用int 33、int 34、int 35和int 36产生中断调用你这4个服务程序。 7 | 8 | -------------------------------------------------------------------------------- /Lab04/disk/Lab04.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab04/disk/Lab04.img -------------------------------------------------------------------------------- /Lab04/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab04/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab04/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | extrn _cmain:near ; 声明一个c程序函数cmain() 5 | extrn _in:near ; C 中的变量,用于存储读入的字符 6 | extrn _ch1:near ; C 中变量,存放临时字符 7 | extrn _ch2:near ; C 中变量,存放临时字符 8 | extrn _ch3:near ; C 中变量,存放临时字符 9 | extrn _ch4:near ; C 中变量,存放临时字符 10 | extrn _p:near ; C 中变量,代表 应该读入的扇区号 11 | 12 | .8086 13 | _TEXT segment byte public 'CODE' 14 | assume cs:_TEXT 15 | DGROUP group _TEXT,_DATA,_BSS 16 | org 100h 17 | start: 18 | xor ax,ax ; AX = 0 19 | mov es,ax ; ES = 0 20 | mov ax,offset Timer 21 | mov word ptr es:[20h],offset Timer ; 设置时钟中断向量的偏移地址 22 | mov ax,cs 23 | mov word ptr es:[22h],cs ; 设置时钟中断向量的段地址=CS 24 | 25 | ;设置 33h 的中断 26 | xor ax,ax 27 | mov es,ax 28 | mov word ptr es:[51*4],offset BIOSService_1 ; 设置 33h 的偏移地址 29 | mov ax,cs 30 | mov word ptr es:[51*4+2],ax 31 | 32 | ;设置 34h 的中断 33 | xor ax,ax 34 | mov es,ax 35 | mov word ptr es:[52*4],offset BIOSService_2 ; 设置 34h 的偏移地址 36 | mov ax,cs 37 | mov word ptr es:[52*4+2],ax 38 | 39 | ;设置 35h 的中断 40 | xor ax,ax 41 | mov es,ax 42 | mov word ptr es:[53*4],offset BIOSService_3 ; 设置 35h 的偏移地址 43 | mov ax,cs 44 | mov word ptr es:[53*4+2],ax 45 | 46 | ;设置 36h 的中断 47 | xor ax,ax 48 | mov es,ax 49 | mov word ptr es:[54*4],offset BIOSService_4 ; 设置 36h 的偏移地址 50 | mov ax,cs 51 | mov word ptr es:[54*4+2],ax 52 | 53 | mov ax, cs 54 | mov ds, ax ; DS = CS 55 | mov es, ax ; ES = CS 56 | mov ss, ax ; SS = cs 57 | mov sp, 64*1024-4 ; SP指向本段高端-4 58 | call near ptr _cmain ; 调用C语言程序cmain() 59 | jmp $ 60 | 61 | include function.asm ; 包含内核库过程 function.asm 62 | include services.asm ; 包含系统服务程序 63 | 64 | _TEXT ends 65 | _DATA segment word public 'DATA' 66 | _DATA ends 67 | _BSS segment word public 'BSS' 68 | _BSS ends 69 | end start 70 | 71 | -------------------------------------------------------------------------------- /Lab04/src/boot.asm: -------------------------------------------------------------------------------- 1 | ;程序源代码(boot.asm) 2 | ;用NASM汇编此程序 3 | ;nasm –f bin boot.asm –o boot.bin 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00处,并开始执行 5 | Start: 6 | mov ax, cs ; 置其他段寄存器值与CS相同 7 | mov ds, ax ; 数据段 8 | mov bp, Message ; BP=当前串的偏移地址 9 | mov ax, ds ; ES:BP = 串地址 10 | mov es, ax ; 置ES=DS 11 | mov cx, MessageLength ; CX = 串长(=9) 12 | mov ax, 1301h ; AH = 13h(功能号)、AL = 01h(光标置于串尾) 13 | mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) 14 | mov dh, 0 ; 行号=0 15 | mov dl, 0 ; 列号=0 16 | int 10h ; BIOS的10h功能:显示一行字符 17 | LoadKernal: 18 | ;读软盘或硬盘上的kernal到内存的ES:BX处: 19 | mov ax, SegOfKernal ; 段地址 ; 存放数据的内存基地址 20 | mov es,ax ; 设置段地址(不能直接mov es,段地址) 21 | mov bx, OffSetOfKernal ; 偏移地址; 存放数据的内存偏移地址 22 | mov ah,2 ; 功能号 23 | mov al, QTYofBlockOfKernal ; 扇区数 24 | mov dl,0 ; 驱动器号 ; 软盘为0,硬盘和U盘为80H 25 | mov dh,0 ; 磁头号 ; 起始编号为0 26 | mov ch,0 ; 柱面号 ; 起始编号为0 27 | mov cl,2 ; 起始扇区号 ; 起始编号为1 28 | int 13H ; 调用中断 29 | ;内核已加载到指定内存区域中 30 | jmp SegOfKernal : OffSetOfKernal 31 | jmp $ ;无限循环 32 | 33 | Message: 34 | db 'Loading MyOs kernal...' 35 | MessageLength equ ($-Message) ; 字符串长度 36 | OffSetOfKernal equ 100h ; 偏移量 37 | SegOfKernal equ 64*1024/16 ; 第二个64k内存的段地址 38 | QTYofBlockOfKernal equ 14 ; 内核占用扇区数 39 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 40 | db 55h, 0aah ; 引导扇区结束标志 41 | 42 | -------------------------------------------------------------------------------- /Lab04/src/pro1.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | 12 | ; 延迟 13 | mov cx,delayTime 14 | toDelay: 15 | mov word[t],cx 16 | mov cx,delayTime 17 | loop1:loop loop1 18 | mov cx,word[t] 19 | loop toDelay 20 | 21 | ret ; 段间返回 22 | 23 | DispStr: ; 显示字符串 24 | ; 显示字符串 "Hello, Here is Program 1 ~"(开始) 25 | mov ah,13h ; 功能号 26 | mov al,1 ; 光标放到串尾 27 | mov bl,0ch ; 黑底红字 28 | mov bh,0 ; 第0页 29 | mov dh,05h ; 第5行 30 | mov dl,1ch ; 第28列 31 | mov bp,BootMsg ; BP=串地址 32 | mov cx,Length1 ; 串长为length1 33 | int 10h ; 调用10H号中断 34 | ; 显示字符串(结束) 35 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 36 | mov ah,13h ; 功能号 37 | mov al,1 ; 光标放到串尾 38 | mov bl,0dh ; 黑底品红字 39 | mov bh,0 ; 第0页 40 | mov dh,07h ; 第7行 41 | mov dl,18 ; 第28列 42 | mov bp,Tips ; BP=串地址 43 | mov cx,Length2 ; 串长 44 | int 10h ; 调用10H号中断 45 | ; 显示字符串2(结束) 46 | ret 47 | 48 | Keyin: ; 读按键 49 | mov ah,0 ; 功能号 50 | int 16h ; 调用16H号中断 51 | ret ; 退出 52 | 53 | Clear: ;清屏 54 | mov ax,0003H ; 清屏属性 55 | int 10H ; 调用中断 56 | ret ; 返回 57 | 58 | delayTime equ 40000 59 | t dw 0 60 | BootMsg: ; 引导字符串 61 | db "Hello. Here is Program 1 ~ " 62 | Length1: equ ($-BootMsg) ; 欢迎字符串的长度 63 | Tips: ; 退出提示 64 | db "Please wait for the program to quit..." 65 | Length2: equ ($-Tips) ; 提示的长度 66 | 67 | 68 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 69 | ;db 55h,0aah ; 启动扇区的结束标志 70 | -------------------------------------------------------------------------------- /Lab04/src/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序2的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | 12 | ; 延迟 13 | mov cx,delayTime 14 | toDelay: 15 | mov word[t],cx 16 | mov cx,delayTime 17 | loop1:loop loop1 18 | mov cx,word[t] 19 | loop toDelay 20 | 21 | ret ; 段间返回 22 | 23 | DispStr: ; 显示字符串 24 | ; 显示字符串 "Hello, Here is Program 1 ~"(开始) 25 | mov ah,13h ; 功能号 26 | mov al,1 ; 光标放到串尾 27 | mov bl,0ch ; 黑底红字 28 | mov bh,0 ; 第0页 29 | mov dh,05h ; 第5行 30 | mov dl,1ch ; 第28列 31 | mov bp,BootMsg ; BP=串地址 32 | mov cx,Length1 ; 串长为length1 33 | int 10h ; 调用10H号中断 34 | ; 显示字符串(结束) 35 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 36 | mov ah,13h ; 功能号 37 | mov al,1 ; 光标放到串尾 38 | mov bl,0dh ; 黑底品红字 39 | mov bh,0 ; 第0页 40 | mov dh,07h ; 第7行 41 | mov dl,18 ; 第28列 42 | mov bp,Tips ; BP=串地址 43 | mov cx,Length2 ; 串长 44 | int 10h ; 调用10H号中断 45 | ; 显示字符串2(结束) 46 | ret 47 | 48 | Keyin: ; 读按键 49 | mov ah,0 ; 功能号 50 | int 16h ; 调用16H号中断 51 | ret ; 退出 52 | 53 | Clear: ;清屏 54 | mov ax,0003H ; 清屏属性 55 | int 10H ; 调用中断 56 | ret ; 返回 57 | 58 | delayTime equ 40000 59 | t dw 0 60 | BootMsg: ; 引导字符串 61 | db "Hi,I am program 2...." 62 | Length1: equ ($-BootMsg) ; 欢迎字符串的长度 63 | Tips: ; 退出提示 64 | db "Please wait for the program to quit..." 65 | Length2: equ ($-Tips) ; 提示的长度 66 | 67 | 68 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 69 | ;db 55h,0aah ; 启动扇区的结束标志 70 | 71 | -------------------------------------------------------------------------------- /Lab04/src/pro3.asm: -------------------------------------------------------------------------------- 1 | ;演示程序 3 2 | Init: ;程序初始化 3 | delayTime equ 4000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,150 88 | je quit 89 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 90 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 91 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 92 | mul word[y] ;计算 160*y ,结果放在 ax 中 93 | mov word[t],ax ;把 ax 的值放到 t 94 | mov ax,word[x] ;把 x 放到 ax 95 | add ax,ax ;ax *= 2 96 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 97 | mov bx,ax ;置 bx 等于 ax ,即为 t 98 | mov al,'A' ;在 al 中放字符 'A' 99 | mov ah,0ch ;在 ah 中放 0ch,表示黑底红字 100 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 101 | mov cx,delayTime ;初始化 cx 为 5000 102 | jmp delay ;跳转到 delay ,进行延迟 103 | 104 | 105 | Clear: ;清屏 106 | MOV AX,0003H 107 | INT 10H 108 | ret 109 | 110 | quit: 111 | ret 112 | 113 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 114 | mov word[t],cx ;把 cx 的值保存到 t 中 115 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 116 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 117 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 118 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 119 | jmp main ;无条件跳转至 main ,继续执行 120 | 121 | data: ;数据声明部分 122 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 123 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 124 | t dw 0 ;声明变量 t ,并初始化 t 为 0 125 | num dw 0 126 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 127 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 128 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 129 | -------------------------------------------------------------------------------- /Lab04/src/services.asm: -------------------------------------------------------------------------------- 1 | ; 本程序为 4 个系统服务程序 2 | BIOSService_1: 3 | push ax 4 | push bx 5 | push cx 6 | push dx 7 | push bp 8 | 9 | mov ah,13h ; 功能号 10 | mov al,0 ; 光标放到串尾 11 | mov bl,0ah ; 亮绿 12 | mov bh,0 ; 第0页 13 | mov dh,0 ; 第0行 14 | mov dl,0 ; 第0列 15 | mov bp,offset MES1 ; BP=串地址 16 | mov cx,504 ; 串长为 504 17 | int 10h ; 调用10H号中断 18 | 19 | pop bp 20 | pop dx 21 | pop cx 22 | pop bx 23 | pop ax 24 | 25 | mov al,33h ; AL = EOI 26 | out 33h,al ; 发送EOI到主8529A 27 | out 0A0h,al ; 发送EOI到从8529A 28 | iret ; 从中断返回 29 | 30 | MES1: 31 | db "****************************************" 32 | db 0ah,0dh 33 | db "**** ****" 34 | db 0ah,0dh 35 | db "**** ****" 36 | db 0ah,0dh 37 | db "**** ****" 38 | db 0ah,0dh 39 | db "**** ****" 40 | db 0ah,0dh 41 | db "**** ****" 42 | db 0ah,0dh 43 | db "**** ****" 44 | db 0ah,0dh 45 | db "**** ****" 46 | db 0ah,0dh 47 | db "**** ****" 48 | db 0ah,0dh 49 | db "**** ****" 50 | db 0ah,0dh 51 | db "**** ****" 52 | db 0ah,0dh 53 | db "****************************************" 54 | db 0ah,0dh,'$' 55 | 56 | BIOSService_2: 57 | push ax 58 | push bx 59 | push cx 60 | push dx 61 | push bp 62 | 63 | mov ah,13h ; 功能号 64 | mov al,0 ; 光标放到串尾 65 | mov bl,0ch ; 亮绿 66 | mov bh,0 ; 第0页 67 | mov dh,5 ; 第5行 68 | mov dl,44 ; 第44列 69 | mov bp,offset MES2 ; BP=串地址 70 | mov cx,30 ; 串长为 30 71 | int 10h ; 调用10H号中断 72 | 73 | pop bp 74 | pop dx 75 | pop cx 76 | pop bx 77 | pop ax 78 | 79 | mov al,34h ; AL = EOI 80 | out 34h,al ; 发送EOI到主8529A 81 | out 0A0h,al ; 发送EOI到从8529A 82 | iret ; 从中断返回 83 | 84 | MES2: 85 | db "You can see me by call int 34h" 86 | 87 | BIOSService_3: 88 | push ax 89 | push bx 90 | push cx 91 | push dx 92 | push bp 93 | 94 | mov ah,13h ; 功能号 95 | mov al,0 ; 光标放到串尾 96 | mov bl,0eh ; 黄色 97 | mov bh,0 ; 第0页 98 | mov dh,13 ; 第13行 99 | mov dl,0 ; 第0列 100 | mov bp,offset MES3 ; BP=串地址 101 | mov cx,479 ; 串长为 479 102 | int 10h ; 调用10H号中断 103 | 104 | pop bp 105 | pop dx 106 | pop cx 107 | pop bx 108 | pop ax 109 | 110 | mov al,35h ; AL = EOI 111 | out 35h,al ; 发送EOI到主8529A 112 | out 0A0h,al ; 发送EOI到从8529A 113 | iret ; 从中断返回 114 | 115 | MES3: 116 | db " O " 117 | db 0ah,0dh 118 | db " O O " 119 | db 0ah,0dh 120 | db " O O " 121 | db 0ah,0dh 122 | db " O O " 123 | db 0ah,0dh 124 | db " O O " 125 | db 0ah,0dh 126 | db " O O " 127 | db 0ah,0dh 128 | db " O O " 129 | db 0ah,0dh 130 | db " O O " 131 | db 0ah,0dh 132 | db " O O " 133 | db 0ah,0dh 134 | db " O O " 135 | db 0ah,0dh 136 | db " O O " 137 | db 0ah,0dh 138 | db " O " 139 | db 0ah,0dh,'$' 140 | 141 | 142 | BIOSService_4: 143 | push ax 144 | push bx 145 | push cx 146 | push dx 147 | push bp 148 | 149 | mov ah,13h ; 功能号 150 | mov al,0 ; 光标放到串尾 151 | mov bl,71h ; 白底深蓝 152 | mov bh,0 ; 第0页 153 | mov dh,18 ; 第18行 154 | mov dl,46 ; 第46列 155 | mov bp,offset MES4 ; BP=串地址 156 | mov cx,28 ; 串长为 28 157 | int 10h ; 调用10H号中断 158 | 159 | pop bp 160 | pop dx 161 | pop cx 162 | pop bx 163 | pop ax 164 | 165 | mov al,36h ; AL = EOI 166 | out 36h,al ; 发送EOI到主8529A 167 | out 0A0h,al ; 发送EOI到从8529A 168 | iret ; 从中断返回 169 | 170 | MES4: 171 | db "Tomorrow is another day~ ^_^" 172 | -------------------------------------------------------------------------------- /Lab05/README.md: -------------------------------------------------------------------------------- 1 | 改进你的原型操作系统,满足下列要求: 2 | 3 | (1)参考下面的系统调用功能表,增加3个其他功能(详见 doc ) 4 | 5 | (2)扩展MYOS内核,实现上表中的所有(包括你增加的)系统调用; 6 | 7 | (3)设计C程序库,实现系统调用的封装,并开发一个测试系统调用所有功能的C程序。 8 | 9 | -------------------------------------------------------------------------------- /Lab05/disk/Lab05.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab05/disk/Lab05.img -------------------------------------------------------------------------------- /Lab05/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab05/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab05/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | extrn _cmain:near ; 声明一个c程序函数cmain() 5 | extrn _to_upper:near ; 声明一个c程序函数cmain() 6 | extrn _to_lower:near ; 声明一个c程序函数cmain() 7 | extrn _to_digit:near ; 声明一个c程序函数cmain() 8 | extrn _to_deci:near ; 声明一个c程序函数cmain() 9 | extrn _to_reverse:near ; 声明一个c程序函数cmain() 10 | extrn _timeToString:near ; 声明一个c程序函数cmain() 11 | extrn _digit_to_str:near ; 声明一个c程序函数cmain() 12 | extrn _get_strlen:near 13 | extrn _print:near ; 声明一个c程序函数cmain() 14 | extrn _printInt:near ; 声明一个c程序函数cmain() 15 | extrn _t:near ; C 中的变量,用于存储读入的字符 16 | extrn _ch1:near ; C 中变量,存放临时字符 17 | extrn _ch2:near ; C 中变量,存放临时字符 18 | extrn _ch3:near ; C 中变量,存放临时字符 19 | extrn _ch4:near ; C 中变量,存放临时字符 20 | extrn _p:near ; C 中变量,代表 应该读入的扇区号 21 | 22 | .8086 23 | _TEXT segment byte public 'CODE' 24 | assume cs:_TEXT 25 | DGROUP group _TEXT,_DATA,_BSS 26 | org 100h 27 | start: 28 | 29 | ;设置 21h 的中断 30 | xor ax,ax 31 | mov es,ax 32 | mov word ptr es:[33*4],offset MOS_21h ; 设置 21h 的偏移地址 33 | mov ax,cs 34 | mov word ptr es:[33*4+2],ax 35 | 36 | xor ax,ax ; AX = 0 37 | mov es,ax ; ES = 0 38 | mov ax,offset Timer 39 | mov word ptr es:[20h],offset Timer ; 设置时钟中断向量的偏移地址 40 | mov ax,cs 41 | mov word ptr es:[22h],cs ; 设置时钟中断向量的段地址=CS 42 | 43 | ;设置 33h 的中断 44 | xor ax,ax 45 | mov es,ax 46 | mov word ptr es:[51*4],offset MOS_33h ; 设置 33h 的偏移地址 47 | mov ax,cs 48 | mov word ptr es:[51*4+2],ax 49 | 50 | ;设置 34h 的中断 51 | xor ax,ax 52 | mov es,ax 53 | mov word ptr es:[52*4],offset MOS_34h ; 设置 34h 的偏移地址 54 | mov ax,cs 55 | mov word ptr es:[52*4+2],ax 56 | 57 | ;设置 35h 的中断 58 | xor ax,ax 59 | mov es,ax 60 | mov word ptr es:[53*4],offset MOS_35h ; 设置 35h 的偏移地址 61 | mov ax,cs 62 | mov word ptr es:[53*4+2],ax 63 | 64 | ;设置 36h 的中断 65 | xor ax,ax 66 | mov es,ax 67 | mov word ptr es:[54*4],offset MOS_36h ; 设置 36h 的偏移地址 68 | mov ax,cs 69 | mov word ptr es:[54*4+2],ax 70 | 71 | mov ax, cs 72 | mov ds, ax ; DS = CS 73 | mov es, ax ; ES = CS 74 | mov ss, ax ; SS = cs 75 | mov sp, 64*1024-4 ; SP指向本段高端-4 76 | call near ptr _cmain ; 调用C语言程序cmain() 77 | jmp $ 78 | 79 | include function.asm ; 包含内核库过程 function.asm 80 | include services.asm ; 包含系统服务程序 81 | 82 | _TEXT ends 83 | _DATA segment word public 'DATA' 84 | _DATA ends 85 | _BSS segment word public 'BSS' 86 | _BSS ends 87 | end start 88 | 89 | -------------------------------------------------------------------------------- /Lab05/src/boot.asm: -------------------------------------------------------------------------------- 1 | ;程序源代码(boot.asm) 2 | ;用NASM汇编此程序 3 | ;nasm –f bin boot.asm –o boot.bin 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00处,并开始执行 5 | Start: 6 | mov ax, cs ; 置其他段寄存器值与CS相同 7 | mov ds, ax ; 数据段 8 | mov bp, Message ; BP=当前串的偏移地址 9 | mov ax, ds ; ES:BP = 串地址 10 | mov es, ax ; 置ES=DS 11 | mov cx, MessageLength ; CX = 串长(=9) 12 | mov ax, 1301h ; AH = 13h(功能号)、AL = 01h(光标置于串尾) 13 | mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) 14 | mov dh, 0 ; 行号=0 15 | mov dl, 0 ; 列号=0 16 | int 10h ; BIOS的10h功能:显示一行字符 17 | LoadKernal: 18 | ;读软盘或硬盘上的kernal到内存的ES:BX处: 19 | mov ax, SegOfKernal ; 段地址 ; 存放数据的内存基地址 20 | mov es,ax ; 设置段地址(不能直接mov es,段地址) 21 | mov bx, OffSetOfKernal ; 偏移地址; 存放数据的内存偏移地址 22 | mov ah,2 ; 功能号 23 | mov al, QTYofBlockOfKernal ; 扇区数 24 | mov dl,0 ; 驱动器号 ; 软盘为0,硬盘和U盘为80H 25 | mov dh,0 ; 磁头号 ; 起始编号为0 26 | mov ch,0 ; 柱面号 ; 起始编号为0 27 | mov cl,2 ; 起始扇区号 ; 起始编号为1 28 | int 13H ; 调用中断 29 | ;内核已加载到指定内存区域中 30 | jmp SegOfKernal : OffSetOfKernal 31 | jmp $ ;无限循环 32 | 33 | Message: 34 | db 'Loading MyOs kernal...' 35 | MessageLength equ ($-Message) ; 字符串长度 36 | OffSetOfKernal equ 100h ; 偏移量 37 | SegOfKernal equ 64*1024/16 ; 第二个64k内存的段地址 38 | QTYofBlockOfKernal equ 24 ; 内核占用扇区数 39 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 40 | db 55h, 0aah ; 引导扇区结束标志 41 | 42 | -------------------------------------------------------------------------------- /Lab05/src/pro1.asm: -------------------------------------------------------------------------------- 1 | ; 运动不填充的小球,尾巴逐渐变长 2 | Init: ;程序初始化 3 | org 7e00h ;程序装载到 7c00h 4 | 5 | mov ax,cs 6 | mov ds,ax ; DS = CS 7 | mov es,ax ; ES = CS 8 | call Clear 9 | jmp Always 10 | jmp $ ; 死循环 11 | 12 | delay equ 3 ; 计时器延迟计数 13 | count1 db 1 ; 计时器计数变量,初值=delay 14 | count2 db 3 15 | 16 | Always: 17 | cmp1: 18 | dec byte[count1] ; 递减计数变量 19 | jnz cmp2 20 | mov ax,word[x1] 21 | mov word[x],ax 22 | mov ax,word[y1] 23 | mov word[y],ax 24 | mov ax,word[t1] 25 | mov word[t],ax 26 | mov ax,word[num1] 27 | mov word[num],ax 28 | mov ax,word[statex1] 29 | mov word[statex],ax 30 | mov ax,word[statey1] 31 | mov word[statey],ax 32 | mov byte[c],65 33 | jmp do 34 | 35 | cmp2: 36 | dec byte[count2] 37 | jnz toEnd 38 | mov ax,word[x2] 39 | mov word[x],ax 40 | mov ax,word[y2] 41 | mov word[y],ax 42 | mov ax,word[t2] 43 | mov word[t],ax 44 | mov ax,word[num2] 45 | mov word[num],ax 46 | mov ax,word[statex2] 47 | mov word[statex],ax 48 | mov ax,word[statey2] 49 | mov word[statey],ax 50 | mov byte[c],32 51 | jmp do 52 | 53 | do: 54 | jmp main 55 | toEnd: 56 | call Todelay 57 | jmp Always 58 | 59 | main: ;可视为主函数 60 | mov ax,24 ;置 ax 为立即数 24 61 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 62 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 63 | mov ax,0 ;在 ax 中放 0 64 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 65 | je UptoDown ;上述条件成立则跳转至 UptoDown 66 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 67 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 68 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 69 | mov ax,0 ;在 ax 中置 0 70 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 71 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 72 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 73 | ret 74 | 75 | Usual: ;在没有触发边界时执行的代码块 76 | mov ax,0 ;ax 置零 77 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 78 | je Down ;相等时跳转到 Down ,向下运动 79 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 80 | 81 | DownToUp: ;触底反弹 82 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 83 | cmp byte[x],0 ;是否到达左下角 84 | je LeftToRight 85 | cmp byte[x],79 ;是否到达右下角 86 | je RightToLeft 87 | jmp Up ;无条件跳转至 Up 88 | 89 | UptoDown: ;触顶反弹 90 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 91 | cmp byte[x],0 ;是否到达左上角 92 | je LeftToRight 93 | cmp byte[x],79 ;是否到达右上角 94 | je RightToLeft 95 | jmp Down ;无条件跳转至 Down 96 | 97 | RightToLeft: ;在最右反弹 98 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 99 | mov ax,0 ;把 ax 置 0 100 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 101 | je Down ;是则跳转到 Down ,向下 102 | jmp Up ;否则跳转到 Up ,向上 103 | 104 | LeftToRight: ;在最左反弹 105 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 106 | mov ax,0 ;将 ax 置 0 107 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 108 | je Down ;是则跳转到 Down 109 | jmp Up ;否则跳转到 Up 110 | 111 | Up: ;向上运动 112 | dec word[y] ;y-- ,把纵坐标减 1,向上 113 | mov ax,0 ;ax 置 0 114 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 115 | je R ;是的话跳转到 R 116 | jmp L ;不是的话跳转到 L 117 | 118 | Down: ;向下运动 119 | inc word[y] ;y++,把纵坐标加 1 ,向下 120 | mov ax,0 ;置 ax 为 0 121 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 122 | je R ;是的话跳转到 R 123 | jmp L ;不是的话跳转到 L 124 | 125 | R: ;向右运动 126 | inc word[x] ; x++,横坐标加 1,向右 127 | jmp Show ;跳转至 Show 代码段 128 | 129 | L: ;向左运动 130 | dec word[x] ;x--,横坐标减 1,向左 131 | jmp Show ;跳转至 Show 代码段 132 | 133 | Show: ;显示字符 134 | inc word[num] 135 | mov ax,word[num] 136 | cmp ax,150 137 | je quit 138 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 139 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 140 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 141 | mul word[y] ;计算 160*y ,结果放在 ax 中 142 | mov word[t],ax ;把 ax 的值放到 t 143 | mov ax,word[x] ;把 x 放到 ax 144 | add ax,ax ;ax *= 2 145 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 146 | mov bx,ax ;置 bx 等于 ax ,即为 t 147 | mov al,byte[c] ;在 al 中放字符 'A' 148 | mov ah,0ch ;在 ah 中放 0ch,表示黑底红字 149 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 150 | mov ax,0 151 | cmp al,byte[count1] 152 | je writeBack1 153 | cmp al,byte[count2] 154 | je writeBack2 155 | jmp toEnd 156 | 157 | writeBack1: 158 | mov ax,word[x] 159 | mov word[x1],ax 160 | mov ax,word[y] 161 | mov word[y1],ax 162 | mov ax,word[t] 163 | mov word[t1],ax 164 | mov ax,word[num] 165 | mov word[num1],ax 166 | mov ax,word[statex] 167 | mov word[statex1],ax 168 | mov ax,word[statey] 169 | mov word[statey1],ax 170 | mov byte[count1],delay 171 | jmp toEnd 172 | 173 | writeBack2: 174 | mov ax,word[x] 175 | mov word[x2],ax 176 | mov ax,word[y] 177 | mov word[y2],ax 178 | mov ax,word[t] 179 | mov word[t2],ax 180 | mov ax,word[num] 181 | mov word[num2],ax 182 | mov ax,word[statex] 183 | mov word[statex2],ax 184 | mov ax,word[statey] 185 | mov word[statey2],aX 186 | mov byte[count2],delay 187 | jmp toEnd 188 | 189 | Clear: ;清屏 190 | MOV AX,0003H 191 | INT 10H 192 | ret 193 | 194 | Todelay: ;双重循环进行延迟,延迟时间为 5000*5000 195 | mov word[tt],cx ;把 cx 的值保存到 t 中 196 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 197 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 198 | mov cx,word[tt] ;把 t 的值放回 cx ,恢复 cx 199 | loop Todelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 200 | 201 | ret 202 | 203 | delayTime equ 100 204 | 205 | quit: 206 | ret 207 | 208 | data: ;数据声明部分 209 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 210 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 211 | t dw 0 ;声明变量 t ,并初始化 t 为 0 212 | c db 65 213 | tt dw 0 ;声明变量 t ,并初始化 t 为 0 214 | num dw 0 215 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 216 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 217 | x1 dw 0 ;声明变量 x ,并初始化 x 为 -1 218 | y1 dw 0 ;声明变量 y ,并初始化 y 为 -1 219 | t1 dw 0 ;声明变量 t ,并初始化 t 为 0 220 | num1 dw 0 221 | statey1 dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 222 | statex1 dw 0 223 | x2 dw -1 ;声明变量 x ,并初始化 x 为 -1 224 | y2 dw -1 ;声明变量 y ,并初始化 y 为 -1 225 | t2 dw 0 ;声明变量 t ,并初始化 t 为 0 226 | num2 dw 0 227 | statey2 dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 228 | statex2 dw 0 229 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 230 | ; 写入启动扇区的结束标志 231 | ;db 55h,0aah 232 | 233 | -------------------------------------------------------------------------------- /Lab05/src/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | call DispStr ; 显示字符串 11 | 12 | mov cx,delayTime ;初始化 cx 为 5000 13 | toDelay: ;双重循环进行延迟,延迟时间为 5000*5000 14 | mov word[t],cx ;把 cx 的值保存到 t 中 15 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 16 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 17 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 18 | loop toDelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 19 | 20 | ret ; 段间返回 21 | 22 | DispStr: ; 显示字符串 23 | ; 显示字符串 "Hello, Here is Program 1 ~"(开始) 24 | mov ah,13h ; 功能号 25 | mov al,1 ; 光标放到串尾 26 | mov bl,0ch ; 黑底红字 27 | mov bh,0 ; 第0页 28 | mov dh,05h ; 第5行 29 | mov dl,1ch ; 第28列 30 | mov bp,BootMsg ; BP=串地址 31 | mov cx,Length1 ; 串长为length1 32 | int 10h ; 调用10H号中断 33 | ; 显示字符串(结束) 34 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 35 | mov ah,13h ; 功能号 36 | mov al,1 ; 光标放到串尾 37 | mov bl,0dh ; 黑底品红字 38 | mov bh,0 ; 第0页 39 | mov dh,07h ; 第7行 40 | mov dl,18 ; 第28列 41 | mov bp,Tips ; BP=串地址 42 | mov cx,Length2 ; 串长 43 | int 10h ; 调用10H号中断 44 | ; 显示字符串2(结束) 45 | ret 46 | 47 | Keyin: ; 读按键 48 | mov ah,0 ; 功能号 49 | int 16h ; 调用16H号中断 50 | ret ; 退出 51 | 52 | Clear: ;清屏 53 | mov ax,0003H ; 清屏属性 54 | int 10H ; 调用中断 55 | ret ; 返回 56 | 57 | delayTime equ 40000 58 | t dw 0 59 | BootMsg: ; 引导字符串 60 | db "Hi,I am program 2...." 61 | Length1: equ ($-BootMsg) ; 欢迎字符串的长度 62 | Tips: ; 退出提示 63 | db "Please wait for the program to quit..." 64 | Length2: equ ($-Tips) ; 提示的长度 65 | 66 | 67 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 68 | ;db 55h,0aah ; 启动扇区的结束标志 69 | 70 | -------------------------------------------------------------------------------- /Lab05/src/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 一个运动的黄色 U 100 个往后擦除 2 | Init: ;程序初始化 3 | delayTime equ 6000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,199 88 | je quit 89 | cmp ax,100 90 | jnz next 91 | call change 92 | 93 | next: 94 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 95 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 96 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 97 | mul word[y] ;计算 160*y ,结果放在 ax 中 98 | mov word[t],ax ;把 ax 的值放到 t 99 | mov ax,word[x] ;把 x 放到 ax 100 | add ax,ax ;ax *= 2 101 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 102 | mov bx,ax ;置 bx 等于 ax ,即为 t 103 | mov al,byte[c] ;在 al 中放字符 'Z' 104 | mov ah,0eh ;在 ah 中放 0ch,表示黑底红字 105 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 106 | mov cx,delayTime ;初始化 cx 为 5000 107 | jmp delay ;跳转到 delay ,进行延迟 108 | 109 | 110 | change: 111 | mov byte[c],32 112 | cmp word[statex],0 113 | jnz cmp2 114 | mov word[statex],1 115 | jmp cmp3 116 | cmp2: 117 | mov word[statex],0 118 | cmp3: 119 | cmp word[statey],0 120 | jnz cmp4 121 | mov word[statey],1 122 | ret 123 | cmp4: 124 | mov word[statey],0 125 | ret 126 | 127 | Clear: ;清屏 128 | MOV AX,0003H 129 | INT 10H 130 | ret 131 | 132 | quit: 133 | ret 134 | 135 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 136 | mov word[t],cx ;把 cx 的值保存到 t 中 137 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 138 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 139 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 140 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 141 | jmp main ;无条件跳转至 main ,继续执行 142 | 143 | data: ;数据声明部分 144 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 145 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 146 | t dw 0 ;声明变量 t ,并初始化 t 为 0 147 | num dw 0 148 | c db 'U' 149 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 150 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 151 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 152 | ;db 55h,0aah 153 | 154 | -------------------------------------------------------------------------------- /Lab06/README.md: -------------------------------------------------------------------------------- 1 | 保留原型原有特征的基础上,设计满足下列要求的新原型操作系统: 2 | 3 | (1) 在c程序中定义进程表,进程数量最多4个。 4 | 5 | (2) 内核一次性加载4个用户程序运行时,采用时间片轮转调度进程运行,用户程序的输出各占1/4屏幕区域,信息输出有动感,以便观察程序是否在执行。 6 | 7 | (3) 在原型中保证原有的系统调用服务可用。再编写4个用户程序,展示系统调用服务还能工作。 8 | 9 | -------------------------------------------------------------------------------- /Lab06/bat/run1.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | nasm boot.asm -o boot.img 4 | 5 | nasm pro1.asm -o pro1.img 6 | 7 | nasm pro2.asm -o pro2.img 8 | 9 | nasm pro3.asm -o pro3.img 10 | 11 | nasm process1.asm -o process1.img 12 | 13 | nasm process2.asm -o process2.img 14 | 15 | nasm process3.asm -o process3.img 16 | 17 | nasm process4.asm -o process4.img 18 | -------------------------------------------------------------------------------- /Lab06/bat/run2.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | tcc -mt -c -omyos.obj MyOs.c 4 | 5 | tasm MyOs.asm os.obj 6 | 7 | tasm c_lib.asm c_lib.lib 8 | 9 | tlink /3 /t os.obj myos.obj c_lib.lib,os.com 10 | 11 | -------------------------------------------------------------------------------- /Lab06/bat/run3.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | nasm boot.asm -o boot.img 4 | 5 | nasm pro1.asm -o pro1.img 6 | 7 | nasm pro2.asm -o pro2.img 8 | 9 | nasm pro3.asm -o pro3.img 10 | 11 | nasm process1.asm -o process1.img 12 | 13 | nasm process2.asm -o process2.img 14 | 15 | nasm process3.asm -o process3.img 16 | 17 | nasm process4.asm -o process4.img 18 | 19 | tcc -mt -c -omyos.obj MyOs.c 20 | 21 | tasm MyOs.asm os.obj 22 | 23 | tasm c_lib.asm c_lib.lib 24 | 25 | tlink /3 /t os.obj myos.obj c_lib.lib,os.com 26 | 27 | -------------------------------------------------------------------------------- /Lab06/disk/Lab06.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab06/disk/Lab06.img -------------------------------------------------------------------------------- /Lab06/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab06/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab06/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | 6 | .8086 7 | _TEXT segment byte public 'CODE' 8 | assume cs:_TEXT 9 | DGROUP group _TEXT,_DATA,_BSS 10 | org 100h 11 | start: 12 | 13 | ;设置 21h 的中断 14 | xor ax,ax 15 | mov es,ax 16 | mov word ptr es:[33*4],offset MOS_21h ; 设置 21h 的偏移地址 17 | mov ax,cs 18 | mov word ptr es:[33*4+2],ax 19 | 20 | ;设置 33h 的中断 21 | xor ax,ax 22 | mov es,ax 23 | mov word ptr es:[51*4],offset MOS_33h ; 设置 33h 的偏移地址 24 | mov ax,cs 25 | mov word ptr es:[51*4+2],ax 26 | 27 | ;设置 34h 的中断 28 | xor ax,ax 29 | mov es,ax 30 | mov word ptr es:[52*4],offset MOS_34h ; 设置 34h 的偏移地址 31 | mov ax,cs 32 | mov word ptr es:[52*4+2],ax 33 | 34 | ;设置 35h 的中断 35 | xor ax,ax 36 | mov es,ax 37 | mov word ptr es:[53*4],offset MOS_35h ; 设置 35h 的偏移地址 38 | mov ax,cs 39 | mov word ptr es:[53*4+2],ax 40 | 41 | ;设置 36h 的中断 42 | xor ax,ax 43 | mov es,ax 44 | mov word ptr es:[54*4],offset MOS_36h ; 设置 36h 的偏移地址 45 | mov ax,cs 46 | mov word ptr es:[54*4+2],ax 47 | 48 | mov ax, cs 49 | mov ds, ax ; DS = CS 50 | mov es, ax ; ES = CS 51 | mov ss, ax ; SS = cs 52 | mov sp, 100h ; SP指向本段高端-4 53 | call near ptr _cmain ; 调用C语言程序cmain() 54 | jmp $ 55 | 56 | include function.asm ; 包含内核库过程 function.asm 57 | include services.asm ; 包含系统服务程序 58 | 59 | _TEXT ends 60 | _DATA segment word public 'DATA' 61 | _DATA ends 62 | _BSS segment word public 'BSS' 63 | _BSS ends 64 | end start 65 | 66 | -------------------------------------------------------------------------------- /Lab06/src/boot.asm: -------------------------------------------------------------------------------- 1 | ;程序源代码(boot.asm) 2 | ;用NASM汇编此程序 3 | ;nasm –f bin boot.asm –o boot.bin 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00处,并开始执行 5 | Start: 6 | mov ax, cs ; 置其他段寄存器值与CS相同 7 | mov ds, ax ; 数据段 8 | mov bp, Message ; BP=当前串的偏移地址 9 | mov ax, ds ; ES:BP = 串地址 10 | mov es, ax ; 置ES=DS 11 | mov cx, MessageLength ; CX = 串长(=9) 12 | mov ax, 1301h ; AH = 13h(功能号)、AL = 01h(光标置于串尾) 13 | mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) 14 | mov dh, 0 ; 行号=0 15 | mov dl, 0 ; 列号=0 16 | int 10h ; BIOS的10h功能:显示一行字符 17 | LoadKernal: 18 | ;读软盘或硬盘上的kernal到内存的ES:BX处: 19 | mov ax, SegOfKernal ; 段地址 ; 存放数据的内存基地址 20 | mov es,ax ; 设置段地址(不能直接mov es,段地址) 21 | mov bx, OffSetOfKernal ; 偏移地址; 存放数据的内存偏移地址 22 | mov ah,2 ; 功能号 23 | mov al, QTYofBlockOfKernal ; 扇区数 24 | mov dl,0 ; 驱动器号 ; 软盘为0,硬盘和U盘为80H 25 | mov dh,0 ; 磁头号 ; 起始编号为0 26 | mov ch,0 ; 柱面号 ; 起始编号为0 27 | mov cl,2 ; 起始扇区号 ; 起始编号为1 28 | int 13H ; 调用中断 29 | ;内核已加载到指定内存区域中 30 | jmp SegOfKernal : OffSetOfKernal 31 | jmp $ ;无限循环 32 | 33 | Message: 34 | db 'Loading MyOs kernal...' 35 | MessageLength equ ($-Message) ; 字符串长度 36 | OffSetOfKernal equ 100h ; 偏移量 37 | SegOfKernal equ 1000h ; 第二个64k内存的段地址 38 | QTYofBlockOfKernal equ 17 ; 内核占用扇区数 39 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 40 | db 55h, 0aah ; 引导扇区结束标志 41 | 42 | -------------------------------------------------------------------------------- /Lab06/src/process.h: -------------------------------------------------------------------------------- 1 | #define Max_PCB 8 2 | /*当前进程编号 */ 3 | int current_PCB = 0; 4 | /*进程数量*/ 5 | int processNum = 1; 6 | /* 新进程段基址 */ 7 | int current_Seg = 0x2000; 8 | /* 进程状态 */ 9 | typedef enum PCB_Status{PCB_READY,PCB_EXIT,PCB_RUNNING, PCB_BLOCKING}PCB_Status; 10 | /* 标志进程是否第一次执行 */ 11 | int tinyFlag; 12 | /* 是否为内核态 */ 13 | int kernal_mode; 14 | 15 | typedef struct RegisterImage{ 16 | int SS; 17 | int GS; 18 | int FS; 19 | int ES; 20 | int DS; 21 | int DI; 22 | int SI; 23 | int BP; 24 | int SP; 25 | int BX; 26 | int DX; 27 | int CX; 28 | int AX; 29 | int IP; 30 | int CS; 31 | int Flags; 32 | }RegisterImage; 33 | 34 | typedef struct PCB{ 35 | RegisterImage regImg;/***registers will be saved in this struct automactically by timer interrupt***/ 36 | /******/ 37 | PCB_Status status; 38 | int ID; 39 | }PCB; 40 | 41 | /*进程表定义*/ 42 | PCB PCB_Queue[Max_PCB]; 43 | /* 当前进程的指针 */ 44 | PCB *runningPCB; 45 | 46 | /*获取当前进程指针*/ 47 | PCB* getCurrentPCB(){ 48 | return &PCB_Queue[current_PCB]; 49 | } 50 | 51 | /*保存当前进程控制块*/ 52 | void SavePCB(int ax,int bx, int cx, int dx, int sp, int bp, int si, int di, int ds ,int es,int fs,int gs, int ss,int ip, int cs,int fl) 53 | { 54 | runningPCB = getCurrentPCB(); 55 | 56 | /******************************/ 57 | runningPCB->regImg.AX = ax; 58 | runningPCB->regImg.BX = bx; 59 | runningPCB->regImg.CX = cx; 60 | runningPCB->regImg.DX = dx; 61 | /******************************/ 62 | runningPCB->regImg.DS = ds; 63 | runningPCB->regImg.ES = es; 64 | runningPCB->regImg.FS = fs; 65 | runningPCB->regImg.GS = gs; 66 | runningPCB->regImg.SS = ss; 67 | /******************************/ 68 | runningPCB->regImg.IP = ip; 69 | runningPCB->regImg.CS = cs; 70 | runningPCB->regImg.Flags = fl; 71 | /******************************/ 72 | runningPCB->regImg.DI = di; 73 | runningPCB->regImg.SI = si; 74 | runningPCB->regImg.SP = sp; 75 | runningPCB->regImg.BP = bp; 76 | } 77 | 78 | /*进程调度,进行进程轮转 */ 79 | void Schedule() 80 | { 81 | /* 切换前进程转态为 PCB_BLOCKING */ 82 | runningPCB->status = PCB_BLOCKING; 83 | 84 | /* 下一个进程 */ 85 | current_PCB = current_PCB+1; 86 | 87 | if(current_PCB == processNum) 88 | current_PCB = 1; 89 | 90 | /* 得到切换后的进程指针 */ 91 | runningPCB = getCurrentPCB(); 92 | 93 | /*进程状态为 PCB_READY,则表示第一次执行,tinyFlag 置 1 */ 94 | if(runningPCB->status == PCB_READY) 95 | tinyFlag = 1; 96 | 97 | /* 切换后进程转态为 PCB_RUNNING*/ 98 | runningPCB->status = PCB_RUNNING; 99 | 100 | return; 101 | } 102 | 103 | /*初始化进程控制块*/ 104 | void PCBInit(PCB *p, int processID, int seg) 105 | { 106 | p->ID = processID; 107 | p->status = PCB_READY; 108 | /******************************/ 109 | p->regImg.GS = 0xb800; 110 | p->regImg.ES = seg; 111 | p->regImg.DS = seg; 112 | p->regImg.FS = seg; 113 | p->regImg.SS = seg; 114 | /******************************/ 115 | p->regImg.DI = 0; 116 | p->regImg.SI = 0; 117 | p->regImg.BP = 0; 118 | p->regImg.SP = 0x100 - 4; 119 | /******************************/ 120 | p->regImg.BX = 0; 121 | p->regImg.AX = 0; 122 | p->regImg.CX = 0; 123 | p->regImg.DX = 0; 124 | /******************************/ 125 | p->regImg.IP = 0x100; 126 | p->regImg.CS = seg; 127 | p->regImg.Flags = 512; 128 | } 129 | 130 | /*创建新的进程*/ 131 | void createNewPCB() 132 | { 133 | if(processNum > Max_PCB) return; 134 | 135 | PCBInit( &PCB_Queue[processNum] ,processNum, current_Seg); 136 | processNum++; 137 | current_Seg += 0x1000; 138 | } 139 | 140 | /* 清空进程控制块 */ 141 | void deleteAllPCB() 142 | { 143 | processNum = 1; 144 | current_Seg = 0x2000; 145 | current_PCB = 0; 146 | } 147 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | 11 | mov ah,0 12 | int 21h 13 | 14 | call DispStr ; 显示字符串 15 | call Delay 16 | call Clear 17 | int 33h 18 | int 34h 19 | int 35h 20 | int 36h 21 | call Delay 22 | ret 23 | 24 | Delay: 25 | mov cx,delayTime ;初始化 cx 为 5000 26 | toDelay: ;双重循环进行延迟,延迟时间为 5000*5000 27 | mov word[t],cx ;把 cx 的值保存到 t 中 28 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 29 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 30 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 31 | loop toDelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 32 | ret ; 段间返回 33 | 34 | DispStr: ; 显示字符串 35 | ; 显示字符串 (开始) 36 | mov ah,5 37 | mov dx,Msg ; dx 放字符串地址 38 | mov ch,5 ; ch 放行号 39 | mov cl,23 ; cl 放列号 40 | int 21h 41 | ; 显示字符串(结束) 42 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 43 | mov ah,13h ; 功能号 44 | mov al,1 ; 光标放到串尾 45 | mov bl,0dh ; 黑底品红字 46 | mov bh,0 ; 第0页 47 | mov dh,07h ; 第7行 48 | mov dl,18 ; 第28列 49 | mov bp,Tips ; BP=串地址 50 | mov cx,Length2 ; 串长 51 | int 10h ; 调用10H号中断 52 | ; 显示字符串2(结束) 53 | ret 54 | 55 | Clear: ;清屏 56 | mov ax,0003H ; 清屏属性 57 | int 10H ; 调用中断 58 | ret ; 返回 59 | 60 | delayTime equ 40000 61 | t dw 0 62 | Msg: ; 字符串 63 | db "Look! The 21h is still available....",0h 64 | Tips: ; 退出提示 65 | db "Please wait for the program to quit..." 66 | Length2: equ ($-Tips) ; 提示的长度 67 | 68 | 69 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 70 | ;db 55h,0aah ; 启动扇区的结束标志 71 | 72 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 一个运动的黄色 U 100 个往后擦除 2 | Init: ;程序初始化 3 | delayTime equ 6000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,199 88 | je quit 89 | cmp ax,100 90 | jnz next 91 | call change 92 | 93 | next: 94 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 95 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 96 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 97 | mul word[y] ;计算 160*y ,结果放在 ax 中 98 | mov word[t],ax ;把 ax 的值放到 t 99 | mov ax,word[x] ;把 x 放到 ax 100 | add ax,ax ;ax *= 2 101 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 102 | mov bx,ax ;置 bx 等于 ax ,即为 t 103 | mov al,byte[c] ;在 al 中放字符 'Z' 104 | mov ah,0eh ;在 ah 中放 0ch,表示黑底红字 105 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 106 | mov cx,delayTime ;初始化 cx 为 5000 107 | jmp delay ;跳转到 delay ,进行延迟 108 | 109 | 110 | change: 111 | mov byte[c],32 112 | cmp word[statex],0 113 | jnz cmp2 114 | mov word[statex],1 115 | jmp cmp3 116 | cmp2: 117 | mov word[statex],0 118 | cmp3: 119 | cmp word[statey],0 120 | jnz cmp4 121 | mov word[statey],1 122 | ret 123 | cmp4: 124 | mov word[statey],0 125 | ret 126 | 127 | Clear: ;清屏 128 | MOV AX,0003H 129 | INT 10H 130 | ret 131 | 132 | quit: 133 | ret 134 | 135 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 136 | mov word[t],cx ;把 cx 的值保存到 t 中 137 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 138 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 139 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 140 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 141 | jmp main ;无条件跳转至 main ,继续执行 142 | 143 | data: ;数据声明部分 144 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 145 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 146 | t dw 0 ;声明变量 t ,并初始化 t 为 0 147 | num dw 0 148 | c db 'U' 149 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 150 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 151 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 152 | ;db 55h,0aah 153 | 154 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/process1.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-05-2 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h ; 程序加载到100h,可用于生成COM 14 | 15 | ;初始化段寄存器 16 | xor ax,ax ; AX = 0 17 | mov ax,100 18 | mov es,ax ; ES = 0 19 | mov ds,ax ; DS = CS 20 | mov ax,0B800h ; 文本窗口显存起始地址 21 | mov gs,ax ; GS = B800h 22 | mov word[count],delay 23 | mov word[dcount],ddelay 24 | 25 | mov word[x],0 26 | mov word[y],0 27 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 28 | mov word[char],'A' 29 | 30 | loop1: 31 | dec word[count] ; 递减计数变量 32 | jnz loop1 ; >0:跳转; 33 | mov word[count],delay 34 | dec word[dcount] ; 递减计数变量 35 | jnz loop1 36 | call boxing 37 | mov word[count],delay 38 | mov word[dcount],ddelay 39 | jmp loop1 40 | 41 | jmp $ ; 死循环 42 | 43 | datadef: 44 | 45 | count dw delay ; 计时器计数变量,初值=delay 46 | dcount dw ddelay ; 计时器计数变量,初值=delay 47 | x dw 0 ; 当前字符显示位置的行号,0~24 48 | y dw 0 ; 当前字符显示位置的列号,0~79 49 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 50 | char db 'A' ; 当前显示字符 51 | 52 | 53 | boxing: 54 | 55 | right: 56 | mov al,byte[rdlu] ;左-->右 57 | cmp al,1 58 | jnz down 59 | mov ax,word[y] ;最后一列? 60 | cmp ax, 39 61 | jz r2d 62 | inc byte[y] 63 | jmp show 64 | r2d: 65 | mov byte[rdlu],2 ;改为向下 66 | inc byte[x] 67 | jmp show 68 | 69 | down: 70 | mov al,byte[rdlu] ;向下 71 | cmp al,2 72 | jnz left 73 | mov ax,word[x] ;最后一行? 74 | cmp ax, 12 75 | jz d2l 76 | inc byte[x] 77 | jmp show 78 | d2l: 79 | mov byte[rdlu],3 ;改为向左 80 | dec byte[y] 81 | jmp show 82 | 83 | left: 84 | mov al,byte[rdlu] ;向左 85 | cmp al,3 86 | jnz up 87 | mov ax,word[y] ;最左一列? 88 | cmp ax, 0 89 | jz l2u 90 | dec byte[y] 91 | jmp show 92 | l2u: 93 | mov byte[rdlu],4 ;改为向 上 94 | dec byte[x] 95 | jmp show 96 | 97 | up: 98 | mov al,byte[rdlu] ;向上 99 | cmp al,4 100 | jnz end 101 | mov ax,word[x] ;最上一行? 102 | cmp ax, 0 103 | jz u2r 104 | dec byte[x] 105 | jmp show 106 | u2r: 107 | mov byte[rdlu],1 ;改为向右 108 | inc byte[y] 109 | mov al,byte[char] 110 | cmp al,'Z' 111 | jz returntoa 112 | inc byte[char] 113 | jmp show 114 | 115 | returntoa: 116 | mov byte[char],'A' 117 | jmp show 118 | 119 | show: 120 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 121 | mov ax,word[x] 122 | mov bx,80 ; (80*x 123 | mul bx 124 | add ax,word[y] ; (80*x+y) 125 | mov bx,2 126 | mul bx ; ((80*x+y)*2) 127 | mov bp,ax 128 | mov ah,0ah ; 0000:黑底、1111:亮白字(默认值为07h) 129 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 130 | mov word[gs:bp],ax ; 显示字符的ASCII码值 131 | 132 | 133 | end: 134 | ret 135 | jmp $ 136 | 137 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/process2.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,200 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_ID: 25 | mov ah,0eh 26 | mov al,'g' 27 | mov word[gs:((80 * 7 + 56) * 2)], ax 28 | mov al,'o' 29 | mov word[gs:((80 * 7 + 57) * 2)], ax 30 | mov al,'o' 31 | mov word[gs:((80 * 7 + 58) * 2)], ax 32 | mov al,'d' 33 | mov word[gs:((80 * 7 + 59) * 2)], ax 34 | mov al,' ' 35 | mov word[gs:((80 * 7 + 60) * 2)], ax 36 | mov al,'d' 37 | mov word[gs:((80 * 7 + 61) * 2)], ax 38 | mov al,'a' 39 | mov word[gs:((80 * 7 + 62) * 2)], ax 40 | mov al,'y' 41 | mov word[gs:((80 * 7 + 63) * 2)], ax 42 | 43 | mov word[x],0 44 | mov word[y],40 45 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 46 | mov word[char],'A' 47 | 48 | loop1: 49 | dec word[count] ; 递减计数变量 50 | jnz loop1 ; >0:跳转; 51 | mov word[count],delay 52 | dec word[dcount] ; 递减计数变量 53 | jnz loop1 54 | call boxing 55 | mov word[count],delay 56 | mov word[dcount],ddelay 57 | jmp loop1 58 | 59 | jmp $ ; 死循环 60 | 61 | datadef: 62 | 63 | count dw delay ; 计时器计数变量,初值=delay 64 | dcount dw ddelay ; 计时器计数变量,初值=delay 65 | x dw 0 ; 当前字符显示位置的行号,0~24 66 | y dw 0 ; 当前字符显示位置的列号,0~79 67 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 68 | char db 'A' ; 当前显示字符 69 | 70 | 71 | boxing: 72 | 73 | right: 74 | mov al,byte[rdlu] ;右 75 | cmp al,1 76 | jnz down 77 | mov ax,word[y] ;最后一列? 78 | cmp ax, 79 79 | jz r2d 80 | inc byte[y] 81 | jmp show 82 | r2d: 83 | mov byte[rdlu],4 ;改为向上 84 | dec byte[x] 85 | jmp show 86 | 87 | down: 88 | mov al,byte[rdlu] ;向下 89 | cmp al,2 90 | jnz left 91 | mov ax,word[x] ;最后一行? 92 | cmp ax, 12 93 | jz d2l 94 | inc byte[x] 95 | jmp show 96 | d2l: 97 | mov byte[rdlu],1 ;改为向右 98 | inc byte[y] 99 | jmp show 100 | 101 | left: 102 | mov al,byte[rdlu] ;向左 103 | cmp al,3 104 | jnz up 105 | mov ax,word[y] ;最左一列? 106 | cmp ax, 40 107 | jz l2u 108 | dec byte[y] 109 | jmp show 110 | l2u: 111 | mov byte[rdlu],2 ;改为向下 112 | inc byte[x] 113 | jmp show 114 | 115 | up: 116 | mov al,byte[rdlu] ;向上 117 | cmp al,4 118 | jnz end 119 | mov ax,word[x] ;最上一行? 120 | cmp ax, 0 121 | jz u2r 122 | dec byte[x] 123 | jmp show 124 | u2r: 125 | mov byte[rdlu],3 ;改为向左 126 | dec byte[y] 127 | mov al,byte[char] 128 | cmp al,'Z' 129 | jz returntoa 130 | inc byte[char] 131 | jmp show 132 | 133 | returntoa: 134 | mov byte[char],'A' 135 | jmp show 136 | 137 | show: 138 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 139 | mov ax,word[x] 140 | mov bx,80 ; (80*x 141 | mul bx 142 | add ax,word[y] ; (80*x+y) 143 | mov bx,2 144 | mul bx ; ((80*x+y)*2) 145 | mov bp,ax 146 | mov ah,0bh ; 0000:黑底、1111:亮白字(默认值为07h) 147 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 148 | mov word[gs:bp],ax ; 显示字符的ASCII码值 149 | 150 | 151 | end: 152 | ret 153 | 154 | 155 | jmp $ 156 | 157 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 158 | ; 写入启动扇区的结束标志 159 | ;db 55h,0aah 160 | 161 | 162 | ;******************************************************************************************************** 163 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 164 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 165 | ;* 166 | ;******************************************************************************************************** 167 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/process3.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,300 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_LOVE: 25 | mov ah,0bh 26 | mov al,'I' 27 | mov word[gs:((80 * 19 + 15) * 2)], ax 28 | mov al,'L' 29 | mov word[gs:((80 * 19 + 17) * 2)], ax 30 | mov al,'O' 31 | mov word[gs:((80 * 19 + 18) * 2)], ax 32 | mov al,'V' 33 | mov word[gs:((80 * 19 + 19) * 2)], ax 34 | mov al,'E' 35 | mov word[gs:((80 * 19 + 20) * 2)], ax 36 | mov al,'O' 37 | mov word[gs:((80 * 19 + 22) * 2)], ax 38 | mov al,'S' 39 | mov word[gs:((80 * 19 + 23) * 2)], ax 40 | 41 | mov word[x],13 42 | mov word[y],0 43 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 44 | mov word[char],'A' 45 | 46 | loop1: 47 | dec word[count] ; 递减计数变量 48 | jnz loop1 ; >0:跳转; 49 | mov word[count],delay 50 | dec word[dcount] ; 递减计数变量 51 | jnz loop1 52 | call boxing 53 | mov word[count],delay 54 | mov word[dcount],ddelay 55 | jmp loop1 56 | 57 | jmp $ ; 死循环 58 | 59 | datadef: 60 | 61 | count dw delay ; 计时器计数变量,初值=delay 62 | dcount dw ddelay ; 计时器计数变量,初值=delay 63 | x dw 0 ; 当前字符显示位置的行号,0~24 64 | y dw 0 ; 当前字符显示位置的列号,0~79 65 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 66 | char db 'A' ; 当前显示字符 67 | 68 | 69 | boxing: 70 | 71 | right: 72 | mov al,byte[rdlu] ;右 73 | cmp al,1 74 | jnz down 75 | mov ax,word[y] ;最后一列? 76 | cmp ax, 39 77 | jz r2d 78 | inc byte[y] 79 | jmp show 80 | r2d: 81 | mov byte[rdlu],4 ;改为向上 82 | dec byte[x] 83 | jmp show 84 | 85 | down: 86 | mov al,byte[rdlu] ;向下 87 | cmp al,2 88 | jnz left 89 | mov ax,word[x] ;最后一行? 90 | cmp ax, 24 91 | jz d2l 92 | inc byte[x] 93 | jmp show 94 | d2l: 95 | mov byte[rdlu],1 ;改为向右 96 | inc byte[y] 97 | jmp show 98 | 99 | left: 100 | mov al,byte[rdlu] ;向左 101 | cmp al,3 102 | jnz up 103 | mov ax,word[y] ;最左一列? 104 | cmp ax,0 105 | jz l2u 106 | dec byte[y] 107 | jmp show 108 | l2u: 109 | mov byte[rdlu],2 ;改为向下 110 | inc byte[x] 111 | jmp show 112 | 113 | up: 114 | mov al,byte[rdlu] ;向上 115 | cmp al,4 116 | jnz end 117 | mov ax,word[x] ;最上一行? 118 | cmp ax,13 119 | jz u2r 120 | dec byte[x] 121 | jmp show 122 | u2r: 123 | mov byte[rdlu],3 ;改为向左 124 | dec byte[y] 125 | mov al,byte[char] 126 | cmp al,'Z' 127 | jz returntoa 128 | inc byte[char] 129 | jmp show 130 | 131 | returntoa: 132 | mov byte[char],'A' 133 | jmp show 134 | 135 | show: 136 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 137 | mov ax,word[x] 138 | mov bx,80 ; (80*x 139 | mul bx 140 | add ax,word[y] ; (80*x+y) 141 | mov bx,2 142 | mul bx ; ((80*x+y)*2) 143 | mov bp,ax 144 | mov ah,0ch ; 0000:黑底、1111:亮白字(默认值为07h) 145 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 146 | mov word[gs:bp],ax ; 显示字符的ASCII码值 147 | 148 | 149 | end: 150 | ret 151 | 152 | 153 | jmp $ 154 | 155 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 156 | ; 写入启动扇区的结束标志 157 | ;db 55h,0aah 158 | 159 | 160 | ;******************************************************************************************************** 161 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 162 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 163 | ;* 164 | ;******************************************************************************************************** 165 | -------------------------------------------------------------------------------- /Lab06/src/用户程序/process4.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | 14 | ;初始化段寄存器 15 | mov ax,400 ; AX = 0 16 | mov es,ax ; ES = 0 17 | mov ds,ax ; DS = CS 18 | mov ax,0B800h ; 文本窗口显存起始地址 19 | mov gs,ax ; GS = B800h 20 | mov word[count],delay 21 | mov word[dcount],ddelay 22 | 23 | mov word[x],13 24 | mov word[y],40 25 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 26 | mov word[char],'A' 27 | 28 | loop1: 29 | dec word[count] ; 递减计数变量 30 | jnz loop1 ; >0:跳转; 31 | mov word[count],delay 32 | dec word[dcount] ; 递减计数变量 33 | jnz loop1 34 | call boxing 35 | mov word[count],delay 36 | mov word[dcount],ddelay 37 | jmp loop1 38 | 39 | jmp $ ; 死循环 40 | 41 | datadef: 42 | 43 | count dw delay ; 计时器计数变量,初值=delay 44 | dcount dw ddelay ; 计时器计数变量,初值=delay 45 | x dw 13 ; 当前字符显示位置的行号,0~24 46 | y dw 40 ; 当前字符显示位置的列号,0~79 47 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 48 | char db 'A' ; 当前显示字符 49 | 50 | 51 | boxing: 52 | 53 | right: 54 | mov al,byte[rdlu] ;左-->右 55 | cmp al,1 56 | jnz down 57 | mov ax,word[y] ;最后一列? 58 | cmp ax, 79 59 | jz r2d 60 | inc byte[y] 61 | jmp show 62 | r2d: 63 | mov byte[rdlu],2 ;改为向下 64 | inc byte[x] 65 | jmp show 66 | 67 | down: 68 | mov al,byte[rdlu] ;向下 69 | cmp al,2 70 | jnz left 71 | mov ax,word[x] ;最后一行? 72 | cmp ax, 24 73 | jz d2l 74 | inc byte[x] 75 | jmp show 76 | d2l: 77 | mov byte[rdlu],3 ;改为向左 78 | dec byte[y] 79 | jmp show 80 | 81 | left: 82 | mov al,byte[rdlu] ;向左 83 | cmp al,3 84 | jnz up 85 | mov ax,word[y] ;最左一列? 86 | cmp ax, 40 87 | jz l2u 88 | dec byte[y] 89 | jmp show 90 | l2u: 91 | mov byte[rdlu],4 ;改为向 上 92 | dec byte[x] 93 | jmp show 94 | 95 | up: 96 | mov al,byte[rdlu] ;向上 97 | cmp al,4 98 | jnz end 99 | mov ax,word[x] ;最上一行? 100 | cmp ax, 13 101 | jz u2r 102 | dec byte[x] 103 | jmp show 104 | u2r: 105 | mov byte[rdlu],1 ;改为向右 106 | inc byte[y] 107 | mov al,byte[char] 108 | cmp al,'Z' 109 | jz returntoa 110 | inc byte[char] 111 | jmp show 112 | 113 | returntoa: 114 | mov byte[char],'A' 115 | jmp show 116 | 117 | show: 118 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 119 | mov ax,word[x] 120 | mov bx,80 ; (80*x 121 | mul bx 122 | add ax,word[y] ; (80*x+y) 123 | mov bx,2 124 | mul bx ; ((80*x+y)*2) 125 | mov bp,ax 126 | mov ah,0eh ; 0000:黑底、1111:亮白字(默认值为07h) 127 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 128 | mov word[gs:bp],ax ; 显示字符的ASCII码值 129 | 130 | 131 | end: 132 | ret 133 | 134 | 135 | jmp $ 136 | 137 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab07/README.md: -------------------------------------------------------------------------------- 1 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 2 | 3 | (1)实现fork()、wait()和exit()。 4 | 5 | (2)内核实现上面三系统调用,并在c库中封装相关的系统调用. 6 | 7 | (3)编写一个c语言程序,实现多进程合作的应用程序。 8 | 可以在下面的基础上完成:一个简单的应用程序例,父进程生成一个字符串,交给子进程统计其中字母的个数,然后在父进程中输出这一统计结果。 9 | 10 | -------------------------------------------------------------------------------- /Lab07/disk/Lab07.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab07/disk/Lab07.img -------------------------------------------------------------------------------- /Lab07/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab07/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab07/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | 6 | .8086 7 | _TEXT segment byte public 'CODE' 8 | assume cs:_TEXT 9 | DGROUP group _TEXT,_DATA,_BSS 10 | org 100h 11 | start: 12 | 13 | ;设置 21h 的中断 14 | xor ax,ax 15 | mov es,ax 16 | mov word ptr es:[33*4],offset MOS_21h ; 设置 21h 的偏移地址 17 | mov ax,cs 18 | mov word ptr es:[33*4+2],ax 19 | 20 | ;设置 33h 的中断 21 | xor ax,ax 22 | mov es,ax 23 | mov word ptr es:[51*4],offset MOS_33h ; 设置 33h 的偏移地址 24 | mov ax,cs 25 | mov word ptr es:[51*4+2],ax 26 | 27 | ;设置 34h 的中断 28 | xor ax,ax 29 | mov es,ax 30 | mov word ptr es:[52*4],offset MOS_34h ; 设置 34h 的偏移地址 31 | mov ax,cs 32 | mov word ptr es:[52*4+2],ax 33 | 34 | ;设置 35h 的中断 35 | xor ax,ax 36 | mov es,ax 37 | mov word ptr es:[53*4],offset MOS_35h ; 设置 35h 的偏移地址 38 | mov ax,cs 39 | mov word ptr es:[53*4+2],ax 40 | 41 | ;设置 36h 的中断 42 | xor ax,ax 43 | mov es,ax 44 | mov word ptr es:[54*4],offset MOS_36h ; 设置 36h 的偏移地址 45 | mov ax,cs 46 | mov word ptr es:[54*4+2],ax 47 | 48 | mov ax, cs 49 | mov ds, ax ; DS = CS 50 | mov es, ax ; ES = CS 51 | mov ss, ax ; SS = cs 52 | mov sp, 100h ; SP指向本段高端-4 53 | call near ptr _cmain ; 调用C语言程序cmain() 54 | jmp $ 55 | 56 | include function.asm ; 包含内核库过程 function.asm 57 | include services.asm ; 包含系统服务程序 58 | 59 | _TEXT ends 60 | _DATA segment word public 'DATA' 61 | _DATA ends 62 | _BSS segment word public 'BSS' 63 | _BSS ends 64 | end start 65 | 66 | -------------------------------------------------------------------------------- /Lab07/src/boot.asm: -------------------------------------------------------------------------------- 1 | ;程序源代码(boot.asm) 2 | ;用NASM汇编此程序 3 | ;nasm –f bin boot.asm –o boot.bin 4 | org 7c00h ; BIOS将把引导扇区加载到0:7C00处,并开始执行 5 | Start: 6 | mov ax, cs ; 置其他段寄存器值与CS相同 7 | mov ds, ax ; 数据段 8 | mov bp, Message ; BP=当前串的偏移地址 9 | mov ax, ds ; ES:BP = 串地址 10 | mov es, ax ; 置ES=DS 11 | mov cx, MessageLength ; CX = 串长(=9) 12 | mov ax, 1301h ; AH = 13h(功能号)、AL = 01h(光标置于串尾) 13 | mov bx, 0007h ; 页号为0(BH = 0) 黑底白字(BL = 07h) 14 | mov dh, 0 ; 行号=0 15 | mov dl, 0 ; 列号=0 16 | int 10h ; BIOS的10h功能:显示一行字符 17 | LoadKernal: 18 | ;读软盘或硬盘上的kernal到内存的ES:BX处: 19 | mov ax, SegOfKernal ; 段地址 ; 存放数据的内存基地址 20 | mov es,ax ; 设置段地址(不能直接mov es,段地址) 21 | mov bx, OffSetOfKernal ; 偏移地址; 存放数据的内存偏移地址 22 | mov ah,2 ; 功能号 23 | mov al, QTYofBlockOfKernal ; 扇区数 24 | mov dl,0 ; 驱动器号 ; 软盘为0,硬盘和U盘为80H 25 | mov dh,0 ; 磁头号 ; 起始编号为0 26 | mov ch,0 ; 柱面号 ; 起始编号为0 27 | mov cl,2 ; 起始扇区号 ; 起始编号为1 28 | int 13H ; 调用中断 29 | ;内核已加载到指定内存区域中 30 | jmp SegOfKernal : OffSetOfKernal 31 | jmp $ ;无限循环 32 | 33 | Message: 34 | db 'Loading MyOs kernal...' 35 | MessageLength equ ($-Message) ; 字符串长度 36 | OffSetOfKernal equ 100h ; 偏移量 37 | SegOfKernal equ 1000h ; 第二个64k内存的段地址 38 | QTYofBlockOfKernal equ 17 ; 内核占用扇区数 39 | times 510-($-$$) db 0 ; 用0填充引导扇区剩下的空间 40 | db 55h, 0aah ; 引导扇区结束标志 41 | 42 | -------------------------------------------------------------------------------- /Lab07/src/c_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;*************** ******************** 9 | ;* void _to_OUCH() * 10 | ;**************** ******************* 11 | ; 调用 21h 0号功能 12 | public _to_OUCH 13 | _to_OUCH proc 14 | push ax 15 | push bx 16 | push cx 17 | push dx 18 | push es 19 | 20 | call Clear 21 | 22 | mov ah,0 23 | int 21h 24 | 25 | call DelaySome 26 | 27 | pop ax 28 | mov es,ax 29 | pop dx 30 | pop cx 31 | pop bx 32 | pop ax 33 | ret 34 | _to_OUCH endp 35 | 36 | ;*************** ******************** 37 | ;* void _upper() * 38 | ;**************** ******************* 39 | ; 调用 21h 1号功能 40 | public _upper 41 | _upper proc 42 | push bp 43 | mov bp,sp 44 | push si 45 | mov si,word ptr [bp+4] ; 获得字符串首地址 46 | 47 | push ax 48 | push bx 49 | push cx 50 | push dx 51 | push es 52 | 53 | mov ah,1 54 | mov dx,si ; 把字符串首地址给 dx 55 | int 21h 56 | 57 | pop ax 58 | mov es,ax 59 | pop dx 60 | pop cx 61 | pop bx 62 | pop ax 63 | 64 | pop si 65 | pop bp 66 | ret 67 | _upper endp 68 | 69 | ;*************** ******************** 70 | ;* void _lower() * 71 | ;**************** ******************* 72 | ; 调用 21h 2号功能 73 | public _lower 74 | _lower proc 75 | push bp 76 | mov bp,sp 77 | push si 78 | mov si,word ptr [bp+4] ; 获得字符串首地址 79 | 80 | push ax 81 | push bx 82 | push cx 83 | push dx 84 | push es 85 | 86 | mov ah,2 87 | mov dx,si ; 把字符串首地址给 dx 88 | int 21h 89 | 90 | pop ax 91 | mov es,ax 92 | pop dx 93 | pop cx 94 | pop bx 95 | pop ax 96 | 97 | pop si 98 | pop bp 99 | ret 100 | _lower endp 101 | 102 | ;*************** ******************** 103 | ;* void _digital() * 104 | ;**************** ******************* 105 | ; 调用 21h 3号功能 106 | public _digital 107 | _digital proc 108 | push bp 109 | mov bp,sp 110 | push si 111 | mov si,word ptr [bp+4] ; 获得字符串首地址 112 | 113 | push bx 114 | push cx 115 | push dx 116 | push es 117 | 118 | mov ah,3 119 | mov dx,si ; 把字符串首地址给 dx 120 | int 21h 121 | 122 | pop bx 123 | mov es,bx 124 | pop dx 125 | pop cx 126 | pop bx 127 | 128 | pop si 129 | pop bp 130 | ret 131 | _digital endp 132 | 133 | ;*************** ******************** 134 | ;* void _convertToString() * 135 | ;**************** ******************* 136 | ; 调用 21h 4号功能 137 | public _convertToString 138 | _convertToString proc 139 | push bp 140 | mov bp,sp 141 | push si 142 | mov si,word ptr [bp+4] ; 获得传递进来的整数 143 | 144 | push bx 145 | push cx 146 | push dx 147 | push es 148 | 149 | mov ah,4 150 | mov bx,si ; 把整数给 dx 151 | int 21h 152 | 153 | pop bx 154 | mov es,bx 155 | pop dx 156 | pop cx 157 | pop bx 158 | 159 | pop si 160 | pop bp 161 | ret 162 | _convertToString endp 163 | 164 | ;*************** ******************** 165 | ;* void _display() * 166 | ;**************** ******************* 167 | ; 调用 21h 5号功能 168 | public _display 169 | _display proc 170 | push bp 171 | mov bp,sp 172 | push si 173 | 174 | push bx 175 | push cx 176 | push dx 177 | push es 178 | 179 | call Clear 180 | 181 | mov bx,word ptr [bp+4] ; 获得行号 182 | mov ax,word ptr [bp+6] ; 获得列号 183 | mov si,word ptr [bp+8] ; 获得字符串首地址 184 | 185 | 186 | mov ah,5 187 | mov dx,si ; dx 放字符串地址 188 | mov ch,bl ; ch 放行号 189 | mov cl,al ; cl 放列号 190 | int 21h 191 | 192 | call DelaySome 193 | call Clear 194 | 195 | pop bx 196 | mov es,bx 197 | pop dx 198 | pop cx 199 | pop bx 200 | 201 | pop si 202 | pop bp 203 | ret 204 | _display endp 205 | 206 | ;*************** ******************** 207 | ;* DelaySome * 208 | ;**************** ******************* 209 | ; 延迟 210 | DelaySome: ; 延迟一段时间 211 | mov cx,delayTime 212 | toDelay: 213 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 214 | mov cx,delayTime 215 | loop1:loop loop1 216 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 217 | loop toDelay 218 | ret 219 | 220 | Clear: ;清屏 221 | MOV AX,0003H 222 | INT 10H 223 | ret 224 | 225 | delayTime equ 40000 226 | t dw 0 227 | 228 | _TEXT ends 229 | _DATA segment word public 'DATA' 230 | _DATA ends 231 | _BSS segment word public 'BSS' 232 | _BSS ends 233 | end start 234 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | 11 | mov ah,0 12 | int 21h 13 | 14 | call DispStr ; 显示字符串 15 | call Delay 16 | call Clear 17 | int 33h 18 | int 34h 19 | int 35h 20 | int 36h 21 | call Delay 22 | ret 23 | 24 | Delay: 25 | mov cx,delayTime ;初始化 cx 为 5000 26 | toDelay: ;双重循环进行延迟,延迟时间为 5000*5000 27 | mov word[t],cx ;把 cx 的值保存到 t 中 28 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 29 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 30 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 31 | loop toDelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 32 | ret ; 段间返回 33 | 34 | DispStr: ; 显示字符串 35 | ; 显示字符串 (开始) 36 | mov ah,5 37 | mov dx,Msg ; dx 放字符串地址 38 | mov ch,5 ; ch 放行号 39 | mov cl,23 ; cl 放列号 40 | int 21h 41 | ; 显示字符串(结束) 42 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 43 | mov ah,13h ; 功能号 44 | mov al,1 ; 光标放到串尾 45 | mov bl,0dh ; 黑底品红字 46 | mov bh,0 ; 第0页 47 | mov dh,07h ; 第7行 48 | mov dl,18 ; 第28列 49 | mov bp,Tips ; BP=串地址 50 | mov cx,Length2 ; 串长 51 | int 10h ; 调用10H号中断 52 | ; 显示字符串2(结束) 53 | ret 54 | 55 | Clear: ;清屏 56 | mov ax,0003H ; 清屏属性 57 | int 10H ; 调用中断 58 | ret ; 返回 59 | 60 | delayTime equ 40000 61 | t dw 0 62 | Msg: ; 字符串 63 | db "Look! The 21h is still available....",0h 64 | Tips: ; 退出提示 65 | db "Please wait for the program to quit..." 66 | Length2: equ ($-Tips) ; 提示的长度 67 | 68 | 69 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 70 | ;db 55h,0aah ; 启动扇区的结束标志 71 | 72 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 一个运动的黄色 U 100 个往后擦除 2 | Init: ;程序初始化 3 | delayTime equ 6000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,199 88 | je quit 89 | cmp ax,100 90 | jnz next 91 | call change 92 | 93 | next: 94 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 95 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 96 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 97 | mul word[y] ;计算 160*y ,结果放在 ax 中 98 | mov word[t],ax ;把 ax 的值放到 t 99 | mov ax,word[x] ;把 x 放到 ax 100 | add ax,ax ;ax *= 2 101 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 102 | mov bx,ax ;置 bx 等于 ax ,即为 t 103 | mov al,byte[c] ;在 al 中放字符 'Z' 104 | mov ah,0eh ;在 ah 中放 0ch,表示黑底红字 105 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 106 | mov cx,delayTime ;初始化 cx 为 5000 107 | jmp delay ;跳转到 delay ,进行延迟 108 | 109 | 110 | change: 111 | mov byte[c],32 112 | cmp word[statex],0 113 | jnz cmp2 114 | mov word[statex],1 115 | jmp cmp3 116 | cmp2: 117 | mov word[statex],0 118 | cmp3: 119 | cmp word[statey],0 120 | jnz cmp4 121 | mov word[statey],1 122 | ret 123 | cmp4: 124 | mov word[statey],0 125 | ret 126 | 127 | Clear: ;清屏 128 | MOV AX,0003H 129 | INT 10H 130 | ret 131 | 132 | quit: 133 | ret 134 | 135 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 136 | mov word[t],cx ;把 cx 的值保存到 t 中 137 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 138 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 139 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 140 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 141 | jmp main ;无条件跳转至 main ,继续执行 142 | 143 | data: ;数据声明部分 144 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 145 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 146 | t dw 0 ;声明变量 t ,并初始化 t 为 0 147 | num dw 0 148 | c db 'U' 149 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 150 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 151 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 152 | ;db 55h,0aah 153 | 154 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/process1.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-05-2 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h ; 程序加载到100h,可用于生成COM 14 | 15 | ;初始化段寄存器 16 | xor ax,ax ; AX = 0 17 | mov ax,100 18 | mov es,ax ; ES = 0 19 | mov ds,ax ; DS = CS 20 | mov ax,0B800h ; 文本窗口显存起始地址 21 | mov gs,ax ; GS = B800h 22 | mov word[count],delay 23 | mov word[dcount],ddelay 24 | 25 | mov word[x],0 26 | mov word[y],0 27 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 28 | mov word[char],'A' 29 | 30 | loop1: 31 | dec word[count] ; 递减计数变量 32 | jnz loop1 ; >0:跳转; 33 | mov word[count],delay 34 | dec word[dcount] ; 递减计数变量 35 | jnz loop1 36 | call boxing 37 | mov word[count],delay 38 | mov word[dcount],ddelay 39 | jmp loop1 40 | 41 | jmp $ ; 死循环 42 | 43 | datadef: 44 | 45 | count dw delay ; 计时器计数变量,初值=delay 46 | dcount dw ddelay ; 计时器计数变量,初值=delay 47 | x dw 0 ; 当前字符显示位置的行号,0~24 48 | y dw 0 ; 当前字符显示位置的列号,0~79 49 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 50 | char db 'A' ; 当前显示字符 51 | 52 | 53 | boxing: 54 | 55 | right: 56 | mov al,byte[rdlu] ;左-->右 57 | cmp al,1 58 | jnz down 59 | mov ax,word[y] ;最后一列? 60 | cmp ax, 39 61 | jz r2d 62 | inc byte[y] 63 | jmp show 64 | r2d: 65 | mov byte[rdlu],2 ;改为向下 66 | inc byte[x] 67 | jmp show 68 | 69 | down: 70 | mov al,byte[rdlu] ;向下 71 | cmp al,2 72 | jnz left 73 | mov ax,word[x] ;最后一行? 74 | cmp ax, 12 75 | jz d2l 76 | inc byte[x] 77 | jmp show 78 | d2l: 79 | mov byte[rdlu],3 ;改为向左 80 | dec byte[y] 81 | jmp show 82 | 83 | left: 84 | mov al,byte[rdlu] ;向左 85 | cmp al,3 86 | jnz up 87 | mov ax,word[y] ;最左一列? 88 | cmp ax, 0 89 | jz l2u 90 | dec byte[y] 91 | jmp show 92 | l2u: 93 | mov byte[rdlu],4 ;改为向 上 94 | dec byte[x] 95 | jmp show 96 | 97 | up: 98 | mov al,byte[rdlu] ;向上 99 | cmp al,4 100 | jnz end 101 | mov ax,word[x] ;最上一行? 102 | cmp ax, 0 103 | jz u2r 104 | dec byte[x] 105 | jmp show 106 | u2r: 107 | mov byte[rdlu],1 ;改为向右 108 | inc byte[y] 109 | mov al,byte[char] 110 | cmp al,'Z' 111 | jz returntoa 112 | inc byte[char] 113 | jmp show 114 | 115 | returntoa: 116 | mov byte[char],'A' 117 | jmp show 118 | 119 | show: 120 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 121 | mov ax,word[x] 122 | mov bx,80 ; (80*x 123 | mul bx 124 | add ax,word[y] ; (80*x+y) 125 | mov bx,2 126 | mul bx ; ((80*x+y)*2) 127 | mov bp,ax 128 | mov ah,0ah ; 0000:黑底、1111:亮白字(默认值为07h) 129 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 130 | mov word[gs:bp],ax ; 显示字符的ASCII码值 131 | 132 | 133 | end: 134 | ret 135 | jmp $ 136 | 137 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/process2.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,200 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_ID: 25 | mov ah,0eh 26 | mov al,'g' 27 | mov word[gs:((80 * 7 + 56) * 2)], ax 28 | mov al,'o' 29 | mov word[gs:((80 * 7 + 57) * 2)], ax 30 | mov al,'o' 31 | mov word[gs:((80 * 7 + 58) * 2)], ax 32 | mov al,'d' 33 | mov word[gs:((80 * 7 + 59) * 2)], ax 34 | mov al,' ' 35 | mov word[gs:((80 * 7 + 60) * 2)], ax 36 | mov al,'d' 37 | mov word[gs:((80 * 7 + 61) * 2)], ax 38 | mov al,'a' 39 | mov word[gs:((80 * 7 + 62) * 2)], ax 40 | mov al,'y' 41 | mov word[gs:((80 * 7 + 63) * 2)], ax 42 | 43 | mov word[x],0 44 | mov word[y],40 45 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 46 | mov word[char],'A' 47 | 48 | loop1: 49 | dec word[count] ; 递减计数变量 50 | jnz loop1 ; >0:跳转; 51 | mov word[count],delay 52 | dec word[dcount] ; 递减计数变量 53 | jnz loop1 54 | call boxing 55 | mov word[count],delay 56 | mov word[dcount],ddelay 57 | jmp loop1 58 | 59 | jmp $ ; 死循环 60 | 61 | datadef: 62 | 63 | count dw delay ; 计时器计数变量,初值=delay 64 | dcount dw ddelay ; 计时器计数变量,初值=delay 65 | x dw 0 ; 当前字符显示位置的行号,0~24 66 | y dw 0 ; 当前字符显示位置的列号,0~79 67 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 68 | char db 'A' ; 当前显示字符 69 | 70 | 71 | boxing: 72 | 73 | right: 74 | mov al,byte[rdlu] ;右 75 | cmp al,1 76 | jnz down 77 | mov ax,word[y] ;最后一列? 78 | cmp ax, 79 79 | jz r2d 80 | inc byte[y] 81 | jmp show 82 | r2d: 83 | mov byte[rdlu],4 ;改为向上 84 | dec byte[x] 85 | jmp show 86 | 87 | down: 88 | mov al,byte[rdlu] ;向下 89 | cmp al,2 90 | jnz left 91 | mov ax,word[x] ;最后一行? 92 | cmp ax, 12 93 | jz d2l 94 | inc byte[x] 95 | jmp show 96 | d2l: 97 | mov byte[rdlu],1 ;改为向右 98 | inc byte[y] 99 | jmp show 100 | 101 | left: 102 | mov al,byte[rdlu] ;向左 103 | cmp al,3 104 | jnz up 105 | mov ax,word[y] ;最左一列? 106 | cmp ax, 40 107 | jz l2u 108 | dec byte[y] 109 | jmp show 110 | l2u: 111 | mov byte[rdlu],2 ;改为向下 112 | inc byte[x] 113 | jmp show 114 | 115 | up: 116 | mov al,byte[rdlu] ;向上 117 | cmp al,4 118 | jnz end 119 | mov ax,word[x] ;最上一行? 120 | cmp ax, 0 121 | jz u2r 122 | dec byte[x] 123 | jmp show 124 | u2r: 125 | mov byte[rdlu],3 ;改为向左 126 | dec byte[y] 127 | mov al,byte[char] 128 | cmp al,'Z' 129 | jz returntoa 130 | inc byte[char] 131 | jmp show 132 | 133 | returntoa: 134 | mov byte[char],'A' 135 | jmp show 136 | 137 | show: 138 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 139 | mov ax,word[x] 140 | mov bx,80 ; (80*x 141 | mul bx 142 | add ax,word[y] ; (80*x+y) 143 | mov bx,2 144 | mul bx ; ((80*x+y)*2) 145 | mov bp,ax 146 | mov ah,0bh ; 0000:黑底、1111:亮白字(默认值为07h) 147 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 148 | mov word[gs:bp],ax ; 显示字符的ASCII码值 149 | 150 | 151 | end: 152 | ret 153 | 154 | 155 | jmp $ 156 | 157 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 158 | ; 写入启动扇区的结束标志 159 | ;db 55h,0aah 160 | 161 | 162 | ;******************************************************************************************************** 163 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 164 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 165 | ;* 166 | ;******************************************************************************************************** 167 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/process3.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,300 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_LOVE: 25 | mov ah,0bh 26 | mov al,'I' 27 | mov word[gs:((80 * 19 + 15) * 2)], ax 28 | mov al,'L' 29 | mov word[gs:((80 * 19 + 17) * 2)], ax 30 | mov al,'O' 31 | mov word[gs:((80 * 19 + 18) * 2)], ax 32 | mov al,'V' 33 | mov word[gs:((80 * 19 + 19) * 2)], ax 34 | mov al,'E' 35 | mov word[gs:((80 * 19 + 20) * 2)], ax 36 | mov al,'O' 37 | mov word[gs:((80 * 19 + 22) * 2)], ax 38 | mov al,'S' 39 | mov word[gs:((80 * 19 + 23) * 2)], ax 40 | 41 | mov word[x],13 42 | mov word[y],0 43 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 44 | mov word[char],'A' 45 | 46 | loop1: 47 | dec word[count] ; 递减计数变量 48 | jnz loop1 ; >0:跳转; 49 | mov word[count],delay 50 | dec word[dcount] ; 递减计数变量 51 | jnz loop1 52 | call boxing 53 | mov word[count],delay 54 | mov word[dcount],ddelay 55 | jmp loop1 56 | 57 | jmp $ ; 死循环 58 | 59 | datadef: 60 | 61 | count dw delay ; 计时器计数变量,初值=delay 62 | dcount dw ddelay ; 计时器计数变量,初值=delay 63 | x dw 0 ; 当前字符显示位置的行号,0~24 64 | y dw 0 ; 当前字符显示位置的列号,0~79 65 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 66 | char db 'A' ; 当前显示字符 67 | 68 | 69 | boxing: 70 | 71 | right: 72 | mov al,byte[rdlu] ;右 73 | cmp al,1 74 | jnz down 75 | mov ax,word[y] ;最后一列? 76 | cmp ax, 39 77 | jz r2d 78 | inc byte[y] 79 | jmp show 80 | r2d: 81 | mov byte[rdlu],4 ;改为向上 82 | dec byte[x] 83 | jmp show 84 | 85 | down: 86 | mov al,byte[rdlu] ;向下 87 | cmp al,2 88 | jnz left 89 | mov ax,word[x] ;最后一行? 90 | cmp ax, 24 91 | jz d2l 92 | inc byte[x] 93 | jmp show 94 | d2l: 95 | mov byte[rdlu],1 ;改为向右 96 | inc byte[y] 97 | jmp show 98 | 99 | left: 100 | mov al,byte[rdlu] ;向左 101 | cmp al,3 102 | jnz up 103 | mov ax,word[y] ;最左一列? 104 | cmp ax,0 105 | jz l2u 106 | dec byte[y] 107 | jmp show 108 | l2u: 109 | mov byte[rdlu],2 ;改为向下 110 | inc byte[x] 111 | jmp show 112 | 113 | up: 114 | mov al,byte[rdlu] ;向上 115 | cmp al,4 116 | jnz end 117 | mov ax,word[x] ;最上一行? 118 | cmp ax,13 119 | jz u2r 120 | dec byte[x] 121 | jmp show 122 | u2r: 123 | mov byte[rdlu],3 ;改为向左 124 | dec byte[y] 125 | mov al,byte[char] 126 | cmp al,'Z' 127 | jz returntoa 128 | inc byte[char] 129 | jmp show 130 | 131 | returntoa: 132 | mov byte[char],'A' 133 | jmp show 134 | 135 | show: 136 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 137 | mov ax,word[x] 138 | mov bx,80 ; (80*x 139 | mul bx 140 | add ax,word[y] ; (80*x+y) 141 | mov bx,2 142 | mul bx ; ((80*x+y)*2) 143 | mov bp,ax 144 | mov ah,0ch ; 0000:黑底、1111:亮白字(默认值为07h) 145 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 146 | mov word[gs:bp],ax ; 显示字符的ASCII码值 147 | 148 | 149 | end: 150 | ret 151 | 152 | 153 | jmp $ 154 | 155 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 156 | ; 写入启动扇区的结束标志 157 | ;db 55h,0aah 158 | 159 | 160 | ;******************************************************************************************************** 161 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 162 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 163 | ;* 164 | ;******************************************************************************************************** 165 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/process4.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | 14 | ;初始化段寄存器 15 | mov ax,400 ; AX = 0 16 | mov es,ax ; ES = 0 17 | mov ds,ax ; DS = CS 18 | mov ax,0B800h ; 文本窗口显存起始地址 19 | mov gs,ax ; GS = B800h 20 | mov word[count],delay 21 | mov word[dcount],ddelay 22 | 23 | mov word[x],13 24 | mov word[y],40 25 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 26 | mov word[char],'A' 27 | 28 | loop1: 29 | dec word[count] ; 递减计数变量 30 | jnz loop1 ; >0:跳转; 31 | mov word[count],delay 32 | dec word[dcount] ; 递减计数变量 33 | jnz loop1 34 | call boxing 35 | mov word[count],delay 36 | mov word[dcount],ddelay 37 | jmp loop1 38 | 39 | jmp $ ; 死循环 40 | 41 | datadef: 42 | 43 | count dw delay ; 计时器计数变量,初值=delay 44 | dcount dw ddelay ; 计时器计数变量,初值=delay 45 | x dw 13 ; 当前字符显示位置的行号,0~24 46 | y dw 40 ; 当前字符显示位置的列号,0~79 47 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 48 | char db 'A' ; 当前显示字符 49 | 50 | 51 | boxing: 52 | 53 | right: 54 | mov al,byte[rdlu] ;左-->右 55 | cmp al,1 56 | jnz down 57 | mov ax,word[y] ;最后一列? 58 | cmp ax, 79 59 | jz r2d 60 | inc byte[y] 61 | jmp show 62 | r2d: 63 | mov byte[rdlu],2 ;改为向下 64 | inc byte[x] 65 | jmp show 66 | 67 | down: 68 | mov al,byte[rdlu] ;向下 69 | cmp al,2 70 | jnz left 71 | mov ax,word[x] ;最后一行? 72 | cmp ax, 24 73 | jz d2l 74 | inc byte[x] 75 | jmp show 76 | d2l: 77 | mov byte[rdlu],3 ;改为向左 78 | dec byte[y] 79 | jmp show 80 | 81 | left: 82 | mov al,byte[rdlu] ;向左 83 | cmp al,3 84 | jnz up 85 | mov ax,word[y] ;最左一列? 86 | cmp ax, 40 87 | jz l2u 88 | dec byte[y] 89 | jmp show 90 | l2u: 91 | mov byte[rdlu],4 ;改为向 上 92 | dec byte[x] 93 | jmp show 94 | 95 | up: 96 | mov al,byte[rdlu] ;向上 97 | cmp al,4 98 | jnz end 99 | mov ax,word[x] ;最上一行? 100 | cmp ax, 13 101 | jz u2r 102 | dec byte[x] 103 | jmp show 104 | u2r: 105 | mov byte[rdlu],1 ;改为向右 106 | inc byte[y] 107 | mov al,byte[char] 108 | cmp al,'Z' 109 | jz returntoa 110 | inc byte[char] 111 | jmp show 112 | 113 | returntoa: 114 | mov byte[char],'A' 115 | jmp show 116 | 117 | show: 118 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 119 | mov ax,word[x] 120 | mov bx,80 ; (80*x 121 | mul bx 122 | add ax,word[y] ; (80*x+y) 123 | mov bx,2 124 | mul bx ; ((80*x+y)*2) 125 | mov bp,ax 126 | mov ah,0eh ; 0000:黑底、1111:亮白字(默认值为07h) 127 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 128 | mov word[gs:bp],ax ; 显示字符的ASCII码值 129 | 130 | 131 | end: 132 | ret 133 | 134 | 135 | jmp $ 136 | 137 | times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/user.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | extrn _main:near 6 | 7 | .8086 8 | _TEXT segment byte public 'CODE' 9 | assume cs:_TEXT 10 | DGROUP group _TEXT,_DATA,_BSS 11 | org 100h 12 | start: 13 | 14 | mov ax, cs 15 | mov ds, ax ; DS = CS 16 | mov es, ax ; ES = CS 17 | mov ss, ax ; SS = cs 18 | mov sp, 100h ; SP指向本段高端-4 19 | call near ptr _main ; 调用C语言程序cmain() 20 | jmp $ 21 | 22 | _TEXT ends 23 | _DATA segment word public 'DATA' 24 | _DATA ends 25 | _BSS segment word public 'BSS' 26 | _BSS ends 27 | end start 28 | 29 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/user.c: -------------------------------------------------------------------------------- 1 | extern int fork(); 2 | extern int wait(); 3 | extern void exit(); 4 | 5 | #include "user_lib.h" 6 | 7 | char str[80] = "129djwqhdsajd128dw9i39ie93i8494urjoiew98kdkd"; 8 | int LetterNr = 0; 9 | 10 | void main() 11 | { 12 | int pid; 13 | char ch; 14 | print("In the user:before fork\r\n"); 15 | pid = fork(); 16 | print("In the user:after fork\r\n"); 17 | print("The pid is:");printInt(pid);print("\r\n"); 18 | if(pid == -1) exit(-1); 19 | if(pid) 20 | { 21 | print("In the user:before wait\r\n"); 22 | ch = wait(); 23 | print("In the user:after wait\r\n"); 24 | print("LetterNr="); 25 | printInt(LetterNr); 26 | print("\r\n"); 27 | exit(0); 28 | } 29 | else 30 | { 31 | print("In the user:sub process is running\r\n"); 32 | LetterNr = strlen(str); 33 | print("In the user:before exit\r\n"); 34 | exit(0); 35 | print("In the user:after exit\r\n"); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/user_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;************ ***************************** 9 | ; *SCOPY@ * 10 | ;****************** *********************** 11 | ; 实参为局部字符串带初始化异常问题的补钉程序 12 | public SCOPY@ 13 | SCOPY@ proc 14 | arg_0 = dword ptr 6 15 | arg_4 = dword ptr 0ah 16 | push bp 17 | mov bp,sp 18 | push si 19 | push di 20 | push ds 21 | lds si,[bp+arg_0] 22 | les di,[bp+arg_4] 23 | cld 24 | shr cx,1 25 | rep movsw 26 | adc cx,cx 27 | rep movsb 28 | pop ds 29 | pop di 30 | pop si 31 | pop bp 32 | retf 8 33 | SCOPY@ endp 34 | 35 | ;*************** ******************** 36 | ;* int _fork() * 37 | ;**************** ******************* 38 | ; 39 | public _fork 40 | _fork proc 41 | mov ah,6 42 | int 21h 43 | ret 44 | _fork endp 45 | 46 | ;*************** ******************** 47 | ;* int _wait() * 48 | ;**************** ******************* 49 | ; 50 | public _wait 51 | _wait proc 52 | mov ah,7 53 | int 21h 54 | ret 55 | _wait endp 56 | 57 | ;*************** ******************** 58 | ;* void _exit() * 59 | ;**************** ******************* 60 | ; 61 | public _exit 62 | _exit proc 63 | push bp 64 | mov bp,sp 65 | push bx 66 | 67 | mov ah,8 68 | mov bx,[bp+4] 69 | int 21h 70 | 71 | pop bx 72 | pop bp 73 | 74 | ret 75 | _exit endp 76 | 77 | ;*************** ******************** 78 | ;* void _cls() * 79 | ;**************** ******************* 80 | ; 清屏 81 | public _cls 82 | _cls proc 83 | mov ax,0003H 84 | int 10h ; 显示中断 85 | ret 86 | _cls endp 87 | 88 | ;**** *********************************** 89 | ;* void _PrintChar() * 90 | ;******* ******************************** 91 | ; 字符输出 92 | public _printChar 93 | _printChar proc 94 | push bp 95 | mov bp,sp 96 | push ax 97 | push bx 98 | ;*** 99 | mov al,[bp+4] 100 | mov bl,0 101 | mov ah,0eh 102 | int 10h 103 | ;*** 104 | pop bx 105 | pop ax 106 | mov sp,bp 107 | pop bp 108 | ret 109 | _printChar endp 110 | 111 | ;*********** **************************** 112 | ;* void _GetChar() * 113 | ;****************** ********************* 114 | ; 读入一个字符 115 | public _getChar 116 | _getChar proc 117 | mov ah,0 118 | int 16h 119 | ret 120 | _getChar endp 121 | 122 | ;*************** ******************** 123 | ;* void _delay() * 124 | ;**************** ******************* 125 | ; 延迟 126 | public _delay 127 | _delay proc 128 | push bp 129 | mov bp,sp 130 | push cx 131 | 132 | mov cx,word ptr[bp+4] 133 | delay_Continue: 134 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 135 | mov cx,word ptr [bp+4] 136 | delay_loop:loop delay_loop 137 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 138 | loop delay_Continue 139 | 140 | pop cx 141 | pop bp 142 | ret 143 | _delay endp 144 | 145 | t dw 0 146 | ;*************** ******************** 147 | ;* void _gettime() * 148 | ;**************** ******************* 149 | ; 获取时间 150 | public _backspace 151 | _backspace proc 152 | push ax 153 | push bx 154 | push cx 155 | push dx 156 | 157 | ;读光标位置,(dh,dl) = (行,列) 158 | mov bh,0 159 | mov ah,3h 160 | int 10h 161 | 162 | add dl,-1 163 | 164 | ;设置光标位置(dh,dl) = (行,列) 165 | mov bh,0 166 | mov ah,2h 167 | int 10h 168 | 169 | mov al,' ' 170 | mov bl,1 171 | mov ah,0eh 172 | int 10h 173 | 174 | ;设置光标位置(dh,dl) = (行,列) 175 | mov bh,0 176 | mov ah,2h 177 | int 10h 178 | 179 | pop dx 180 | pop cx 181 | pop bx 182 | pop ax 183 | ret 184 | _backspace endp 185 | 186 | 187 | _TEXT ends 188 | _DATA segment word public 'DATA' 189 | _DATA ends 190 | _BSS segment word public 'BSS' 191 | _BSS ends 192 | end start 193 | -------------------------------------------------------------------------------- /Lab07/src/用户程序/user_lib.h: -------------------------------------------------------------------------------- 1 | extern void cls(); 2 | extern char getchar(); 3 | extern void delay(int t); 4 | extern void printchar(); 5 | extern void backspace(); 6 | 7 | char input[100],output[100],t_char[100]; 8 | 9 | void reverse(char str[],int len) 10 | { 11 | /* 12 | * 将字符串反转 13 | */ 14 | int i; 15 | for(i = 0;i < len;++i) 16 | { 17 | t_char[i] = str[len-i-1]; 18 | } 19 | for(i = 0;i < len;++i) 20 | { 21 | str[i] = t_char[i]; 22 | } 23 | } 24 | 25 | int strlen(char str[]) 26 | { 27 | /* 28 | * 获取字符串长度 29 | */ 30 | int i = 0; 31 | while(str[i] != '\0') 32 | { 33 | i++; 34 | } 35 | return i; 36 | } 37 | 38 | void print(char *p) 39 | { 40 | /* 41 | * 输出字符串 p 42 | */ 43 | while(*p != '\0') 44 | { 45 | printChar(*p); 46 | p++; 47 | } 48 | } 49 | 50 | int getline(char arr[],int maxLen) 51 | { 52 | /* 53 | * 读取用户输入的一行 54 | */ 55 | 56 | int i = 0; 57 | char in; 58 | if(maxLen == 0) 59 | { 60 | return 0; 61 | } 62 | in = getchar(); 63 | while(in != '\n'&& in != '\r') 64 | { 65 | /* 66 | * 判断是不是回车键 67 | */ 68 | int k = in; 69 | if(k == 8) 70 | { 71 | /* 72 | * 判断是不是退格键 73 | */ 74 | i--; 75 | backspace(); 76 | in = getchar(); 77 | continue; 78 | } 79 | printChar(in); 80 | arr[i++] = in; 81 | if(i == maxLen) 82 | { 83 | /* 84 | * 是否达到允许输入的最大长度 85 | */ 86 | arr[i] = '\0'; 87 | printChar('\n'); 88 | return 0; 89 | } 90 | in = getchar(); 91 | } 92 | arr[i] = '\0'; 93 | print("\n\r"); 94 | return 1; 95 | } 96 | 97 | void printInt(int ans) 98 | { 99 | /* 100 | * 打印一个整数到屏幕 101 | */ 102 | int i = 0; 103 | if(ans == 0) 104 | { 105 | output[0] = '0'; 106 | i++; 107 | } 108 | while(ans) 109 | { 110 | int t = ans%10; 111 | output[i++] = '0'+t; 112 | ans/=10; 113 | } 114 | reverse(output,i); 115 | output[i] = '\0'; 116 | print(output); 117 | } 118 | -------------------------------------------------------------------------------- /Lab08/README.md: -------------------------------------------------------------------------------- 1 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 2 | 3 | (1) 实现信号量机制。 4 | 5 | (2) 内核实现信号量机制后,在c库中封装相关的系统调用. 6 | 7 | (3) 编写一个c语言程序,实现有限缓冲的生产者-消费者模型的应用程序。 8 | 9 | 编译连接你编写的用户程序,产生一个com文件,放进程原型操作系统映像盘中。 10 | 11 | -------------------------------------------------------------------------------- /Lab08/disk/Lab08.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab08/disk/Lab08.img -------------------------------------------------------------------------------- /Lab08/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab08/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab08/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | 6 | .8086 7 | _TEXT segment byte public 'CODE' 8 | assume cs:_TEXT 9 | DGROUP group _TEXT,_DATA,_BSS 10 | org 100h 11 | start: 12 | 13 | ;设置 21h 的中断 14 | xor ax,ax 15 | mov es,ax 16 | mov word ptr es:[33*4],offset MOS_21h ; 设置 21h 的偏移地址 17 | mov ax,cs 18 | mov word ptr es:[33*4+2],ax 19 | 20 | ;设置 33h 的中断 21 | xor ax,ax 22 | mov es,ax 23 | mov word ptr es:[51*4],offset MOS_33h ; 设置 33h 的偏移地址 24 | mov ax,cs 25 | mov word ptr es:[51*4+2],ax 26 | 27 | ;设置 34h 的中断 28 | xor ax,ax 29 | mov es,ax 30 | mov word ptr es:[52*4],offset MOS_34h ; 设置 34h 的偏移地址 31 | mov ax,cs 32 | mov word ptr es:[52*4+2],ax 33 | 34 | ;设置 35h 的中断 35 | xor ax,ax 36 | mov es,ax 37 | mov word ptr es:[53*4],offset MOS_35h ; 设置 35h 的偏移地址 38 | mov ax,cs 39 | mov word ptr es:[53*4+2],ax 40 | 41 | ;设置 36h 的中断 42 | xor ax,ax 43 | mov es,ax 44 | mov word ptr es:[54*4],offset MOS_36h ; 设置 36h 的偏移地址 45 | mov ax,cs 46 | mov word ptr es:[54*4+2],ax 47 | 48 | mov ax, cs 49 | mov ds, ax ; DS = CS 50 | mov es, ax ; ES = CS 51 | mov ss, ax ; SS = cs 52 | mov sp, 100h ; SP指向本段高端-4 53 | call near ptr _cmain ; 调用C语言程序cmain() 54 | jmp $ 55 | 56 | include function.asm ; 包含内核库过程 function.asm 57 | include services.asm ; 包含系统服务程序 58 | include file.asm 59 | 60 | _TEXT ends 61 | _DATA segment word public 'DATA' 62 | _DATA ends 63 | _BSS segment word public 'BSS' 64 | _BSS ends 65 | end start 66 | 67 | -------------------------------------------------------------------------------- /Lab08/src/boot.asm: -------------------------------------------------------------------------------- 1 | org 7c00h ; 加载到 0:7C00 处 2 | jmp short LABEL_START ; 跳转到代码起始处 3 | nop ; 这个nop(无操作指令)不可少(占位字节) 4 | 5 | ; 下面是 FAT12 磁盘的头(BPB+EBPB,占51B) 6 | BS_OEMName DB 'MyOS 1.0' ; OEM String, 必须 8 个字节(不足补空格) 7 | BPB_BytsPerSec DW 512 ; 每扇区字节数 8 | BPB_SecPerClus DB 1 ; 每簇多少扇区 9 | BPB_RsvdSecCnt DW 1 ; Boot记录占用多少扇区 10 | BPB_NumFATs DB 2 ; 共有多少 FAT 表 11 | BPB_RootEntCnt DW 224 ; 根目录文件数最大值 12 | BPB_TotSec16 DW 2880 ; 逻辑扇区总数 13 | BPB_Media DB 0xF0 ; 介质描述符 14 | BPB_FATSz16 DW 9 ; 每FAT扇区数 15 | BPB_SecPerTrk DW 18 ; 每磁道扇区数 16 | BPB_NumHeads DW 2 ; 磁头数(面数) 17 | BPB_HiddSec DD 0 ; 隐藏扇区数 18 | BPB_TotSec32 DD 0 ; BPB_TotSec16为0时这个值记录扇区数 19 | BS_DrvNum DB 0 ; 中断 13h 的驱动器号 20 | BS_Reserved1 DB 0 ; 未使用 21 | BS_BootSig DB 29h ; 扩展引导标记 (29h) 22 | BS_VolID DD 12345678h; 卷序列号 23 | BS_VolLab DB 'MyOS System'; 卷标, 必须 11 个字节(不足补空格) 24 | BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节(不足补空格) 25 | 26 | LABEL_START: 27 | mov ax, cs ; 置DS和ES=CS 28 | mov ds, ax 29 | mov es, ax 30 | call ScrollPg ; 向上滚动显示页 31 | call DispStr ; 调用显示字符串例程 32 | jmp $ ; 无限循环 33 | 34 | ScrollPg: ; 清屏例程 35 | mov ah, 6 ; 功能号 36 | mov al, 0 ; 滚动的文本行数(0=整个窗口) 37 | mov bh,0fh ; 设置插入空行的字符颜色为黑底亮白字 38 | mov cx, 0 ; 窗口左上角的行号=CH、列号=CL 39 | mov dh, 24 ; 窗口右下角的行号 40 | mov dl, 79 ; 窗口右下角的列号 41 | int 10h ; 显示中断 42 | ret 43 | 44 | DispStr: 45 | mov ah,13h ; BIOS中断的功能号(显示字符串) 46 | mov al,1 ; 光标放到串尾 47 | mov bh,0 ; 页号=0 48 | mov bl,0ch ; 字符颜色=黑底亮红字 49 | mov cx,16 ; 串长=16 50 | mov dx,0 ; 显示串的起始位置(0,0):DH=行号、DL=列号 51 | mov bp,BootMsg ; ES:BP=串地址 52 | int 10h ; 调用10H号显示中断 53 | ret ; 从例程返回 54 | 55 | BootMsg: 56 | db "Hello, OS world!" ; 显示用字符串 57 | times 510-($-$$) db 0 ; 用0填充剩下的扇区空间(软盘无分区表) 58 | db 55h, 0aah ; 引导扇区结束标志 59 | 60 | ; 填充两个FAT表的头两个项(每个FAT占9个扇区) 61 | db 0f0h, 0ffh, 0ffh ; 介质描述符(F0h)和Fh、结束簇标志项FFFh 62 | times 512*9-3 db 0 ; 用0填充FAT#1剩下的空间 63 | db 0f0h, 0ffh, 0ffh ; 介质描述符(F0h)和Fh、结束簇标志项FFFh 64 | times 512*9-3 db 0 ; 用0填充FAT#2剩下的空间 65 | ; 根目录中的卷标条目 66 | db 'MyOS System' ; 卷标, 必须 11 个字节(不足补空格) 67 | db 8 ; 文件属性值(卷标条目的为08h) 68 | dw 0,0,0,0,0 ; 10个保留字节 69 | dw 0,426Eh ; 创建时间,设为2013年3月14日0时0分0秒 70 | dw 0 ; 开始簇号(卷标条目的必需为0) 71 | dd 0 ; 文件大小(也设为0) 72 | 73 | 74 | -------------------------------------------------------------------------------- /Lab08/src/c_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;*************** ******************** 9 | ;* void _to_OUCH() * 10 | ;**************** ******************* 11 | ; 调用 21h 0号功能 12 | public _to_OUCH 13 | _to_OUCH proc 14 | push ax 15 | push bx 16 | push cx 17 | push dx 18 | push es 19 | 20 | call Clear 21 | 22 | mov ah,0 23 | int 21h 24 | 25 | call DelaySome 26 | 27 | pop ax 28 | mov es,ax 29 | pop dx 30 | pop cx 31 | pop bx 32 | pop ax 33 | ret 34 | _to_OUCH endp 35 | 36 | ;*************** ******************** 37 | ;* void _upper() * 38 | ;**************** ******************* 39 | ; 调用 21h 1号功能 40 | public _upper 41 | _upper proc 42 | push bp 43 | mov bp,sp 44 | push si 45 | mov si,word ptr [bp+4] ; 获得字符串首地址 46 | 47 | push ax 48 | push bx 49 | push cx 50 | push dx 51 | push es 52 | 53 | mov ah,1 54 | mov dx,si ; 把字符串首地址给 dx 55 | int 21h 56 | 57 | pop ax 58 | mov es,ax 59 | pop dx 60 | pop cx 61 | pop bx 62 | pop ax 63 | 64 | pop si 65 | pop bp 66 | ret 67 | _upper endp 68 | 69 | ;*************** ******************** 70 | ;* void _lower() * 71 | ;**************** ******************* 72 | ; 调用 21h 2号功能 73 | public _lower 74 | _lower proc 75 | push bp 76 | mov bp,sp 77 | push si 78 | mov si,word ptr [bp+4] ; 获得字符串首地址 79 | 80 | push ax 81 | push bx 82 | push cx 83 | push dx 84 | push es 85 | 86 | mov ah,2 87 | mov dx,si ; 把字符串首地址给 dx 88 | int 21h 89 | 90 | pop ax 91 | mov es,ax 92 | pop dx 93 | pop cx 94 | pop bx 95 | pop ax 96 | 97 | pop si 98 | pop bp 99 | ret 100 | _lower endp 101 | 102 | ;*************** ******************** 103 | ;* void _digital() * 104 | ;**************** ******************* 105 | ; 调用 21h 3号功能 106 | public _digital 107 | _digital proc 108 | push bp 109 | mov bp,sp 110 | push si 111 | mov si,word ptr [bp+4] ; 获得字符串首地址 112 | 113 | push bx 114 | push cx 115 | push dx 116 | push es 117 | 118 | mov ah,3 119 | mov dx,si ; 把字符串首地址给 dx 120 | int 21h 121 | 122 | pop bx 123 | mov es,bx 124 | pop dx 125 | pop cx 126 | pop bx 127 | 128 | pop si 129 | pop bp 130 | ret 131 | _digital endp 132 | 133 | ;*************** ******************** 134 | ;* void _convertToString() * 135 | ;**************** ******************* 136 | ; 调用 21h 4号功能 137 | public _convertToString 138 | _convertToString proc 139 | push bp 140 | mov bp,sp 141 | push si 142 | mov si,word ptr [bp+4] ; 获得传递进来的整数 143 | 144 | push bx 145 | push cx 146 | push dx 147 | push es 148 | 149 | mov ah,4 150 | mov bx,si ; 把整数给 dx 151 | int 21h 152 | 153 | pop bx 154 | mov es,bx 155 | pop dx 156 | pop cx 157 | pop bx 158 | 159 | pop si 160 | pop bp 161 | ret 162 | _convertToString endp 163 | 164 | ;*************** ******************** 165 | ;* void _display() * 166 | ;**************** ******************* 167 | ; 调用 21h 5号功能 168 | public _display 169 | _display proc 170 | push bp 171 | mov bp,sp 172 | push si 173 | 174 | push bx 175 | push cx 176 | push dx 177 | push es 178 | 179 | call Clear 180 | 181 | mov bx,word ptr [bp+4] ; 获得行号 182 | mov ax,word ptr [bp+6] ; 获得列号 183 | mov si,word ptr [bp+8] ; 获得字符串首地址 184 | 185 | 186 | mov ah,5 187 | mov dx,si ; dx 放字符串地址 188 | mov ch,bl ; ch 放行号 189 | mov cl,al ; cl 放列号 190 | int 21h 191 | 192 | call DelaySome 193 | call Clear 194 | 195 | pop bx 196 | mov es,bx 197 | pop dx 198 | pop cx 199 | pop bx 200 | 201 | pop si 202 | pop bp 203 | ret 204 | _display endp 205 | 206 | ;*************** ******************** 207 | ;* DelaySome * 208 | ;**************** ******************* 209 | ; 延迟 210 | DelaySome: ; 延迟一段时间 211 | mov cx,delayTime 212 | toDelay: 213 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 214 | mov cx,delayTime 215 | loop1:loop loop1 216 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 217 | loop toDelay 218 | ret 219 | 220 | Clear: ;清屏 221 | MOV AX,0003H 222 | INT 10H 223 | ret 224 | 225 | delayTime equ 40000 226 | t dw 0 227 | 228 | _TEXT ends 229 | _DATA segment word public 'DATA' 230 | _DATA ends 231 | _BSS segment word public 'BSS' 232 | _BSS ends 233 | end start 234 | -------------------------------------------------------------------------------- /Lab08/src/sema.h: -------------------------------------------------------------------------------- 1 | #define NrSemaphore 10 2 | #define Nr_PCB 10 3 | 4 | typedef struct SemaphoreType 5 | { 6 | int count; 7 | int blocked_PCB[Nr_PCB]; 8 | int used,front,tail; 9 | }SemaphoreType; 10 | 11 | SemaphoreType semaphoreQueue[NrSemaphore]; 12 | 13 | int semaGet(int value) 14 | { 15 | int i = 0; 16 | /* 找到第一个未使用的信号量 */ 17 | while(semaphoreQueue[i].used == 1 && i < NrSemaphore) 18 | { 19 | i++; 20 | } 21 | /* 检测合法性 */ 22 | if(i < NrSemaphore) 23 | { 24 | /*初始操作*/ 25 | semaphoreQueue[i].used = 1; 26 | semaphoreQueue[i].count = value; 27 | semaphoreQueue[i].front = 0; 28 | semaphoreQueue[i].tail = 0; 29 | /*print("kernal:semGet ");printInt(i);print(" ");printInt(semaphoreQueue[i].count);print("\r\n");*/ 30 | PCB_Queue[current_PCB].regImg.AX = i; 31 | PCB_Restore(); 32 | return i; 33 | } 34 | else 35 | { 36 | /* 非法情况 */ 37 | PCB_Queue[current_PCB].regImg.AX = -1; 38 | PCB_Restore(); 39 | return -1; 40 | } 41 | } 42 | 43 | int semaFree(int s) 44 | { 45 | /* 释放信号量 */ 46 | semaphoreQueue[s].used = 0; 47 | } 48 | 49 | 50 | /* 把进程加入对应信号量的阻塞队列 */ 51 | void semaBlock(int s) 52 | { 53 | /*print("kernal:the process ");printInt(current_PCB);print(" be blocked by P in s ");printInt(s);print("\r\n");*/ 54 | PCB_Queue[current_PCB].status = PCB_BLOCKED; 55 | if((semaphoreQueue[s].tail + 1)%Nr_PCB == semaphoreQueue[s].front) 56 | { 57 | /* 阻塞队列满 */ 58 | print("kernal:too much blocked process\r\n"); 59 | return; 60 | } 61 | /* 进程号放到队尾 */ 62 | semaphoreQueue[s].blocked_PCB[semaphoreQueue[s].tail] = current_PCB; 63 | /* 队尾指针移动 */ 64 | semaphoreQueue[s].tail = (semaphoreQueue[s].tail + 1)%Nr_PCB; 65 | } 66 | 67 | /* 从阻塞队列唤醒一个进程 */ 68 | void semaWakeUp(int s) 69 | { 70 | int t; 71 | if(semaphoreQueue[s].tail == semaphoreQueue[s].front) 72 | { 73 | /* 队空 */ 74 | print("No blocked process to wake up!\r\n"); 75 | return ; 76 | } 77 | /* 队头进程变为就绪态 */ 78 | t = semaphoreQueue[s].blocked_PCB[semaphoreQueue[s].front]; 79 | /*print("kernal:the process ");printInt(t);print(" be wake up by V in s ");printInt(s);print("\r\n");*/ 80 | PCB_Queue[t].status = PCB_READY; 81 | /* 队头指针移动 */ 82 | semaphoreQueue[s].front = (semaphoreQueue[s].front + 1)%Nr_PCB; 83 | return; 84 | } 85 | 86 | /* P 操作 */ 87 | void semaP(int s) 88 | { 89 | semaphoreQueue[s].count--; 90 | if(semaphoreQueue[s].count < 0) 91 | { 92 | /* count 小于 0 要阻塞 */ 93 | semaBlock(s); 94 | schedule(); 95 | } 96 | PCB_Restore(); 97 | } 98 | 99 | /* V 操作 */ 100 | void semaV(int s) 101 | { 102 | semaphoreQueue[s].count++; 103 | if(semaphoreQueue[s].count <= 0) 104 | { 105 | /* count 小于等于 0 要唤醒一个阻塞进程 */ 106 | semaWakeUp(s); 107 | schedule(); 108 | } 109 | PCB_Restore(); 110 | } 111 | 112 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | 11 | mov ah,0 12 | int 21h 13 | 14 | call DispStr ; 显示字符串 15 | call Delay 16 | call Clear 17 | int 33h 18 | int 34h 19 | int 35h 20 | int 36h 21 | call Delay 22 | ret 23 | 24 | Delay: 25 | mov cx,delayTime ;初始化 cx 为 5000 26 | toDelay: ;双重循环进行延迟,延迟时间为 5000*5000 27 | mov word[t],cx ;把 cx 的值保存到 t 中 28 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 29 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 30 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 31 | loop toDelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 32 | ret ; 段间返回 33 | 34 | DispStr: ; 显示字符串 35 | ; 显示字符串 (开始) 36 | mov ah,5 37 | mov dx,Msg ; dx 放字符串地址 38 | mov ch,5 ; ch 放行号 39 | mov cl,23 ; cl 放列号 40 | int 21h 41 | ; 显示字符串(结束) 42 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 43 | mov ah,13h ; 功能号 44 | mov al,1 ; 光标放到串尾 45 | mov bl,0dh ; 黑底品红字 46 | mov bh,0 ; 第0页 47 | mov dh,07h ; 第7行 48 | mov dl,18 ; 第28列 49 | mov bp,Tips ; BP=串地址 50 | mov cx,Length2 ; 串长 51 | int 10h ; 调用10H号中断 52 | ; 显示字符串2(结束) 53 | ret 54 | 55 | Clear: ;清屏 56 | mov ax,0003H ; 清屏属性 57 | int 10H ; 调用中断 58 | ret ; 返回 59 | 60 | delayTime equ 40000 61 | t dw 0 62 | Msg: ; 字符串 63 | db "Look! The 21h is still available....",0h 64 | Tips: ; 退出提示 65 | db "Please wait for the program to quit..." 66 | Length2: equ ($-Tips) ; 提示的长度 67 | 68 | 69 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 70 | ;db 55h,0aah ; 启动扇区的结束标志 71 | 72 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 一个运动的黄色 U 100 个往后擦除 2 | Init: ;程序初始化 3 | delayTime equ 6000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,199 88 | je quit 89 | cmp ax,100 90 | jnz next 91 | call change 92 | 93 | next: 94 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 95 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 96 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 97 | mul word[y] ;计算 160*y ,结果放在 ax 中 98 | mov word[t],ax ;把 ax 的值放到 t 99 | mov ax,word[x] ;把 x 放到 ax 100 | add ax,ax ;ax *= 2 101 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 102 | mov bx,ax ;置 bx 等于 ax ,即为 t 103 | mov al,byte[c] ;在 al 中放字符 'Z' 104 | mov ah,0eh ;在 ah 中放 0ch,表示黑底红字 105 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 106 | mov cx,delayTime ;初始化 cx 为 5000 107 | jmp delay ;跳转到 delay ,进行延迟 108 | 109 | 110 | change: 111 | mov byte[c],32 112 | cmp word[statex],0 113 | jnz cmp2 114 | mov word[statex],1 115 | jmp cmp3 116 | cmp2: 117 | mov word[statex],0 118 | cmp3: 119 | cmp word[statey],0 120 | jnz cmp4 121 | mov word[statey],1 122 | ret 123 | cmp4: 124 | mov word[statey],0 125 | ret 126 | 127 | Clear: ;清屏 128 | MOV AX,0003H 129 | INT 10H 130 | ret 131 | 132 | quit: 133 | ret 134 | 135 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 136 | mov word[t],cx ;把 cx 的值保存到 t 中 137 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 138 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 139 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 140 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 141 | jmp main ;无条件跳转至 main ,继续执行 142 | 143 | data: ;数据声明部分 144 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 145 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 146 | t dw 0 ;声明变量 t ,并初始化 t 为 0 147 | num dw 0 148 | c db 'U' 149 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 150 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 151 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 152 | ;db 55h,0aah 153 | 154 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/process1.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-05-2 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h ; 程序加载到100h,可用于生成COM 14 | 15 | ;初始化段寄存器 16 | xor ax,ax ; AX = 0 17 | mov ax,100 18 | mov es,ax ; ES = 0 19 | mov ds,ax ; DS = CS 20 | mov ax,0B800h ; 文本窗口显存起始地址 21 | mov gs,ax ; GS = B800h 22 | mov word[count],delay 23 | mov word[dcount],ddelay 24 | 25 | mov word[x],0 26 | mov word[y],0 27 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 28 | mov word[char],'A' 29 | 30 | loop1: 31 | dec word[count] ; 递减计数变量 32 | jnz loop1 ; >0:跳转; 33 | mov word[count],delay 34 | dec word[dcount] ; 递减计数变量 35 | jnz loop1 36 | call boxing 37 | mov word[count],delay 38 | mov word[dcount],ddelay 39 | jmp loop1 40 | 41 | jmp $ ; 死循环 42 | 43 | datadef: 44 | 45 | count dw delay ; 计时器计数变量,初值=delay 46 | dcount dw ddelay ; 计时器计数变量,初值=delay 47 | x dw 0 ; 当前字符显示位置的行号,0~24 48 | y dw 0 ; 当前字符显示位置的列号,0~79 49 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 50 | char db 'A' ; 当前显示字符 51 | 52 | 53 | boxing: 54 | 55 | right: 56 | mov al,byte[rdlu] ;左-->右 57 | cmp al,1 58 | jnz down 59 | mov ax,word[y] ;最后一列? 60 | cmp ax, 39 61 | jz r2d 62 | inc byte[y] 63 | jmp show 64 | r2d: 65 | mov byte[rdlu],2 ;改为向下 66 | inc byte[x] 67 | jmp show 68 | 69 | down: 70 | mov al,byte[rdlu] ;向下 71 | cmp al,2 72 | jnz left 73 | mov ax,word[x] ;最后一行? 74 | cmp ax, 12 75 | jz d2l 76 | inc byte[x] 77 | jmp show 78 | d2l: 79 | mov byte[rdlu],3 ;改为向左 80 | dec byte[y] 81 | jmp show 82 | 83 | left: 84 | mov al,byte[rdlu] ;向左 85 | cmp al,3 86 | jnz up 87 | mov ax,word[y] ;最左一列? 88 | cmp ax, 0 89 | jz l2u 90 | dec byte[y] 91 | jmp show 92 | l2u: 93 | mov byte[rdlu],4 ;改为向 上 94 | dec byte[x] 95 | jmp show 96 | 97 | up: 98 | mov al,byte[rdlu] ;向上 99 | cmp al,4 100 | jnz end 101 | mov ax,word[x] ;最上一行? 102 | cmp ax, 0 103 | jz u2r 104 | dec byte[x] 105 | jmp show 106 | u2r: 107 | mov byte[rdlu],1 ;改为向右 108 | inc byte[y] 109 | mov al,byte[char] 110 | cmp al,'Z' 111 | jz returntoa 112 | inc byte[char] 113 | jmp show 114 | 115 | returntoa: 116 | mov byte[char],'A' 117 | jmp show 118 | 119 | show: 120 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 121 | mov ax,word[x] 122 | mov bx,80 ; (80*x 123 | mul bx 124 | add ax,word[y] ; (80*x+y) 125 | mov bx,2 126 | mul bx ; ((80*x+y)*2) 127 | mov bp,ax 128 | mov ah,0ah ; 0000:黑底、1111:亮白字(默认值为07h) 129 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 130 | mov word[gs:bp],ax ; 显示字符的ASCII码值 131 | 132 | 133 | end: 134 | ret 135 | 136 | ;times 510-($-$$) db 0 ; $=当前地址、$$=当前节地址 137 | ; 写入启动扇区的结束标志 138 | ;db 55h,0aah 139 | 140 | 141 | ;******************************************************************************************************** 142 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 143 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 144 | ;* 145 | ;******************************************************************************************************** 146 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/process2.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,200 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_ID: 25 | mov ah,0eh 26 | mov al,'g' 27 | mov word[gs:((80 * 7 + 56) * 2)], ax 28 | mov al,'o' 29 | mov word[gs:((80 * 7 + 57) * 2)], ax 30 | mov al,'o' 31 | mov word[gs:((80 * 7 + 58) * 2)], ax 32 | mov al,'d' 33 | mov word[gs:((80 * 7 + 59) * 2)], ax 34 | mov al,' ' 35 | mov word[gs:((80 * 7 + 60) * 2)], ax 36 | mov al,'d' 37 | mov word[gs:((80 * 7 + 61) * 2)], ax 38 | mov al,'a' 39 | mov word[gs:((80 * 7 + 62) * 2)], ax 40 | mov al,'y' 41 | mov word[gs:((80 * 7 + 63) * 2)], ax 42 | 43 | mov word[x],0 44 | mov word[y],40 45 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 46 | mov word[char],'A' 47 | 48 | loop1: 49 | dec word[count] ; 递减计数变量 50 | jnz loop1 ; >0:跳转; 51 | mov word[count],delay 52 | dec word[dcount] ; 递减计数变量 53 | jnz loop1 54 | call boxing 55 | mov word[count],delay 56 | mov word[dcount],ddelay 57 | jmp loop1 58 | 59 | jmp $ ; 死循环 60 | 61 | datadef: 62 | 63 | count dw delay ; 计时器计数变量,初值=delay 64 | dcount dw ddelay ; 计时器计数变量,初值=delay 65 | x dw 0 ; 当前字符显示位置的行号,0~24 66 | y dw 0 ; 当前字符显示位置的列号,0~79 67 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 68 | char db 'A' ; 当前显示字符 69 | 70 | 71 | boxing: 72 | 73 | right: 74 | mov al,byte[rdlu] ;右 75 | cmp al,1 76 | jnz down 77 | mov ax,word[y] ;最后一列? 78 | cmp ax, 79 79 | jz r2d 80 | inc byte[y] 81 | jmp show 82 | r2d: 83 | mov byte[rdlu],4 ;改为向上 84 | dec byte[x] 85 | jmp show 86 | 87 | down: 88 | mov al,byte[rdlu] ;向下 89 | cmp al,2 90 | jnz left 91 | mov ax,word[x] ;最后一行? 92 | cmp ax, 12 93 | jz d2l 94 | inc byte[x] 95 | jmp show 96 | d2l: 97 | mov byte[rdlu],1 ;改为向右 98 | inc byte[y] 99 | jmp show 100 | 101 | left: 102 | mov al,byte[rdlu] ;向左 103 | cmp al,3 104 | jnz up 105 | mov ax,word[y] ;最左一列? 106 | cmp ax, 40 107 | jz l2u 108 | dec byte[y] 109 | jmp show 110 | l2u: 111 | mov byte[rdlu],2 ;改为向下 112 | inc byte[x] 113 | jmp show 114 | 115 | up: 116 | mov al,byte[rdlu] ;向上 117 | cmp al,4 118 | jnz end 119 | mov ax,word[x] ;最上一行? 120 | cmp ax, 0 121 | jz u2r 122 | dec byte[x] 123 | jmp show 124 | u2r: 125 | mov byte[rdlu],3 ;改为向左 126 | dec byte[y] 127 | mov al,byte[char] 128 | cmp al,'Z' 129 | jz returntoa 130 | inc byte[char] 131 | jmp show 132 | 133 | returntoa: 134 | mov byte[char],'A' 135 | jmp show 136 | 137 | show: 138 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 139 | mov ax,word[x] 140 | mov bx,80 ; (80*x 141 | mul bx 142 | add ax,word[y] ; (80*x+y) 143 | mov bx,2 144 | mul bx ; ((80*x+y)*2) 145 | mov bp,ax 146 | mov ah,0bh ; 0000:黑底、1111:亮白字(默认值为07h) 147 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 148 | mov word[gs:bp],ax ; 显示字符的ASCII码值 149 | 150 | 151 | end: 152 | ret 153 | 154 | 155 | jmp $ 156 | 157 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 158 | ; 写入启动扇区的结束标志 159 | ;db 55h,0aah 160 | 161 | 162 | ;******************************************************************************************************** 163 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 164 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 165 | ;* 166 | ;******************************************************************************************************** 167 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/process3.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,300 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_LOVE: 25 | mov ah,0bh 26 | mov al,'I' 27 | mov word[gs:((80 * 19 + 15) * 2)], ax 28 | mov al,'L' 29 | mov word[gs:((80 * 19 + 17) * 2)], ax 30 | mov al,'O' 31 | mov word[gs:((80 * 19 + 18) * 2)], ax 32 | mov al,'V' 33 | mov word[gs:((80 * 19 + 19) * 2)], ax 34 | mov al,'E' 35 | mov word[gs:((80 * 19 + 20) * 2)], ax 36 | mov al,'O' 37 | mov word[gs:((80 * 19 + 22) * 2)], ax 38 | mov al,'S' 39 | mov word[gs:((80 * 19 + 23) * 2)], ax 40 | 41 | mov word[x],13 42 | mov word[y],0 43 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 44 | mov word[char],'A' 45 | 46 | loop1: 47 | dec word[count] ; 递减计数变量 48 | jnz loop1 ; >0:跳转; 49 | mov word[count],delay 50 | dec word[dcount] ; 递减计数变量 51 | jnz loop1 52 | call boxing 53 | mov word[count],delay 54 | mov word[dcount],ddelay 55 | jmp loop1 56 | 57 | jmp $ ; 死循环 58 | 59 | datadef: 60 | 61 | count dw delay ; 计时器计数变量,初值=delay 62 | dcount dw ddelay ; 计时器计数变量,初值=delay 63 | x dw 0 ; 当前字符显示位置的行号,0~24 64 | y dw 0 ; 当前字符显示位置的列号,0~79 65 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 66 | char db 'A' ; 当前显示字符 67 | 68 | 69 | boxing: 70 | 71 | right: 72 | mov al,byte[rdlu] ;右 73 | cmp al,1 74 | jnz down 75 | mov ax,word[y] ;最后一列? 76 | cmp ax, 39 77 | jz r2d 78 | inc byte[y] 79 | jmp show 80 | r2d: 81 | mov byte[rdlu],4 ;改为向上 82 | dec byte[x] 83 | jmp show 84 | 85 | down: 86 | mov al,byte[rdlu] ;向下 87 | cmp al,2 88 | jnz left 89 | mov ax,word[x] ;最后一行? 90 | cmp ax, 24 91 | jz d2l 92 | inc byte[x] 93 | jmp show 94 | d2l: 95 | mov byte[rdlu],1 ;改为向右 96 | inc byte[y] 97 | jmp show 98 | 99 | left: 100 | mov al,byte[rdlu] ;向左 101 | cmp al,3 102 | jnz up 103 | mov ax,word[y] ;最左一列? 104 | cmp ax,0 105 | jz l2u 106 | dec byte[y] 107 | jmp show 108 | l2u: 109 | mov byte[rdlu],2 ;改为向下 110 | inc byte[x] 111 | jmp show 112 | 113 | up: 114 | mov al,byte[rdlu] ;向上 115 | cmp al,4 116 | jnz end 117 | mov ax,word[x] ;最上一行? 118 | cmp ax,13 119 | jz u2r 120 | dec byte[x] 121 | jmp show 122 | u2r: 123 | mov byte[rdlu],3 ;改为向左 124 | dec byte[y] 125 | mov al,byte[char] 126 | cmp al,'Z' 127 | jz returntoa 128 | inc byte[char] 129 | jmp show 130 | 131 | returntoa: 132 | mov byte[char],'A' 133 | jmp show 134 | 135 | show: 136 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 137 | mov ax,word[x] 138 | mov bx,80 ; (80*x 139 | mul bx 140 | add ax,word[y] ; (80*x+y) 141 | mov bx,2 142 | mul bx ; ((80*x+y)*2) 143 | mov bp,ax 144 | mov ah,0ch ; 0000:黑底、1111:亮白字(默认值为07h) 145 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 146 | mov word[gs:bp],ax ; 显示字符的ASCII码值 147 | 148 | 149 | end: 150 | ret 151 | 152 | 153 | jmp $ 154 | 155 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 156 | ; 写入启动扇区的结束标志 157 | ;db 55h,0aah 158 | 159 | 160 | ;******************************************************************************************************** 161 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 162 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 163 | ;* 164 | ;******************************************************************************************************** 165 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/process4.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | 14 | ;初始化段寄存器 15 | mov ax,400 ; AX = 0 16 | mov es,ax ; ES = 0 17 | mov ds,ax ; DS = CS 18 | mov ax,0B800h ; 文本窗口显存起始地址 19 | mov gs,ax ; GS = B800h 20 | mov word[count],delay 21 | mov word[dcount],ddelay 22 | 23 | mov word[x],13 24 | mov word[y],40 25 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 26 | mov word[char],'A' 27 | 28 | loop1: 29 | dec word[count] ; 递减计数变量 30 | jnz loop1 ; >0:跳转; 31 | mov word[count],delay 32 | dec word[dcount] ; 递减计数变量 33 | jnz loop1 34 | call boxing 35 | mov word[count],delay 36 | mov word[dcount],ddelay 37 | jmp loop1 38 | 39 | jmp $ ; 死循环 40 | 41 | datadef: 42 | 43 | count dw delay ; 计时器计数变量,初值=delay 44 | dcount dw ddelay ; 计时器计数变量,初值=delay 45 | x dw 13 ; 当前字符显示位置的行号,0~24 46 | y dw 40 ; 当前字符显示位置的列号,0~79 47 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 48 | char db 'A' ; 当前显示字符 49 | 50 | 51 | boxing: 52 | 53 | right: 54 | mov al,byte[rdlu] ;左-->右 55 | cmp al,1 56 | jnz down 57 | mov ax,word[y] ;最后一列? 58 | cmp ax, 79 59 | jz r2d 60 | inc byte[y] 61 | jmp show 62 | r2d: 63 | mov byte[rdlu],2 ;改为向下 64 | inc byte[x] 65 | jmp show 66 | 67 | down: 68 | mov al,byte[rdlu] ;向下 69 | cmp al,2 70 | jnz left 71 | mov ax,word[x] ;最后一行? 72 | cmp ax, 24 73 | jz d2l 74 | inc byte[x] 75 | jmp show 76 | d2l: 77 | mov byte[rdlu],3 ;改为向左 78 | dec byte[y] 79 | jmp show 80 | 81 | left: 82 | mov al,byte[rdlu] ;向左 83 | cmp al,3 84 | jnz up 85 | mov ax,word[y] ;最左一列? 86 | cmp ax, 40 87 | jz l2u 88 | dec byte[y] 89 | jmp show 90 | l2u: 91 | mov byte[rdlu],4 ;改为向 上 92 | dec byte[x] 93 | jmp show 94 | 95 | up: 96 | mov al,byte[rdlu] ;向上 97 | cmp al,4 98 | jnz end 99 | mov ax,word[x] ;最上一行? 100 | cmp ax, 13 101 | jz u2r 102 | dec byte[x] 103 | jmp show 104 | u2r: 105 | mov byte[rdlu],1 ;改为向右 106 | inc byte[y] 107 | mov al,byte[char] 108 | cmp al,'Z' 109 | jz returntoa 110 | inc byte[char] 111 | jmp show 112 | 113 | returntoa: 114 | mov byte[char],'A' 115 | jmp show 116 | 117 | show: 118 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 119 | mov ax,word[x] 120 | mov bx,80 ; (80*x 121 | mul bx 122 | add ax,word[y] ; (80*x+y) 123 | mov bx,2 124 | mul bx ; ((80*x+y)*2) 125 | mov bp,ax 126 | mov ah,0eh ; 0000:黑底、1111:亮白字(默认值为07h) 127 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 128 | mov word[gs:bp],ax ; 显示字符的ASCII码值 129 | 130 | 131 | end: 132 | ret 133 | 134 | 135 | jmp $ 136 | 137 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/user.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | extrn _main:near 6 | 7 | .8086 8 | _TEXT segment byte public 'CODE' 9 | assume cs:_TEXT 10 | DGROUP group _TEXT,_DATA,_BSS 11 | org 100h 12 | start: 13 | 14 | mov ax, cs 15 | mov ds, ax ; DS = CS 16 | mov es, ax ; ES = CS 17 | mov ss, ax ; SS = cs 18 | mov sp, 100h ; SP指向本段高端-4 19 | call near ptr _main ; 调用C语言程序cmain() 20 | jmp $ 21 | 22 | _TEXT ends 23 | _DATA segment word public 'DATA' 24 | _DATA ends 25 | _BSS segment word public 'BSS' 26 | _BSS ends 27 | end start 28 | 29 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/user1.c: -------------------------------------------------------------------------------- 1 | extern int fork(); 2 | extern int wait(); 3 | extern void exit(); 4 | 5 | #include "user_lib.h" 6 | 7 | char words[100]; 8 | int be_change = 0; 9 | 10 | void write(char *p) 11 | { 12 | int i = 0; 13 | while(*p != '\0') 14 | { 15 | words[i++] = *p; 16 | p++; 17 | } 18 | return; 19 | } 20 | 21 | void main() 22 | { 23 | int s; 24 | s = semaGet(1); 25 | if(fork()) 26 | { 27 | while(1) 28 | { 29 | semaP(s); 30 | if(be_change) 31 | { 32 | print(words); 33 | be_change = 0; 34 | } 35 | semaV(s); 36 | } 37 | } 38 | else 39 | { 40 | while(1) 41 | { 42 | semaP(s); 43 | be_change = 1; 44 | write("Father will live one year after anther forever!\r\n\r\n"); 45 | semaV(s); 46 | delay(15000); 47 | } 48 | exit(0); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/user2.c: -------------------------------------------------------------------------------- 1 | extern int fork(); 2 | extern int wait(); 3 | extern void exit(); 4 | 5 | #include "user_lib.h" 6 | 7 | char words[100]; 8 | int be_change = 0,fruit_disk; 9 | 10 | void write(char *p) 11 | { 12 | int i = 0; 13 | while(*p != '\0') 14 | { 15 | words[i++] = *p; 16 | p++; 17 | } 18 | return; 19 | } 20 | 21 | void putfruit() 22 | { 23 | int t; 24 | t = rand()%10; 25 | fruit_disk = t; 26 | } 27 | 28 | void main() 29 | { 30 | int s1,s2; 31 | s1 = semaGet(0); 32 | s2 = semaGet(0); 33 | if(fork()) 34 | { 35 | while(1) 36 | { 37 | semaP(s1); 38 | semaP(s2); 39 | if(be_change) 40 | { 41 | print(words); 42 | be_change = 0; 43 | } 44 | print("Father enjoy the fruit ");printInt(fruit_disk);print("\r\n\r\n"); 45 | fruit_disk = 0; 46 | } 47 | } 48 | else 49 | { 50 | if(fork()) 51 | { 52 | while(1) 53 | { 54 | be_change = 1; 55 | write("Father will live one year after anther forever!\r\n"); 56 | semaV(s1); 57 | delay(21000); 58 | } 59 | } 60 | else 61 | { 62 | while(1) 63 | { 64 | putfruit(); 65 | semaV(s2); 66 | delay(21000); 67 | } 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/user_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;************ ***************************** 9 | ; *SCOPY@ * 10 | ;****************** *********************** 11 | ; 实参为局部字符串带初始化异常问题的补钉程序 12 | public SCOPY@ 13 | SCOPY@ proc 14 | arg_0 = dword ptr 6 15 | arg_4 = dword ptr 0ah 16 | push bp 17 | mov bp,sp 18 | push si 19 | push di 20 | push ds 21 | lds si,[bp+arg_0] 22 | les di,[bp+arg_4] 23 | cld 24 | shr cx,1 25 | rep movsw 26 | adc cx,cx 27 | rep movsb 28 | pop ds 29 | pop di 30 | pop si 31 | pop bp 32 | retf 8 33 | SCOPY@ endp 34 | 35 | ;*************** ******************** 36 | ;* int _fork() * 37 | ;**************** ******************* 38 | ; 39 | public _fork 40 | _fork proc 41 | mov ah,6 42 | int 21h 43 | ret 44 | _fork endp 45 | 46 | ;*************** ******************** 47 | ;* int _wait() * 48 | ;**************** ******************* 49 | ; 50 | public _wait 51 | _wait proc 52 | mov ah,7 53 | int 21h 54 | ret 55 | _wait endp 56 | 57 | ;*************** ******************** 58 | ;* void _exit() * 59 | ;**************** ******************* 60 | ; 61 | public _exit 62 | _exit proc 63 | push bp 64 | mov bp,sp 65 | push bx 66 | 67 | mov ah,8 68 | mov bx,[bp+4] 69 | int 21h 70 | 71 | pop bx 72 | pop bp 73 | 74 | ret 75 | _exit endp 76 | 77 | ;*************** ******************** 78 | ;* void _cls() * 79 | ;**************** ******************* 80 | ; 清屏 81 | public _cls 82 | _cls proc 83 | mov ax,0003H 84 | int 10h ; 显示中断 85 | ret 86 | _cls endp 87 | 88 | ;**** *********************************** 89 | ;* void _PrintChar() * 90 | ;******* ******************************** 91 | ; 字符输出 92 | public _printChar 93 | _printChar proc 94 | push bp 95 | mov bp,sp 96 | push ax 97 | push bx 98 | ;*** 99 | mov al,[bp+4] 100 | mov bl,0 101 | mov ah,0eh 102 | int 10h 103 | ;*** 104 | pop bx 105 | pop ax 106 | mov sp,bp 107 | pop bp 108 | ret 109 | _printChar endp 110 | 111 | ;*********** **************************** 112 | ;* void _GetChar() * 113 | ;****************** ********************* 114 | ; 读入一个字符 115 | public _getChar 116 | _getChar proc 117 | mov ah,0 118 | int 16h 119 | ret 120 | _getChar endp 121 | 122 | ;*************** ******************** 123 | ;* void _delay() * 124 | ;**************** ******************* 125 | ; 延迟 126 | public _delay 127 | _delay proc 128 | push bp 129 | mov bp,sp 130 | push cx 131 | 132 | mov cx,word ptr[bp+4] 133 | delay_Continue: 134 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 135 | mov cx,word ptr [bp+4] 136 | delay_loop:loop delay_loop 137 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 138 | loop delay_Continue 139 | 140 | pop cx 141 | pop bp 142 | ret 143 | _delay endp 144 | 145 | t dw 0 146 | ;*************** ******************** 147 | ;* void _gettime() * 148 | ;**************** ******************* 149 | ; 获取时间 150 | public _backspace 151 | _backspace proc 152 | push ax 153 | push bx 154 | push cx 155 | push dx 156 | 157 | ;读光标位置,(dh,dl) = (行,列) 158 | mov bh,0 159 | mov ah,3h 160 | int 10h 161 | 162 | add dl,-1 163 | 164 | ;设置光标位置(dh,dl) = (行,列) 165 | mov bh,0 166 | mov ah,2h 167 | int 10h 168 | 169 | mov al,' ' 170 | mov bl,1 171 | mov ah,0eh 172 | int 10h 173 | 174 | ;设置光标位置(dh,dl) = (行,列) 175 | mov bh,0 176 | mov ah,2h 177 | int 10h 178 | 179 | pop dx 180 | pop cx 181 | pop bx 182 | pop ax 183 | ret 184 | _backspace endp 185 | 186 | 187 | _TEXT ends 188 | _DATA segment word public 'DATA' 189 | _DATA ends 190 | _BSS segment word public 'BSS' 191 | _BSS ends 192 | end start 193 | -------------------------------------------------------------------------------- /Lab08/src/用户程序/user_lib.h: -------------------------------------------------------------------------------- 1 | extern void cls(); 2 | extern char getchar(); 3 | extern void delay(int t); 4 | extern void printchar(); 5 | extern void backspace(); 6 | 7 | char input[100],output[100],t_char[100]; 8 | 9 | void reverse(char str[],int len) 10 | { 11 | /* 12 | * 将字符串反转 13 | */ 14 | int i; 15 | for(i = 0;i < len;++i) 16 | { 17 | t_char[i] = str[len-i-1]; 18 | } 19 | for(i = 0;i < len;++i) 20 | { 21 | str[i] = t_char[i]; 22 | } 23 | } 24 | 25 | int strlen(char str[]) 26 | { 27 | /* 28 | * 获取字符串长度 29 | */ 30 | int i = 0; 31 | while(str[i] != '\0') 32 | { 33 | i++; 34 | } 35 | return i; 36 | } 37 | 38 | void print(char *p) 39 | { 40 | /* 41 | * 输出字符串 p 42 | */ 43 | while(*p != '\0') 44 | { 45 | printChar(*p); 46 | p++; 47 | } 48 | } 49 | 50 | int getline(char arr[],int maxLen) 51 | { 52 | /* 53 | * 读取用户输入的一行 54 | */ 55 | 56 | int i = 0; 57 | char in; 58 | if(maxLen == 0) 59 | { 60 | return 0; 61 | } 62 | in = getchar(); 63 | while(in != '\n'&& in != '\r') 64 | { 65 | /* 66 | * 判断是不是回车键 67 | */ 68 | int k = in; 69 | if(k == 8) 70 | { 71 | /* 72 | * 判断是不是退格键 73 | */ 74 | i--; 75 | backspace(); 76 | in = getchar(); 77 | continue; 78 | } 79 | printChar(in); 80 | arr[i++] = in; 81 | if(i == maxLen) 82 | { 83 | /* 84 | * 是否达到允许输入的最大长度 85 | */ 86 | arr[i] = '\0'; 87 | printChar('\n'); 88 | return 0; 89 | } 90 | in = getchar(); 91 | } 92 | arr[i] = '\0'; 93 | print("\n\r"); 94 | return 1; 95 | } 96 | 97 | void printInt(int ans) 98 | { 99 | /* 100 | * 打印一个整数到屏幕 101 | */ 102 | int i = 0; 103 | if(ans == 0) 104 | { 105 | output[0] = '0'; 106 | i++; 107 | } 108 | while(ans) 109 | { 110 | int t = ans%10; 111 | output[i++] = '0'+t; 112 | ans/=10; 113 | } 114 | reverse(output,i); 115 | output[i] = '\0'; 116 | print(output); 117 | } 118 | -------------------------------------------------------------------------------- /Lab09/README.md: -------------------------------------------------------------------------------- 1 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 2 | 3 | (1) 映像文件满足FAT12格式。 4 | 5 | (2) 内核以文件形式存放在映像的FAT12文件系统中,修改引导程序实现内核的加载. 6 | 7 | (3) 将所有测试的用户程序放在在映像文件中的FAT12文件系统中,修改内核,实现从文件系统加载用户程序。 8 | 9 | -------------------------------------------------------------------------------- /Lab09/disk/Lab09.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab09/disk/Lab09.img -------------------------------------------------------------------------------- /Lab09/doc/实验说明.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/Lab09/doc/实验说明.doc -------------------------------------------------------------------------------- /Lab09/src/MyOs.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | 6 | .8086 7 | _TEXT segment byte public 'CODE' 8 | assume cs:_TEXT 9 | DGROUP group _TEXT,_DATA,_BSS 10 | org 100h 11 | start: 12 | 13 | ;设置 21h 的中断 14 | xor ax,ax 15 | mov es,ax 16 | mov word ptr es:[33*4],offset MOS_21h ; 设置 21h 的偏移地址 17 | mov ax,cs 18 | mov word ptr es:[33*4+2],ax 19 | 20 | ;设置 33h 的中断 21 | xor ax,ax 22 | mov es,ax 23 | mov word ptr es:[51*4],offset MOS_33h ; 设置 33h 的偏移地址 24 | mov ax,cs 25 | mov word ptr es:[51*4+2],ax 26 | 27 | ;设置 34h 的中断 28 | xor ax,ax 29 | mov es,ax 30 | mov word ptr es:[52*4],offset MOS_34h ; 设置 34h 的偏移地址 31 | mov ax,cs 32 | mov word ptr es:[52*4+2],ax 33 | 34 | ;设置 35h 的中断 35 | xor ax,ax 36 | mov es,ax 37 | mov word ptr es:[53*4],offset MOS_35h ; 设置 35h 的偏移地址 38 | mov ax,cs 39 | mov word ptr es:[53*4+2],ax 40 | 41 | ;设置 36h 的中断 42 | xor ax,ax 43 | mov es,ax 44 | mov word ptr es:[54*4],offset MOS_36h ; 设置 36h 的偏移地址 45 | mov ax,cs 46 | mov word ptr es:[54*4+2],ax 47 | 48 | mov ax, cs 49 | mov ds, ax ; DS = CS 50 | mov es, ax ; ES = CS 51 | mov ss, ax ; SS = cs 52 | mov sp, 100h ; SP指向本段高端-4 53 | call near ptr _cmain ; 调用C语言程序cmain() 54 | jmp $ 55 | 56 | include function.asm ; 包含内核库过程 function.asm 57 | include services.asm ; 包含系统服务程序 58 | include file.asm 59 | 60 | _TEXT ends 61 | _DATA segment word public 'DATA' 62 | _DATA ends 63 | _BSS segment word public 'BSS' 64 | _BSS ends 65 | end start 66 | 67 | -------------------------------------------------------------------------------- /Lab09/src/bat 文件/run1.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | nasm process1.asm -o prs1.bin 4 | 5 | nasm process2.asm -o prs2.bin 6 | 7 | nasm process3.asm -o prs3.bin 8 | 9 | nasm process4.asm -o prs4.bin 10 | 11 | nasm pro1.asm -o pro1.bin 12 | 13 | nasm pro2.asm -o pro2.bin 14 | 15 | nasm pro3.asm -o pro3.bin 16 | -------------------------------------------------------------------------------- /Lab09/src/bat 文件/run2.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | tcc -mt -c -omyos.obj MyOs.c 4 | 5 | tasm MyOs.asm os.obj 6 | 7 | tasm c_lib.asm c_lib.lib 8 | 9 | tlink /3 /t os.obj myos.obj c_lib.lib,os.com 10 | 11 | -------------------------------------------------------------------------------- /Lab09/src/bat 文件/run3.bat: -------------------------------------------------------------------------------- 1 | cls 2 | 3 | tcc -mt -c -ouser.obj user.c 4 | 5 | tasm user.asm uuser.obj 6 | 7 | tasm user_lib.asm user_lib.lib 8 | 9 | tlink /3 /t uuser.obj user.obj user_lib.lib,user.com 10 | 11 | -------------------------------------------------------------------------------- /Lab09/src/boot.asm: -------------------------------------------------------------------------------- 1 | org 7c00h ; 加载到 0:7C00 处 2 | jmp short LABEL_START ; 跳转到代码起始处 3 | nop ; 这个nop(无操作指令)不可少(占位字节) 4 | 5 | ; 下面是 FAT12 磁盘的头(BPB+EBPB,占51B) 6 | BS_OEMName DB 'MyOS 1.0' ; OEM String, 必须 8 个字节(不足补空格) 7 | BPB_BytsPerSec DW 512 ; 每扇区字节数 8 | BPB_SecPerClus DB 1 ; 每簇多少扇区 9 | BPB_RsvdSecCnt DW 1 ; Boot记录占用多少扇区 10 | BPB_NumFATs DB 2 ; 共有多少 FAT 表 11 | BPB_RootEntCnt DW 224 ; 根目录文件数最大值 12 | BPB_TotSec16 DW 2880 ; 逻辑扇区总数 13 | BPB_Media DB 0xF0 ; 介质描述符 14 | BPB_FATSz16 DW 9 ; 每FAT扇区数 15 | BPB_SecPerTrk DW 18 ; 每磁道扇区数 16 | BPB_NumHeads DW 2 ; 磁头数(面数) 17 | BPB_HiddSec DD 0 ; 隐藏扇区数 18 | BPB_TotSec32 DD 0 ; BPB_TotSec16为0时这个值记录扇区数 19 | BS_DrvNum DB 0 ; 中断 13h 的驱动器号 20 | BS_Reserved1 DB 0 ; 未使用 21 | BS_BootSig DB 29h ; 扩展引导标记 (29h) 22 | BS_VolID DD 12345678h; 卷序列号 23 | BS_VolLab DB 'MyOS System'; 卷标, 必须 11 个字节(不足补空格) 24 | BS_FileSysType DB 'FAT12 ' ; 文件系统类型, 必须 8个字节(不足补空格) 25 | 26 | LABEL_START: 27 | mov ax, cs ; 置DS和ES=CS 28 | mov ds, ax 29 | mov es, ax 30 | call ScrollPg ; 向上滚动显示页 31 | call DispStr ; 调用显示字符串例程 32 | jmp $ ; 无限循环 33 | 34 | ScrollPg: ; 清屏例程 35 | mov ah, 6 ; 功能号 36 | mov al, 0 ; 滚动的文本行数(0=整个窗口) 37 | mov bh,0fh ; 设置插入空行的字符颜色为黑底亮白字 38 | mov cx, 0 ; 窗口左上角的行号=CH、列号=CL 39 | mov dh, 24 ; 窗口右下角的行号 40 | mov dl, 79 ; 窗口右下角的列号 41 | int 10h ; 显示中断 42 | ret 43 | 44 | DispStr: 45 | mov ah,13h ; BIOS中断的功能号(显示字符串) 46 | mov al,1 ; 光标放到串尾 47 | mov bh,0 ; 页号=0 48 | mov bl,0ch ; 字符颜色=黑底亮红字 49 | mov cx,16 ; 串长=16 50 | mov dx,0 ; 显示串的起始位置(0,0):DH=行号、DL=列号 51 | mov bp,BootMsg ; ES:BP=串地址 52 | int 10h ; 调用10H号显示中断 53 | ret ; 从例程返回 54 | 55 | BootMsg: 56 | db "Hello, OS world!" ; 显示用字符串 57 | times 510-($-$$) db 0 ; 用0填充剩下的扇区空间(软盘无分区表) 58 | db 55h, 0aah ; 引导扇区结束标志 59 | 60 | ; 填充两个FAT表的头两个项(每个FAT占9个扇区) 61 | db 0f0h, 0ffh, 0ffh ; 介质描述符(F0h)和Fh、结束簇标志项FFFh 62 | times 512*9-3 db 0 ; 用0填充FAT#1剩下的空间 63 | db 0f0h, 0ffh, 0ffh ; 介质描述符(F0h)和Fh、结束簇标志项FFFh 64 | times 512*9-3 db 0 ; 用0填充FAT#2剩下的空间 65 | ; 根目录中的卷标条目 66 | db 'MyOS System' ; 卷标, 必须 11 个字节(不足补空格) 67 | db 8 ; 文件属性值(卷标条目的为08h) 68 | dw 0,0,0,0,0 ; 10个保留字节 69 | dw 0,426Eh ; 创建时间,设为2013年3月14日0时0分0秒 70 | dw 0 ; 开始簇号(卷标条目的必需为0) 71 | dd 0 ; 文件大小(也设为0) 72 | 73 | 74 | -------------------------------------------------------------------------------- /Lab09/src/c_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;*************** ******************** 9 | ;* void _to_OUCH() * 10 | ;**************** ******************* 11 | ; 调用 21h 0号功能 12 | public _to_OUCH 13 | _to_OUCH proc 14 | push ax 15 | push bx 16 | push cx 17 | push dx 18 | push es 19 | 20 | call Clear 21 | 22 | mov ah,0 23 | int 21h 24 | 25 | call DelaySome 26 | 27 | pop ax 28 | mov es,ax 29 | pop dx 30 | pop cx 31 | pop bx 32 | pop ax 33 | ret 34 | _to_OUCH endp 35 | 36 | ;*************** ******************** 37 | ;* void _upper() * 38 | ;**************** ******************* 39 | ; 调用 21h 1号功能 40 | public _upper 41 | _upper proc 42 | push bp 43 | mov bp,sp 44 | push si 45 | mov si,word ptr [bp+4] ; 获得字符串首地址 46 | 47 | push ax 48 | push bx 49 | push cx 50 | push dx 51 | push es 52 | 53 | mov ah,1 54 | mov dx,si ; 把字符串首地址给 dx 55 | int 21h 56 | 57 | pop ax 58 | mov es,ax 59 | pop dx 60 | pop cx 61 | pop bx 62 | pop ax 63 | 64 | pop si 65 | pop bp 66 | ret 67 | _upper endp 68 | 69 | ;*************** ******************** 70 | ;* void _lower() * 71 | ;**************** ******************* 72 | ; 调用 21h 2号功能 73 | public _lower 74 | _lower proc 75 | push bp 76 | mov bp,sp 77 | push si 78 | mov si,word ptr [bp+4] ; 获得字符串首地址 79 | 80 | push ax 81 | push bx 82 | push cx 83 | push dx 84 | push es 85 | 86 | mov ah,2 87 | mov dx,si ; 把字符串首地址给 dx 88 | int 21h 89 | 90 | pop ax 91 | mov es,ax 92 | pop dx 93 | pop cx 94 | pop bx 95 | pop ax 96 | 97 | pop si 98 | pop bp 99 | ret 100 | _lower endp 101 | 102 | ;*************** ******************** 103 | ;* void _digital() * 104 | ;**************** ******************* 105 | ; 调用 21h 3号功能 106 | public _digital 107 | _digital proc 108 | push bp 109 | mov bp,sp 110 | push si 111 | mov si,word ptr [bp+4] ; 获得字符串首地址 112 | 113 | push bx 114 | push cx 115 | push dx 116 | push es 117 | 118 | mov ah,3 119 | mov dx,si ; 把字符串首地址给 dx 120 | int 21h 121 | 122 | pop bx 123 | mov es,bx 124 | pop dx 125 | pop cx 126 | pop bx 127 | 128 | pop si 129 | pop bp 130 | ret 131 | _digital endp 132 | 133 | ;*************** ******************** 134 | ;* void _convertToString() * 135 | ;**************** ******************* 136 | ; 调用 21h 4号功能 137 | public _convertToString 138 | _convertToString proc 139 | push bp 140 | mov bp,sp 141 | push si 142 | mov si,word ptr [bp+4] ; 获得传递进来的整数 143 | 144 | push bx 145 | push cx 146 | push dx 147 | push es 148 | 149 | mov ah,4 150 | mov bx,si ; 把整数给 dx 151 | int 21h 152 | 153 | pop bx 154 | mov es,bx 155 | pop dx 156 | pop cx 157 | pop bx 158 | 159 | pop si 160 | pop bp 161 | ret 162 | _convertToString endp 163 | 164 | ;*************** ******************** 165 | ;* void _display() * 166 | ;**************** ******************* 167 | ; 调用 21h 5号功能 168 | public _display 169 | _display proc 170 | push bp 171 | mov bp,sp 172 | push si 173 | 174 | push bx 175 | push cx 176 | push dx 177 | push es 178 | 179 | call Clear 180 | 181 | mov bx,word ptr [bp+4] ; 获得行号 182 | mov ax,word ptr [bp+6] ; 获得列号 183 | mov si,word ptr [bp+8] ; 获得字符串首地址 184 | 185 | 186 | mov ah,5 187 | mov dx,si ; dx 放字符串地址 188 | mov ch,bl ; ch 放行号 189 | mov cl,al ; cl 放列号 190 | int 21h 191 | 192 | call DelaySome 193 | call Clear 194 | 195 | pop bx 196 | mov es,bx 197 | pop dx 198 | pop cx 199 | pop bx 200 | 201 | pop si 202 | pop bp 203 | ret 204 | _display endp 205 | 206 | ;*************** ******************** 207 | ;* DelaySome * 208 | ;**************** ******************* 209 | ; 延迟 210 | DelaySome: ; 延迟一段时间 211 | mov cx,delayTime 212 | toDelay: 213 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 214 | mov cx,delayTime 215 | loop1:loop loop1 216 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 217 | loop toDelay 218 | ret 219 | 220 | Clear: ;清屏 221 | MOV AX,0003H 222 | INT 10H 223 | ret 224 | 225 | delayTime equ 40000 226 | t dw 0 227 | 228 | _TEXT ends 229 | _DATA segment word public 'DATA' 230 | _DATA ends 231 | _BSS segment word public 'BSS' 232 | _BSS ends 233 | end start 234 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/pro2.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; 本文件为用户程序1的源码文件 3 | ; 4 | org 7e00h ; 加载到0:7e00h处,并开始执行 5 | START: 6 | mov ax,cs ; 设置 DS和ES = CS 7 | mov ds,ax 8 | mov es,ax 9 | call Clear ; 清屏 10 | 11 | mov ah,0 12 | int 21h 13 | 14 | call DispStr ; 显示字符串 15 | call Delay 16 | call Clear 17 | int 33h 18 | int 34h 19 | int 35h 20 | int 36h 21 | call Delay 22 | ret 23 | 24 | Delay: 25 | mov cx,delayTime ;初始化 cx 为 5000 26 | toDelay: ;双重循环进行延迟,延迟时间为 5000*5000 27 | mov word[t],cx ;把 cx 的值保存到 t 中 28 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 29 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 30 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 31 | loop toDelay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 32 | ret ; 段间返回 33 | 34 | DispStr: ; 显示字符串 35 | ; 显示字符串 (开始) 36 | mov ah,5 37 | mov dx,Msg ; dx 放字符串地址 38 | mov ch,5 ; ch 放行号 39 | mov cl,23 ; cl 放列号 40 | int 21h 41 | ; 显示字符串(结束) 42 | ; 显示字符串2 "Please Key in Esc to quit:"(开始) 43 | mov ah,13h ; 功能号 44 | mov al,1 ; 光标放到串尾 45 | mov bl,0dh ; 黑底品红字 46 | mov bh,0 ; 第0页 47 | mov dh,07h ; 第7行 48 | mov dl,18 ; 第28列 49 | mov bp,Tips ; BP=串地址 50 | mov cx,Length2 ; 串长 51 | int 10h ; 调用10H号中断 52 | ; 显示字符串2(结束) 53 | ret 54 | 55 | Clear: ;清屏 56 | mov ax,0003H ; 清屏属性 57 | int 10H ; 调用中断 58 | ret ; 返回 59 | 60 | delayTime equ 40000 61 | t dw 0 62 | Msg: ; 字符串 63 | db "Look! The 21h is still available....",0h 64 | Tips: ; 退出提示 65 | db "Please wait for the program to quit..." 66 | Length2: equ ($-Tips) ; 提示的长度 67 | 68 | 69 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分 70 | ;db 55h,0aah ; 启动扇区的结束标志 71 | 72 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/pro3.asm: -------------------------------------------------------------------------------- 1 | ; 一个运动的黄色 U 100 个往后擦除 2 | Init: ;程序初始化 3 | delayTime equ 6000 ;定义 delayTime 代表 50 4 | org 7e00h ;程序装载到 7c00h 5 | call Clear 6 | mov ax,cs ;用 cs 中的值初始化 ds 和 es 寄存器 7 | mov ds,ax 8 | mov es, ax 9 | jmp main 10 | 11 | main: ;可视为主函数 12 | mov ax,24 ;置 ax 为立即数 24 13 | cmp ax,word[y] ;比较 y 是否等于 24 ,即比较字符是否到达底端 14 | je DownToUp ;如果 ZF 标志位为 1,即上述比较结果为相等,则跳转到 DownToUp 位置 15 | mov ax,0 ;在 ax 中放 0 16 | cmp ax,word[y] ;比较 y 是否为 0 ,判断字符是否到达屏幕顶端 17 | je UptoDown ;上述条件成立则跳转至 UptoDown 18 | mov ax,79 ;把 ax 置为 79 ,即为屏幕最右端 19 | cmp ax,word[x] ;比较 x 是否为 79 ,即比较字符是否到达最右端 20 | je RightToLeft ;如果上述条件成立则跳转至 RightToLeft 21 | mov ax,0 ;在 ax 中置 0 22 | cmp ax,word[x] ;比较 x 是否为 0 ,即比较字符是否到达最左端 23 | je LeftToRight ;如果上述条件成立则跳转到 LeftToRight 24 | jmp Usual ;如果上述四个边界条件都没有触发则执行 Usual 的代码段,正常地进行显示 25 | 26 | Usual: ;在没有触发边界时执行的代码块 27 | mov ax,0 ;ax 置零 28 | cmp ax,word[statey] ;比较 statey 是否为 0 ,即此时状态是否向下 29 | je Down ;相等时跳转到 Down ,向下运动 30 | jmp Up ;上一个语句没有跳转,则直接则跳到 Up ,向上运动 31 | 32 | DownToUp: ;触底反弹 33 | mov word[statey],1 ;statey 置为 1,状态改为向上运动 34 | cmp byte[x],0 ;是否到达左下角 35 | je LeftToRight 36 | cmp byte[x],79 ;是否到达右下角 37 | je RightToLeft 38 | jmp Up ;无条件跳转至 Up 39 | 40 | UptoDown: ;触顶反弹 41 | mov word[statey],0 ;把 statey 置 0 ,状态变成向下 42 | cmp byte[x],0 ;是否到达左上角 43 | je LeftToRight 44 | cmp byte[x],79 ;是否到达右上角 45 | je RightToLeft 46 | jmp Down ;无条件跳转至 Down 47 | 48 | RightToLeft: ;在最右反弹 49 | mov word[statex],1 ;将 statex 置 1 ,状态改为向左 50 | mov ax,0 ;把 ax 置 0 51 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 则向下运动 52 | je Down ;是则跳转到 Down ,向下 53 | jmp Up ;否则跳转到 Up ,向上 54 | 55 | LeftToRight: ;在最左反弹 56 | mov word[statex],0 ;将 statex 置 0 ,状态改为向右 57 | mov ax,0 ;将 ax 置 0 58 | cmp ax,word[statey] ;判断 statey 是否为 0 ,0 为向下 59 | je Down ;是则跳转到 Down 60 | jmp Up ;否则跳转到 Up 61 | 62 | Up: ;向上运动 63 | dec word[y] ;y-- ,把纵坐标减 1,向上 64 | mov ax,0 ;ax 置 0 65 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 66 | je R ;是的话跳转到 R 67 | jmp L ;不是的话跳转到 L 68 | 69 | Down: ;向下运动 70 | inc word[y] ;y++,把纵坐标加 1 ,向下 71 | mov ax,0 ;置 ax 为 0 72 | cmp ax,word[statex] ;判断 statex 是否为 0 ,0 为向右 73 | je R ;是的话跳转到 R 74 | jmp L ;不是的话跳转到 L 75 | 76 | R: ;向右运动 77 | inc word[x] ; x++,横坐标加 1,向右 78 | jmp Show ;跳转至 Show 代码段 79 | 80 | L: ;向左运动 81 | dec word[x] ;x--,横坐标减 1,向左 82 | jmp Show ;跳转至 Show 代码段 83 | 84 | Show: ;显示字符 85 | inc word[num] 86 | mov ax,word[num] 87 | cmp ax,199 88 | je quit 89 | cmp ax,100 90 | jnz next 91 | call change 92 | 93 | next: 94 | mov ax,0b800h ;置 ax 为彩色显存起始地址 0b800h 95 | mov gs,ax ;把 ax 的值加载到 es,作为存放字符的基址 96 | mov ax,160 ;置 ax 为160,根据屏幕 80x24 可得出偏移量 bx = 2(80*y + x) 97 | mul word[y] ;计算 160*y ,结果放在 ax 中 98 | mov word[t],ax ;把 ax 的值放到 t 99 | mov ax,word[x] ;把 x 放到 ax 100 | add ax,ax ;ax *= 2 101 | add ax,word[t] ;把 t 和 ax 相加放到 ax 中,完成 t = 160*y + x*2 102 | mov bx,ax ;置 bx 等于 ax ,即为 t 103 | mov al,byte[c] ;在 al 中放字符 'Z' 104 | mov ah,0eh ;在 ah 中放 0ch,表示黑底红字 105 | mov [gs:bx],ax ;把 ax 的值放到 [es:bx] (基址+偏移量) 处,字符完成显示 106 | mov cx,delayTime ;初始化 cx 为 5000 107 | jmp delay ;跳转到 delay ,进行延迟 108 | 109 | 110 | change: 111 | mov byte[c],32 112 | cmp word[statex],0 113 | jnz cmp2 114 | mov word[statex],1 115 | jmp cmp3 116 | cmp2: 117 | mov word[statex],0 118 | cmp3: 119 | cmp word[statey],0 120 | jnz cmp4 121 | mov word[statey],1 122 | ret 123 | cmp4: 124 | mov word[statey],0 125 | ret 126 | 127 | Clear: ;清屏 128 | MOV AX,0003H 129 | INT 10H 130 | ret 131 | 132 | quit: 133 | ret 134 | 135 | delay: ;双重循环进行延迟,延迟时间为 5000*5000 136 | mov word[t],cx ;把 cx 的值保存到 t 中 137 | mov cx,delayTime ;置 cx 为 delayTime 的值(500) 138 | loop1:loop loop1 ;每执行一次循环 cx 值减 1,直到 cx = 0,循环为在当前语句跳转,用于延迟 139 | mov cx,word[t] ;把 t 的值放回 cx ,恢复 cx 140 | loop delay ;执行循环,跳转到 delay 处,每执行一次循环 cx 值减 1,直到 cx = 0 141 | jmp main ;无条件跳转至 main ,继续执行 142 | 143 | data: ;数据声明部分 144 | x dw -1 ;声明变量 x ,并初始化 x 为 -1 145 | y dw -1 ;声明变量 y ,并初始化 y 为 -1 146 | t dw 0 ;声明变量 t ,并初始化 t 为 0 147 | num dw 0 148 | c db 'U' 149 | statey dw 0 ;声明变量 statey ,初始状态为向下,0 向下 1 向上 150 | statex dw 0 ;声明变量 statex ,初始状态为向右,0 向右 1 向左 151 | times 512-($-$$) db 0 ; 用0填充扇区的剩余部分($$=当前节地址) 152 | ;db 55h,0aah 153 | 154 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/process1.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-05-2 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h ; 程序加载到100h,可用于生成COM 14 | 15 | ;初始化段寄存器 16 | xor ax,ax ; AX = 0 17 | mov ax,100 18 | mov es,ax ; ES = 0 19 | mov ds,ax ; DS = CS 20 | mov ax,0B800h ; 文本窗口显存起始地址 21 | mov gs,ax ; GS = B800h 22 | mov word[count],delay 23 | mov word[dcount],ddelay 24 | 25 | mov word[x],0 26 | mov word[y],0 27 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 28 | mov word[char],'A' 29 | 30 | loop1: 31 | dec word[count] ; 递减计数变量 32 | jnz loop1 ; >0:跳转; 33 | mov word[count],delay 34 | dec word[dcount] ; 递减计数变量 35 | jnz loop1 36 | call boxing 37 | mov word[count],delay 38 | mov word[dcount],ddelay 39 | jmp loop1 40 | 41 | jmp $ ; 死循环 42 | 43 | datadef: 44 | 45 | count dw delay ; 计时器计数变量,初值=delay 46 | dcount dw ddelay ; 计时器计数变量,初值=delay 47 | x dw 0 ; 当前字符显示位置的行号,0~24 48 | y dw 0 ; 当前字符显示位置的列号,0~79 49 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 50 | char db 'A' ; 当前显示字符 51 | 52 | 53 | boxing: 54 | 55 | right: 56 | mov al,byte[rdlu] ;左-->右 57 | cmp al,1 58 | jnz down 59 | mov ax,word[y] ;最后一列? 60 | cmp ax, 39 61 | jz r2d 62 | inc byte[y] 63 | jmp show 64 | r2d: 65 | mov byte[rdlu],2 ;改为向下 66 | inc byte[x] 67 | jmp show 68 | 69 | down: 70 | mov al,byte[rdlu] ;向下 71 | cmp al,2 72 | jnz left 73 | mov ax,word[x] ;最后一行? 74 | cmp ax, 12 75 | jz d2l 76 | inc byte[x] 77 | jmp show 78 | d2l: 79 | mov byte[rdlu],3 ;改为向左 80 | dec byte[y] 81 | jmp show 82 | 83 | left: 84 | mov al,byte[rdlu] ;向左 85 | cmp al,3 86 | jnz up 87 | mov ax,word[y] ;最左一列? 88 | cmp ax, 0 89 | jz l2u 90 | dec byte[y] 91 | jmp show 92 | l2u: 93 | mov byte[rdlu],4 ;改为向 上 94 | dec byte[x] 95 | jmp show 96 | 97 | up: 98 | mov al,byte[rdlu] ;向上 99 | cmp al,4 100 | jnz end 101 | mov ax,word[x] ;最上一行? 102 | cmp ax, 0 103 | jz u2r 104 | dec byte[x] 105 | jmp show 106 | u2r: 107 | mov byte[rdlu],1 ;改为向右 108 | inc byte[y] 109 | mov al,byte[char] 110 | cmp al,'Z' 111 | jz returntoa 112 | inc byte[char] 113 | jmp show 114 | 115 | returntoa: 116 | mov byte[char],'A' 117 | jmp show 118 | 119 | show: 120 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 121 | mov ax,word[x] 122 | mov bx,80 ; (80*x 123 | mul bx 124 | add ax,word[y] ; (80*x+y) 125 | mov bx,2 126 | mul bx ; ((80*x+y)*2) 127 | mov bp,ax 128 | mov ah,0ah ; 0000:黑底、1111:亮白字(默认值为07h) 129 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 130 | mov word[gs:bp],ax ; 显示字符的ASCII码值 131 | 132 | 133 | end: 134 | ret 135 | 136 | ;times 510-($-$$) db 0 ; $=当前地址、$$=当前节地址 137 | ; 写入启动扇区的结束标志 138 | ;db 55h,0aah 139 | 140 | 141 | ;******************************************************************************************************** 142 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 143 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 144 | ;* 145 | ;******************************************************************************************************** 146 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/process2.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右上角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,200 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_ID: 25 | mov ah,0eh 26 | mov al,'g' 27 | mov word[gs:((80 * 7 + 56) * 2)], ax 28 | mov al,'o' 29 | mov word[gs:((80 * 7 + 57) * 2)], ax 30 | mov al,'o' 31 | mov word[gs:((80 * 7 + 58) * 2)], ax 32 | mov al,'d' 33 | mov word[gs:((80 * 7 + 59) * 2)], ax 34 | mov al,' ' 35 | mov word[gs:((80 * 7 + 60) * 2)], ax 36 | mov al,'d' 37 | mov word[gs:((80 * 7 + 61) * 2)], ax 38 | mov al,'a' 39 | mov word[gs:((80 * 7 + 62) * 2)], ax 40 | mov al,'y' 41 | mov word[gs:((80 * 7 + 63) * 2)], ax 42 | 43 | mov word[x],0 44 | mov word[y],40 45 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 46 | mov word[char],'A' 47 | 48 | loop1: 49 | dec word[count] ; 递减计数变量 50 | jnz loop1 ; >0:跳转; 51 | mov word[count],delay 52 | dec word[dcount] ; 递减计数变量 53 | jnz loop1 54 | call boxing 55 | mov word[count],delay 56 | mov word[dcount],ddelay 57 | jmp loop1 58 | 59 | jmp $ ; 死循环 60 | 61 | datadef: 62 | 63 | count dw delay ; 计时器计数变量,初值=delay 64 | dcount dw ddelay ; 计时器计数变量,初值=delay 65 | x dw 0 ; 当前字符显示位置的行号,0~24 66 | y dw 0 ; 当前字符显示位置的列号,0~79 67 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 68 | char db 'A' ; 当前显示字符 69 | 70 | 71 | boxing: 72 | 73 | right: 74 | mov al,byte[rdlu] ;右 75 | cmp al,1 76 | jnz down 77 | mov ax,word[y] ;最后一列? 78 | cmp ax, 79 79 | jz r2d 80 | inc byte[y] 81 | jmp show 82 | r2d: 83 | mov byte[rdlu],4 ;改为向上 84 | dec byte[x] 85 | jmp show 86 | 87 | down: 88 | mov al,byte[rdlu] ;向下 89 | cmp al,2 90 | jnz left 91 | mov ax,word[x] ;最后一行? 92 | cmp ax, 12 93 | jz d2l 94 | inc byte[x] 95 | jmp show 96 | d2l: 97 | mov byte[rdlu],1 ;改为向右 98 | inc byte[y] 99 | jmp show 100 | 101 | left: 102 | mov al,byte[rdlu] ;向左 103 | cmp al,3 104 | jnz up 105 | mov ax,word[y] ;最左一列? 106 | cmp ax, 40 107 | jz l2u 108 | dec byte[y] 109 | jmp show 110 | l2u: 111 | mov byte[rdlu],2 ;改为向下 112 | inc byte[x] 113 | jmp show 114 | 115 | up: 116 | mov al,byte[rdlu] ;向上 117 | cmp al,4 118 | jnz end 119 | mov ax,word[x] ;最上一行? 120 | cmp ax, 0 121 | jz u2r 122 | dec byte[x] 123 | jmp show 124 | u2r: 125 | mov byte[rdlu],3 ;改为向左 126 | dec byte[y] 127 | mov al,byte[char] 128 | cmp al,'Z' 129 | jz returntoa 130 | inc byte[char] 131 | jmp show 132 | 133 | returntoa: 134 | mov byte[char],'A' 135 | jmp show 136 | 137 | show: 138 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 139 | mov ax,word[x] 140 | mov bx,80 ; (80*x 141 | mul bx 142 | add ax,word[y] ; (80*x+y) 143 | mov bx,2 144 | mul bx ; ((80*x+y)*2) 145 | mov bp,ax 146 | mov ah,0bh ; 0000:黑底、1111:亮白字(默认值为07h) 147 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 148 | mov word[gs:bp],ax ; 显示字符的ASCII码值 149 | 150 | 151 | end: 152 | ret 153 | 154 | 155 | jmp $ 156 | 157 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 158 | ; 写入启动扇区的结束标志 159 | ;db 55h,0aah 160 | 161 | 162 | ;******************************************************************************************************** 163 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 164 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 165 | ;* 166 | ;******************************************************************************************************** 167 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/process3.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框左下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | ;org 7c00h 14 | 15 | ;初始化段寄存器 16 | mov ax,300 ; AX = 0 17 | mov es,ax ; ES = 0 18 | mov ds,ax ; DS = CS 19 | mov ax,0B800h ; 文本窗口显存起始地址 20 | mov gs,ax ; GS = B800h 21 | mov word[count],delay 22 | mov word[dcount],ddelay 23 | 24 | LABEL_SHOW_LOVE: 25 | mov ah,0bh 26 | mov al,'I' 27 | mov word[gs:((80 * 19 + 15) * 2)], ax 28 | mov al,'L' 29 | mov word[gs:((80 * 19 + 17) * 2)], ax 30 | mov al,'O' 31 | mov word[gs:((80 * 19 + 18) * 2)], ax 32 | mov al,'V' 33 | mov word[gs:((80 * 19 + 19) * 2)], ax 34 | mov al,'E' 35 | mov word[gs:((80 * 19 + 20) * 2)], ax 36 | mov al,'O' 37 | mov word[gs:((80 * 19 + 22) * 2)], ax 38 | mov al,'S' 39 | mov word[gs:((80 * 19 + 23) * 2)], ax 40 | 41 | mov word[x],13 42 | mov word[y],0 43 | mov byte[rdlu], 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 44 | mov word[char],'A' 45 | 46 | loop1: 47 | dec word[count] ; 递减计数变量 48 | jnz loop1 ; >0:跳转; 49 | mov word[count],delay 50 | dec word[dcount] ; 递减计数变量 51 | jnz loop1 52 | call boxing 53 | mov word[count],delay 54 | mov word[dcount],ddelay 55 | jmp loop1 56 | 57 | jmp $ ; 死循环 58 | 59 | datadef: 60 | 61 | count dw delay ; 计时器计数变量,初值=delay 62 | dcount dw ddelay ; 计时器计数变量,初值=delay 63 | x dw 0 ; 当前字符显示位置的行号,0~24 64 | y dw 0 ; 当前字符显示位置的列号,0~79 65 | rdlu db 2 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 66 | char db 'A' ; 当前显示字符 67 | 68 | 69 | boxing: 70 | 71 | right: 72 | mov al,byte[rdlu] ;右 73 | cmp al,1 74 | jnz down 75 | mov ax,word[y] ;最后一列? 76 | cmp ax, 39 77 | jz r2d 78 | inc byte[y] 79 | jmp show 80 | r2d: 81 | mov byte[rdlu],4 ;改为向上 82 | dec byte[x] 83 | jmp show 84 | 85 | down: 86 | mov al,byte[rdlu] ;向下 87 | cmp al,2 88 | jnz left 89 | mov ax,word[x] ;最后一行? 90 | cmp ax, 24 91 | jz d2l 92 | inc byte[x] 93 | jmp show 94 | d2l: 95 | mov byte[rdlu],1 ;改为向右 96 | inc byte[y] 97 | jmp show 98 | 99 | left: 100 | mov al,byte[rdlu] ;向左 101 | cmp al,3 102 | jnz up 103 | mov ax,word[y] ;最左一列? 104 | cmp ax,0 105 | jz l2u 106 | dec byte[y] 107 | jmp show 108 | l2u: 109 | mov byte[rdlu],2 ;改为向下 110 | inc byte[x] 111 | jmp show 112 | 113 | up: 114 | mov al,byte[rdlu] ;向上 115 | cmp al,4 116 | jnz end 117 | mov ax,word[x] ;最上一行? 118 | cmp ax,13 119 | jz u2r 120 | dec byte[x] 121 | jmp show 122 | u2r: 123 | mov byte[rdlu],3 ;改为向左 124 | dec byte[y] 125 | mov al,byte[char] 126 | cmp al,'Z' 127 | jz returntoa 128 | inc byte[char] 129 | jmp show 130 | 131 | returntoa: 132 | mov byte[char],'A' 133 | jmp show 134 | 135 | show: 136 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 137 | mov ax,word[x] 138 | mov bx,80 ; (80*x 139 | mul bx 140 | add ax,word[y] ; (80*x+y) 141 | mov bx,2 142 | mul bx ; ((80*x+y)*2) 143 | mov bp,ax 144 | mov ah,0ch ; 0000:黑底、1111:亮白字(默认值为07h) 145 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 146 | mov word[gs:bp],ax ; 显示字符的ASCII码值 147 | 148 | 149 | end: 150 | ret 151 | 152 | 153 | jmp $ 154 | 155 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 156 | ; 写入启动扇区的结束标志 157 | ;db 55h,0aah 158 | 159 | 160 | ;******************************************************************************************************** 161 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 162 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 163 | ;* 164 | ;******************************************************************************************************** 165 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/process4.asm: -------------------------------------------------------------------------------- 1 | ;;********************************************************************************** 2 | ;; 程序功能:利用时钟中断,在显示框右下角画框 3 | ;; 程序原作:凌应标 4 | ;; 程序修改:廖锦城 5 | ;; 修改时间:2013-04-15 6 | ;;********************************************************************************** 7 | 8 | delay equ 2000 ; 计时器延迟计数,用于控制画框的速度 9 | ddelay equ 580 ; 计时器延迟计数,用于控制画框的速度 10 | 11 | 12 | org 100h ; 程序加载到100h,可用于生成COM 13 | 14 | ;初始化段寄存器 15 | mov ax,400 ; AX = 0 16 | mov es,ax ; ES = 0 17 | mov ds,ax ; DS = CS 18 | mov ax,0B800h ; 文本窗口显存起始地址 19 | mov gs,ax ; GS = B800h 20 | mov word[count],delay 21 | mov word[dcount],ddelay 22 | 23 | mov word[x],13 24 | mov word[y],40 25 | mov byte[rdlu], 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 26 | mov word[char],'A' 27 | 28 | loop1: 29 | dec word[count] ; 递减计数变量 30 | jnz loop1 ; >0:跳转; 31 | mov word[count],delay 32 | dec word[dcount] ; 递减计数变量 33 | jnz loop1 34 | call boxing 35 | mov word[count],delay 36 | mov word[dcount],ddelay 37 | jmp loop1 38 | 39 | jmp $ ; 死循环 40 | 41 | datadef: 42 | 43 | count dw delay ; 计时器计数变量,初值=delay 44 | dcount dw ddelay ; 计时器计数变量,初值=delay 45 | x dw 13 ; 当前字符显示位置的行号,0~24 46 | y dw 40 ; 当前字符显示位置的列号,0~79 47 | rdlu db 1 ; 当前画框的方向, 1-向右,2-向下,3-向左,4-向上 48 | char db 'A' ; 当前显示字符 49 | 50 | 51 | boxing: 52 | 53 | right: 54 | mov al,byte[rdlu] ;左-->右 55 | cmp al,1 56 | jnz down 57 | mov ax,word[y] ;最后一列? 58 | cmp ax, 79 59 | jz r2d 60 | inc byte[y] 61 | jmp show 62 | r2d: 63 | mov byte[rdlu],2 ;改为向下 64 | inc byte[x] 65 | jmp show 66 | 67 | down: 68 | mov al,byte[rdlu] ;向下 69 | cmp al,2 70 | jnz left 71 | mov ax,word[x] ;最后一行? 72 | cmp ax, 24 73 | jz d2l 74 | inc byte[x] 75 | jmp show 76 | d2l: 77 | mov byte[rdlu],3 ;改为向左 78 | dec byte[y] 79 | jmp show 80 | 81 | left: 82 | mov al,byte[rdlu] ;向左 83 | cmp al,3 84 | jnz up 85 | mov ax,word[y] ;最左一列? 86 | cmp ax, 40 87 | jz l2u 88 | dec byte[y] 89 | jmp show 90 | l2u: 91 | mov byte[rdlu],4 ;改为向 上 92 | dec byte[x] 93 | jmp show 94 | 95 | up: 96 | mov al,byte[rdlu] ;向上 97 | cmp al,4 98 | jnz end 99 | mov ax,word[x] ;最上一行? 100 | cmp ax, 13 101 | jz u2r 102 | dec byte[x] 103 | jmp show 104 | u2r: 105 | mov byte[rdlu],1 ;改为向右 106 | inc byte[y] 107 | mov al,byte[char] 108 | cmp al,'Z' 109 | jz returntoa 110 | inc byte[char] 111 | jmp show 112 | 113 | returntoa: 114 | mov byte[char],'A' 115 | jmp show 116 | 117 | show: 118 | xor ax,ax ; 计算当前字符的显存地址 gs:((80*x+y)*2) 119 | mov ax,word[x] 120 | mov bx,80 ; (80*x 121 | mul bx 122 | add ax,word[y] ; (80*x+y) 123 | mov bx,2 124 | mul bx ; ((80*x+y)*2) 125 | mov bp,ax 126 | mov ah,0eh ; 0000:黑底、1111:亮白字(默认值为07h) 127 | mov al,byte[char] ; AL = 显示字符值(默认值为20h=空格符) 128 | mov word[gs:bp],ax ; 显示字符的ASCII码值 129 | 130 | 131 | end: 132 | ret 133 | 134 | 135 | jmp $ 136 | 137 | ;times 512-($-$$) db 0 ; $=当前地址、$$=当前节地址 138 | ; 写入启动扇区的结束标志 139 | ;db 55h,0aah 140 | 141 | 142 | ;******************************************************************************************************** 143 | ;* 修改一: 本程序画框是顺时针的,请把方向改为逆时间 144 | ;* 修改二: 本程序画框重复画最大的框,请改为先画最大的框,之后在所画的框内画最大的框,如此反复,直到画满屏幕 145 | ;* 146 | ;******************************************************************************************************** 147 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/user.asm: -------------------------------------------------------------------------------- 1 | ;************************************************** 2 | ;* 程序版本信息 * 3 | ;************************************************** 4 | 5 | extrn _main:near 6 | 7 | .8086 8 | _TEXT segment byte public 'CODE' 9 | assume cs:_TEXT 10 | DGROUP group _TEXT,_DATA,_BSS 11 | org 100h 12 | start: 13 | 14 | mov ax, cs 15 | mov ds, ax ; DS = CS 16 | mov es, ax ; ES = CS 17 | mov ss, ax ; SS = cs 18 | mov sp, 100h ; SP指向本段高端-4 19 | call near ptr _main ; 调用C语言程序cmain() 20 | jmp $ 21 | 22 | _TEXT ends 23 | _DATA segment word public 'DATA' 24 | _DATA ends 25 | _BSS segment word public 'BSS' 26 | _BSS ends 27 | end start 28 | 29 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/user.c: -------------------------------------------------------------------------------- 1 | extern int fork(); 2 | extern int wait(); 3 | extern void exit(); 4 | 5 | #include "user_lib.h" 6 | 7 | char str[80] = "129djwqhdsajd128dw9i39ie93i8494urjoiew98kdkd"; 8 | int LetterNr = 0; 9 | 10 | void main() 11 | { 12 | int pid; 13 | char ch; 14 | print("In the user:before fork\r\n"); 15 | pid = fork(); 16 | print("In the user:after fork\r\n"); 17 | print("The pid is:");printInt(pid);print("\r\n"); 18 | if(pid == -1) exit(-1); 19 | if(pid) 20 | { 21 | print("In the user:before wait\r\n"); 22 | ch = wait(); 23 | print("In the user:after wait\r\n"); 24 | print("LetterNr="); 25 | printInt(LetterNr); 26 | print("\r\n"); 27 | exit(0); 28 | } 29 | else 30 | { 31 | print("In the user:sub process is running\r\n"); 32 | LetterNr = strlen(str); 33 | print("In the user:before exit\r\n"); 34 | exit(0); 35 | print("In the user:after exit\r\n"); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/user_lib.asm: -------------------------------------------------------------------------------- 1 | ; 用于生成库文件 2 | .8086 3 | _TEXT segment byte public 'CODE' 4 | assume cs:_TEXT 5 | DGROUP group _TEXT,_DATA,_BSS 6 | start: 7 | 8 | ;************ ***************************** 9 | ; *SCOPY@ * 10 | ;****************** *********************** 11 | ; 实参为局部字符串带初始化异常问题的补钉程序 12 | public SCOPY@ 13 | SCOPY@ proc 14 | arg_0 = dword ptr 6 15 | arg_4 = dword ptr 0ah 16 | push bp 17 | mov bp,sp 18 | push si 19 | push di 20 | push ds 21 | lds si,[bp+arg_0] 22 | les di,[bp+arg_4] 23 | cld 24 | shr cx,1 25 | rep movsw 26 | adc cx,cx 27 | rep movsb 28 | pop ds 29 | pop di 30 | pop si 31 | pop bp 32 | retf 8 33 | SCOPY@ endp 34 | 35 | ;*************** ******************** 36 | ;* int _fork() * 37 | ;**************** ******************* 38 | ; 39 | public _fork 40 | _fork proc 41 | mov ah,6 42 | int 21h 43 | ret 44 | _fork endp 45 | 46 | ;*************** ******************** 47 | ;* int _wait() * 48 | ;**************** ******************* 49 | ; 50 | public _wait 51 | _wait proc 52 | mov ah,7 53 | int 21h 54 | ret 55 | _wait endp 56 | 57 | ;*************** ******************** 58 | ;* void _exit() * 59 | ;**************** ******************* 60 | ; 61 | public _exit 62 | _exit proc 63 | push bp 64 | mov bp,sp 65 | push bx 66 | 67 | mov ah,8 68 | mov bx,[bp+4] 69 | int 21h 70 | 71 | pop bx 72 | pop bp 73 | 74 | ret 75 | _exit endp 76 | 77 | ;*************** ******************** 78 | ;* void _cls() * 79 | ;**************** ******************* 80 | ; 清屏 81 | public _cls 82 | _cls proc 83 | mov ax,0003H 84 | int 10h ; 显示中断 85 | ret 86 | _cls endp 87 | 88 | ;**** *********************************** 89 | ;* void _PrintChar() * 90 | ;******* ******************************** 91 | ; 字符输出 92 | public _printChar 93 | _printChar proc 94 | push bp 95 | mov bp,sp 96 | push ax 97 | push bx 98 | ;*** 99 | mov al,[bp+4] 100 | mov bl,0 101 | mov ah,0eh 102 | int 10h 103 | ;*** 104 | pop bx 105 | pop ax 106 | mov sp,bp 107 | pop bp 108 | ret 109 | _printChar endp 110 | 111 | ;*********** **************************** 112 | ;* void _GetChar() * 113 | ;****************** ********************* 114 | ; 读入一个字符 115 | public _getChar 116 | _getChar proc 117 | mov ah,0 118 | int 16h 119 | ret 120 | _getChar endp 121 | 122 | ;*************** ******************** 123 | ;* void _delay() * 124 | ;**************** ******************* 125 | ; 延迟 126 | public _delay 127 | _delay proc 128 | push bp 129 | mov bp,sp 130 | push cx 131 | 132 | mov cx,word ptr[bp+4] 133 | delay_Continue: 134 | mov word ptr es:[t],cx ; 把 cx 的值保存到 t 中 135 | mov cx,word ptr [bp+4] 136 | delay_loop:loop delay_loop 137 | mov cx,word ptr es:[t] ; 把 t 的值放回 cx ,恢复 cx 138 | loop delay_Continue 139 | 140 | pop cx 141 | pop bp 142 | ret 143 | _delay endp 144 | 145 | t dw 0 146 | ;*************** ******************** 147 | ;* void _gettime() * 148 | ;**************** ******************* 149 | ; 获取时间 150 | public _backspace 151 | _backspace proc 152 | push ax 153 | push bx 154 | push cx 155 | push dx 156 | 157 | ;读光标位置,(dh,dl) = (行,列) 158 | mov bh,0 159 | mov ah,3h 160 | int 10h 161 | 162 | add dl,-1 163 | 164 | ;设置光标位置(dh,dl) = (行,列) 165 | mov bh,0 166 | mov ah,2h 167 | int 10h 168 | 169 | mov al,' ' 170 | mov bl,1 171 | mov ah,0eh 172 | int 10h 173 | 174 | ;设置光标位置(dh,dl) = (行,列) 175 | mov bh,0 176 | mov ah,2h 177 | int 10h 178 | 179 | pop dx 180 | pop cx 181 | pop bx 182 | pop ax 183 | ret 184 | _backspace endp 185 | 186 | 187 | _TEXT ends 188 | _DATA segment word public 'DATA' 189 | _DATA ends 190 | _BSS segment word public 'BSS' 191 | _BSS ends 192 | end start 193 | -------------------------------------------------------------------------------- /Lab09/src/用户程序/user_lib.h: -------------------------------------------------------------------------------- 1 | extern void cls(); 2 | extern char getchar(); 3 | extern void delay(int t); 4 | extern void printchar(); 5 | extern void backspace(); 6 | 7 | char input[100],output[100],t_char[100]; 8 | 9 | void reverse(char str[],int len) 10 | { 11 | /* 12 | * 将字符串反转 13 | */ 14 | int i; 15 | for(i = 0;i < len;++i) 16 | { 17 | t_char[i] = str[len-i-1]; 18 | } 19 | for(i = 0;i < len;++i) 20 | { 21 | str[i] = t_char[i]; 22 | } 23 | } 24 | 25 | int strlen(char str[]) 26 | { 27 | /* 28 | * 获取字符串长度 29 | */ 30 | int i = 0; 31 | while(str[i] != '\0') 32 | { 33 | i++; 34 | } 35 | return i; 36 | } 37 | 38 | void print(char *p) 39 | { 40 | /* 41 | * 输出字符串 p 42 | */ 43 | while(*p != '\0') 44 | { 45 | printChar(*p); 46 | p++; 47 | } 48 | } 49 | 50 | int getline(char arr[],int maxLen) 51 | { 52 | /* 53 | * 读取用户输入的一行 54 | */ 55 | 56 | int i = 0; 57 | char in; 58 | if(maxLen == 0) 59 | { 60 | return 0; 61 | } 62 | in = getchar(); 63 | while(in != '\n'&& in != '\r') 64 | { 65 | /* 66 | * 判断是不是回车键 67 | */ 68 | int k = in; 69 | if(k == 8) 70 | { 71 | /* 72 | * 判断是不是退格键 73 | */ 74 | i--; 75 | backspace(); 76 | in = getchar(); 77 | continue; 78 | } 79 | printChar(in); 80 | arr[i++] = in; 81 | if(i == maxLen) 82 | { 83 | /* 84 | * 是否达到允许输入的最大长度 85 | */ 86 | arr[i] = '\0'; 87 | printChar('\n'); 88 | return 0; 89 | } 90 | in = getchar(); 91 | } 92 | arr[i] = '\0'; 93 | print("\n\r"); 94 | return 1; 95 | } 96 | 97 | void printInt(int ans) 98 | { 99 | /* 100 | * 打印一个整数到屏幕 101 | */ 102 | int i = 0; 103 | if(ans == 0) 104 | { 105 | output[0] = '0'; 106 | i++; 107 | } 108 | while(ans) 109 | { 110 | int t = ans%10; 111 | output[i++] = '0'+t; 112 | ans/=10; 113 | } 114 | reverse(output,i); 115 | output[i] = '\0'; 116 | print(output); 117 | } 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本项目为从零开始做操作系统,前期为纯汇编 nasm 实现,后期采用 tasm + C 实现。 2 | 3 | Lab 01 4 | 设计一个引导扇区程序,程序功能是:用字符‘A’从屏幕左边某行位置45度角下斜射出,保持一个可观察的 5 | 适当速度直线运动,碰到下边后反射,如此类推,不断运动 6 | 7 | Lab 02 8 | 设计满足下列要求的原型操作系统: 9 | 10 | 1.用户程序大小不等,但最大不超过5个扇区。 11 | 12 | 2.允许用控制台命令指定一组要执行的用户程序。比如,磁盘上有3个用户程序,可以用命令指定按某顺序 13 | 运行其中1个、2个或3个程序。 14 | 15 | Lab 03 16 | 设计满足下列要求的原型操作系统: 17 | 18 | (1)用引导程序加载的MYOS内核 19 | 20 | (2)内核由汇编语言kernal.asm和c语言kernal.c二个模块生成; 21 | 22 | (3)实现作业控制语言mJCB,原型操作系统在当前行显示一个指示符(可以是简单的一个字符或你的学号之类), 23 | 允许用户输入一行命令(回车结束,语法由你设计),操作系统解释命令并完成相应的功能(3个以上的内置 24 | 功能,如time、date、asc等,而且能执行软盘上的某个用户程序)。 25 | 26 | Lab 04 27 | 设计满足下列要求的原型操作系统: 28 | (1)操作系统工作期间,在屏幕24行79列位置轮流显示’|’、’/’和’\’,适当控制显示速度,以方便 29 | 观察效果。 30 | 31 | (2)用户程序运行时,键盘事件有事反应:当键盘有按键时,屏幕适当位置显示”OUCH! OUCH!”。 32 | 33 | (3)在内核中,对33号、34号、35号和36号中断编写中断服务程序,程序服务是分别在屏幕1/4区域内显示 34 | 一些个性化信息。再编写一个汇编语言的程序,利用int 33、int 34、int 35和int 36产生中断调用你这 35 | 4个服务程序。 36 | 37 | Lab 05 38 | 改进你的原型操作系统,满足下列要求: 39 | 40 | (1)参考下面的系统调用功能表,增加3个其他功能 41 | 42 | (2)扩展MYOS内核,实现上表中的所有(包括你增加的)系统调用; 43 | 44 | (3)设计C程序库,实现系统调用的封装,并开发一个测试系统调用所有功能的C程序。 45 | 46 | Lab 06 47 | 保留原型原有特征的基础上,设计满足下列要求的新原型操作系统: 48 | 49 | (1) 在c程序中定义进程表,进程数量最多4个。 50 | 51 | (2) 内核一次性加载4个用户程序运行时,采用时间片轮转调度进程运行,用户程序的输出各占1/4屏幕 52 | 区域,信息输出有动感,以便观察程序是否在执行。 53 | 54 | (3) 在原型中保证原有的系统调用服务可用。再编写4个用户程序,展示系统调用服务还能工作。 55 | 56 | Lab 07 57 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 58 | 59 | (1)实现fork()、wait()和exit()。 60 | 61 | (2)内核实现上面三系统调用,并在c库中封装相关的系统调用. 62 | 63 | (3)编写一个c语言程序,实现多进程合作的应用程序。 64 | 65 | 可以在下面的基础上完成:一个简单的应用程序例,父进程生成一个字符串,交给子进程统计其中字母的 66 | 个数,然后在父进程中输出这一统计结果。 67 | 68 | Lab 08 69 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 70 | 71 | (1) 实现信号量机制。 72 | 73 | (2) 内核实现信号量机制后,在c库中封装相关的系统调用. 74 | 75 | (3) 编写一个c语言程序,实现有限缓冲的生产者-消费者模型的应用程序。 76 | 77 | 编译连接你编写的用户程序,产生一个com文件,放进程原型操作系统映像盘中。 78 | 79 | Lab 09 80 | 原型保留原有特征的基础上,设计满足下列要求的新原型操作系统: 81 | 82 | (1) 映像文件满足FAT12格式。 83 | 84 | (2) 内核以文件形式存放在映像的FAT12文件系统中,修改引导程序实现内核的加载. 85 | 86 | (3) 将所有测试的用户程序放在在映像文件中的FAT12文件系统中,修改内核,实现从文件系统加载 87 | 用户程序。 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /tools/LINK.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/tools/LINK.EXE -------------------------------------------------------------------------------- /tools/TASM.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/tools/TASM.EXE -------------------------------------------------------------------------------- /tools/TCC.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/tools/TCC.EXE -------------------------------------------------------------------------------- /tools/TLINK.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/tools/TLINK.EXE -------------------------------------------------------------------------------- /tools/nasm.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AngryHacker/OS_Lab/63d9e933f4ee442d077d78940103c87a55bb0d7b/tools/nasm.exe --------------------------------------------------------------------------------