读书笔记《30天自制操作系统》day03

来源:互联网 发布:老公 知乎 编辑:程序博客网 时间:2024/05/20 09:26

http://blog.csdn.net/ltbylc/article/details/8309257


0. 自己试着在win7下用NASM和minGW改写汇编和C混合编程,结果受挫了。还是先使用作者提供的工具构建吧。

1. 通过前2天的工作已经能使用NASM制作一个映像了,并且编写的汇编代码可以成为引导扇区代码。

2. 引导扇区代码中可以调用BIOS中断,读取软盘上其它扇区到内存中,根据FAT12文件系统格式得知,保存到软盘内的第一个文件的文件名一定从19逻辑扇区开始,且该文件的内容从逻辑扇区33开始。

3. 引导扇区可以将第一个保存的文件(kernel.sys=自己改的名字,功能是跳入保护模式并调用C语言编写的函数代码)读入内存并使之执行,找这个文件用到了一个技巧,不然通过文件系统结构分析出文件位置,并加载码就太复杂了。

4. 引导扇区代码如下ipl10.asm

[plain] view plaincopy
  1. ; haribote-ipl  
  2. ; TAB=4  
  3.   
  4. CYLS    EQU     10                
  5.   
  6.         ORG     0x7c00            
  7.   
  8.         JMP     entry  
  9.         DB      0x90  
  10.         DB      "HARIBOTE"        
  11.         DW      512               
  12.         DB      1                 
  13.         DW      1                 
  14.         DB      2                 
  15.         DW      224               
  16.         DW      2880              
  17.         DB      0xf0              
  18.         DW      9                 
  19.         DW      18                
  20.         DW      2                 
  21.         DD      0                 
  22.         DD      2880              
  23.         DB      0,0,0x29          
  24.         DD      0xffffffff        
  25.         DB      "HARIBOTEOS "     
  26.         DB      "FAT12   "        
  27.         RESB    18                
  28.   
  29.   
  30.   
  31. entry:  
  32.         MOV     AX,0              
  33.         MOV     SS,AX  
  34.         MOV     SP,0x7c00  
  35.         MOV     DS,AX  
  36.   
  37.   
  38.         MOV     AX,0x0820  
  39.         MOV     ES,AX  
  40.         MOV     CH,0              
  41.         MOV     DH,0              
  42.         MOV     CL,2              
  43. readloop:  
  44.         MOV     SI,0              
  45. retry:  
  46.         MOV     AH,0x02           
  47.         MOV     AL,1              
  48.         MOV     BX,0  
  49.         MOV     DL,0x00           
  50.         INT     0x13              
  51.         JNC     next              
  52.         ADD     SI,1              
  53.         CMP     SI,5              
  54.         JAE     error             
  55.         MOV     AH,0x00  
  56.         MOV     DL,0x00           
  57.         INT     0x13              
  58.         JMP     retry  
  59. next:  
  60.         MOV     AX,ES             
  61.         ADD     AX,0x0020  
  62.         MOV     ES,AX             
  63.         ADD     CL,1              
  64.         CMP     CL,18             
  65.         JBE     readloop          
  66.         MOV     CL,1  
  67.         ADD     DH,1  
  68.         CMP     DH,2  
  69.         JB      readloop          
  70.         MOV     DH,0  
  71.         ADD     CH,1  
  72.         CMP     CH,CYLS  
  73.         JB      readloop          
  74.   
  75.   
  76.         MOV     [0x0ff0],CH       
  77.         JMP     0xc200  
  78.   
  79. error:  
  80.         MOV     SI,msg  
  81. putloop:  
  82.         MOV     AL,[SI]  
  83.         ADD     SI,1              
  84.         CMP     AL,0  
  85.         JE      fin  
  86.         MOV     AH,0x0e           
  87.         MOV     BX,15             
  88.         INT     0x10              
  89.         JMP     putloop  
  90. fin:  
  91.         HLT                       
  92.         JMP     fin               
  93. msg:  
  94.         DB      0x0a, 0x0a        
  95.         DB      "load error"  
  96.         DB      0x0a              
  97.         DB      0  
  98.   
  99.         ;RESB   0x7dfe-$          
  100.         times 510-($-$$) db 0  
  101.   
  102.         DB      0x55, 0xaa  


 

5. 跳入保护模式代码如下asmhead.nas

(1)准备GDT

(2)用LGDT加载gdtr

(3)打开A20

(4)设置CR0的PE位

(5)跳转进入保护模式

[plain] view plaincopy
  1. ; haribote-os boot asm  
  2. ; TAB=4  
  3.   
  4. BOTPAK  EQU     0x00280000        
  5. DSKCAC  EQU     0x00100000        
  6. DSKCAC0 EQU     0x00008000        
  7.   
  8.   
  9. CYLS    EQU     0x0ff0            
  10. LEDS    EQU     0x0ff1  
  11. VMODE   EQU     0x0ff2            
  12. SCRNX   EQU     0x0ff4            
  13. SCRNY   EQU     0x0ff6            
  14. VRAM    EQU     0x0ff8            
  15.   
  16.         ORG     0xc200   ;让引导扇区加载后从这里开始运行         
  17.   
  18.   
  19.   
  20.         MOV     AL,0x13     ;保存信息     
  21.         MOV     AH,0x00  
  22.         INT     0x10  
  23.         MOV     BYTE [VMODE],8    
  24.         MOV     WORD [SCRNX],320  
  25.         MOV     WORD [SCRNY],200  
  26.         MOV     DWORD [VRAM],0x000a0000  
  27.   
  28.   
  29.         MOV     AH,0x02  
  30.         INT     0x16            ; keyboard BIOS  
  31.         MOV     [LEDS],AL  
  32.   
  33.   
  34.         MOV     AL,0xff  
  35.             OUT     0x21,AL  
  36.         NOP                       
  37.         OUT     0xa1,AL  
  38.   
  39.         CLI                       
  40.   
  41.   
  42.   
  43.         CALL    waitkbdout  
  44.         MOV     AL,0xd1  
  45.         OUT     0x64,AL  
  46.         CALL    waitkbdout  
  47.         MOV     AL,0xdf         ; enable A20  
  48.         OUT     0x60,AL  
  49.         CALL    waitkbdout  
  50.   
  51.   
  52. [INSTRSET "i486p"]                
  53.   
  54.         LGDT    [GDTR0]           
  55.         MOV     EAX,CR0  
  56.         AND     EAX,0x7fffffff    
  57.         OR      EAX,0x00000001    
  58.         MOV     CR0,EAX  
  59.         JMP     pipelineflush  
  60. pipelineflush:  
  61.         MOV     AX,1*8            
  62.         MOV     DS,AX  
  63.         MOV     ES,AX  
  64.         MOV     FS,AX  
  65.         MOV     GS,AX  
  66.         MOV     SS,AX  
  67.   
  68.   
  69.   
  70.         MOV     ESI,bootpack      
  71.         MOV     EDI,BOTPAK        
  72.         MOV     ECX,512*1024/4  
  73.         CALL    memcpy  
  74.   
  75.   
  76.   
  77.         MOV     ESI,0x7c00        
  78.         MOV     EDI,DSKCAC        
  79.         MOV     ECX,512/4  
  80.         CALL    memcpy  
  81.   
  82.   
  83.         MOV     ESI,DSKCAC0+512   
  84.         MOV     EDI,DSKCAC+512    
  85.         MOV     ECX,0  
  86.         MOV     CL,BYTE [CYLS]  
  87.         IMUL    ECX,512*18*2/4    
  88.         SUB     ECX,512/4         
  89.         CALL    memcpy  
  90.   
  91.   
  92.         MOV     EBX,BOTPAK  
  93.         MOV     ECX,[EBX+16]  
  94.         ADD     ECX,3             
  95.         SHR     ECX,2             
  96.         JZ      skip              
  97.         MOV     ESI,[EBX+20]      
  98.         ADD     ESI,EBX  
  99.         MOV     EDI,[EBX+12]      
  100.         CALL    memcpy  
  101. skip:  
  102.         MOV     ESP,[EBX+12]      
  103.         JMP     DWORD 2*8:0x0000001b  
  104.   
  105. waitkbdout:  
  106.         IN       AL,0x64  
  107.         AND      AL,0x02  
  108.         JNZ     waitkbdout        
  109.         RET  
  110.   
  111. memcpy:  
  112.         MOV     EAX,[ESI]  
  113.         ADD     ESI,4  
  114.         MOV     [EDI],EAX  
  115.         ADD     EDI,4  
  116.         SUB     ECX,1  
  117.         JNZ     memcpy            
  118.         RET  
  119.   
  120.   
  121.         ALIGNB  16  
  122. GDT0:  
  123.         RESB    8                 
  124.         DW      0xffff,0x0000,0x9200,0x00cf   
  125.         DW      0xffff,0x0000,0x9a28,0x0047   
  126.   
  127.         DW      0  
  128. GDTR0:  
  129.         DW      8*3-1  
  130.         DD      GDT0  
  131.   
  132.         ALIGNB  16  
  133. bootpack:  

6. C语言代码如下bootpack.c

[cpp] view plaincopy
  1. void io_hlt(void);  
  2. void write_mem8(int addr,int data);  
  3. void HariMain(void)  
  4. {  
  5.     int i;  
  6.     for(i=0xa0000;i<=0xaffff;i++)  
  7.     {  
  8.         write_mem8(i,15);  
  9.     }  
  10.     for(;;)  
  11.     {  
  12.         io_hlt();  
  13.     }  
  14.   
  15. }  


7. C语言中调用的io_hlt和write_mem8函数放到了如下代码中func.asm

[plain] view plaincopy
  1. [FORMAT "WCOFF"]                  
  2. [INSTRSET "i486p"]            
  3. [BITS 32]                         
  4. [FILE "naskfunc.nas"]             
  5. global _io_hlt,_write_mem8  
  6. [section .text]  
  7. ;void io_hlt(void);  
  8. _io_hlt:  
  9.     HLT  
  10.     RET  
  11.       
  12. ;void write_mem8(int addr,int data);  
  13. _write_mem8:  
  14.     MOV ECX,[ESP+4]  
  15.     MOV AL,[ESP+8]  
  16.     MOV [ECX],AL  
  17.     RET  

8. 在toolset文件夹内建立一个新文件夹,将上面所有的文件放在里边,编译链接接上面的文件,写个bat文件如下

[plain] view plaincopy
  1. nasm -o ipl10.bin ipl10.asm  
  2. nasm -o img.img img.asm  
  3. ..\z_tools\nask.exe asmhead.nas asmhead.bin  
  4. ..\z_tools\cc1.exe -I..\z_tools\haribote\ -Os -Wall -quiet -o bootpack.gas bootpack.c  
  5. ..\z_tools\gas2nask.exe -a bootpack.gas bootpack.nas  
  6. ..\z_tools\nask.exe bootpack.nas bootpack.obj  
  7. ..\z_tools\nask.exe func.asm func.obj  
  8. ..\z_tools\obj2bim.exe @..\z_tools\haribote\haribote.rul out:bootpack.bim stack:3136k map:bootpack.map bootpack.obj func.obj  
  9. ..\z_tools\bim2hrb.exe bootpack.bim bootpack.hrb 0  
  10. copy /B asmhead.bin+bootpack.hrb kernel.sys  


9.这样除了中间文件外,生成img.img文件和kernel.sys文件。使用winImage打开img.img文件将kernel.sys文件加入到该img文件中。

10. 启动Bochs,呵呵看见屏幕白了,这可是从C代码里控制的啊!

11. asmhead中跳入保护模式的代码慢慢在深入掌握,不然会掉入细节里不能自拔了。

12. asmhead和C代码是通过copy /B进行链接的其中asmhead代码最后留了个标号bootpack,在这个标号后面C的目标代码被砍去文件头直接将代码链接到了这里,所以能实现从汇编跳转到C语言的目的。
原创粉丝点击