本文始作于2012年1月22日,刊登于人人网,于2013年2月13日迁移至此
现在是早上4:24,今天忙活了一宿,把setup.s大体轮廓作出来了,只是刚刚达到要求的合格品,明天还要继续改进,要把所有信息都进行输出才算完满。我在写输出的时候不明白什么是页号,后来百度,虽然还是不太明白,但是知道该怎么填了,像Bios这样低端的部分肯定用0。
bios中断中的页号:
页就是将显示内存分成N份,每份叫一页.这是一种简化的说法,事实上根据硬件的不同有些小区别.
它的产生是因为显存大于内存分配给显存的映射空间.一般在文本模式下只有一页,因此总是用第0页就可以了.
在图形模式下需要计算出屏幕上某个位置处在显存的第几页,并进行换页操作才能写入指定位置.
可以看看VGA编程方面的相关资料.
完成功能:setup.s在运行开始向屏幕输出一串字符串“Now we are in SETUP”;能判断出有没有第二快硬盘,并将结果输出。其实原内核已经可以判断出来了,我做的只是在适当的地方插入输出语句和必要的跳转。
源代码如下:
1 ! 2 ! setup.s (C) 1991 Linus Torvalds 3 ! 4 ! setup.s is responsible for getting the system data from the BIOS, 5 ! and putting them into the appropriate places in system memory. 6 ! both setup.s and system has been loaded by the bootblock. 7 ! 8 ! This code asks the bios for memory/disk/other parameters, and 9 ! puts them in a "safe" place: 0x90000-0x901FF, ie where the 10 ! boot-block used to be. It is then up to the protected mode 11 ! system to read them from there before the area is overwritten 12 ! for buffer-blocks. 13 ! 14 15 ! NOTE! These had better be the same as in bootsect.s! 16 17 INITSEG = 0x9000 ! we move boot here - out of the way 18 SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). 19 SETUPSEG = 0x9020 ! this is the current segment 20 21 .globl begtext, begdata, begbss, endtext, enddata, endbss 22 .text 23 begtext: 24 .data 25 begdata: 26 .bss 27 begbss: 28 .text 29 30 entry start 31 start: 32 33 ! Show some message 34 35 mov ax,#SETUPSEG 36 mov es,ax 37 38 mov ah,#0x03 ! read cursor pos 39 xor bh,bh 40 int 0x10 41 42 mov cx,#19 43 mov bx,#0x0007 44 mov bp,#message 45 mov ax,#0x1301 46 int 0x10 47 48 mov ax,#0xe0d 49 int 0x10 50 mov al,#0x0a 51 int 0x10 52 mov ax,#0xe0d 53 int 0x10 54 mov al,#0x0a 55 int 0x10 56 57 ! ok, the read went well so we get current cursor position and save it for 58 ! posterity. 59 60 mov ax,#INITSEG ! this is done in bootsect already, but... 61 mov ds,ax 62 mov ah,#0x03 ! read cursor pos 63 xor bh,bh 64 int 0x10 ! save it in known place, con_init fetches 65 mov [0],dx ! it from 0x90000. 66 67 ! Get memory size (extended mem, kB) 68 69 mov ah,#0x88 70 int 0x15 71 mov [2],ax 72 73 ! Get video-card data: 74 75 mov ah,#0x0f 76 int 0x10 77 mov [4],bx ! bh = display page 78 mov [6],ax ! al = video mode, ah = window width 79 80 ! check for EGA/VGA and some config parameters 81 82 mov ah,#0x12 83 mov bl,#0x10 84 int 0x10 85 mov [8],ax 86 mov [10],bx 87 mov [12],cx 88 89 ! Get hd0 data 90 91 mov ax,#0x0000 92 mov ds,ax 93 lds si,[4*0x41] 94 mov ax,#INITSEG 95 mov es,ax 96 mov di,#0x0080 97 mov cx,#0x10 98 rep 99 movsb 100 101 ! Get hd1 data 102 103 mov ax,#0x0000 104 mov ds,ax 105 lds si,[4*0x46] 106 mov ax,#INITSEG 107 mov es,ax 108 mov di,#0x0090 109 mov cx,#0x10 110 rep 111 movsb 112 113 ! Check that there IS a hd1 :-) 114 115 mov ax,#0x01500 116 mov dl,#0x81 117 int 0x13 118 jc no_disk1 119 cmp ah,#3 120 je is_disk1 121 122 no_disk1: 123 124 ! Show some message 125 126 mov ax,#SETUPSEG 127 mov es,ax 128 129 mov ah,#0x03 ! read cursor pos 130 xor bh,bh 131 int 0x10 132 133 mov cx,#15 134 mov bx,#0x0007 135 mov bp,#no 136 mov ax,#0x1301 137 int 0x10 138 139 mov ax,#0xe0d 140 int 0x10 141 mov al,#0x0a 142 int 0x10 143 int 0x10 144 int 0x10 145 int 0x10 146 int 0x10 147 148 mov ax,#INITSEG 149 mov es,ax 150 mov di,#0x0090 151 mov cx,#0x10 152 mov ax,#0x00 153 rep 154 stosb 155 156 jmp exit 157 158 is_disk1: 159 160 ! Show some message 161 162 mov ax,#SETUPSEG 163 mov es,ax 164 165 mov ah,#0x03 ! read cursor pos 166 xor bh,bh 167 int 0x10 168 169 mov cx,#12 170 mov bx,#0x0007 171 mov bp,#exist 172 mov ax,#0x1301 173 int 0x10 174 175 mov ax,#0xe0d 176 int 0x10 177 mov al,#0x0a 178 int 0x10 179 int 0x10 180 int 0x10 181 int 0x10 182 int 0x10 183 184 exit: 185 186 ! now we want to move to protected mode ... 187 188 cli ! no interrupts allowed ! 189 190 ! first we move the system to it's rightful place 191 192 mov ax,#0x0000 193 cld ! 'direction'=0, movs moves forward 194 do_move: 195 mov es,ax ! destination segment 196 add ax,#0x1000 197 cmp ax,#0x9000 198 jz end_move 199 mov ds,ax ! source segment 200 sub di,di 201 sub si,si 202 mov cx,#0x8000 203 rep 204 movsw 205 jmp do_move 206 207 ! then we load the segment descriptors 208 209 end_move: 210 mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-) 211 mov ds,ax 212 lidt idt_48 ! load idt with 0,0 213 lgdt gdt_48 ! load gdt with whatever appropriate 214 215 ! that was painless, now we enable A20 216 217 call empty_8042 218 mov al,#0xD1 ! command write 219 out #0x64,al 220 call empty_8042 221 mov al,#0xDF ! A20 on 222 out #0x60,al 223 call empty_8042 224 225 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-( 226 ! we put them right after the intel-reserved hardware interrupts, at 227 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really 228 ! messed this up with the original PC, and they haven't been able to 229 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, 230 ! which is used for the internal hardware interrupts as well. We just 231 ! have to reprogram the 8259's, and it isn't fun. 232 233 mov al,#0x11 ! initialization sequence 234 out #0x20,al ! send it to 8259A-1 235 .word 0x00eb,0x00eb ! jmp $+2, jmp $+2 236 out #0xA0,al ! and to 8259A-2 237 .word 0x00eb,0x00eb 238 mov al,#0x20 ! start of hardware int's (0x20) 239 out #0x21,al 240 .word 0x00eb,0x00eb 241 mov al,#0x28 ! start of hardware int's 2 (0x28) 242 out #0xA1,al 243 .word 0x00eb,0x00eb 244 mov al,#0x04 ! 8259-1 is master 245 out #0x21,al 246 .word 0x00eb,0x00eb 247 mov al,#0x02 ! 8259-2 is slave 248 out #0xA1,al 249 .word 0x00eb,0x00eb 250 mov al,#0x01 ! 8086 mode for both 251 out #0x21,al 252 .word 0x00eb,0x00eb 253 out #0xA1,al 254 .word 0x00eb,0x00eb 255 mov al,#0xFF ! mask off all interrupts for now 256 out #0x21,al 257 .word 0x00eb,0x00eb 258 out #0xA1,al 259 260 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't 261 ! need no steenking BIOS anyway (except for the initial loading :-). 262 ! The BIOS-routine wants lots of unnecessary data, and it's less 263 ! "interesting" anyway. This is how REAL programmers do it. 264 ! 265 ! Well, now's the time to actually move into protected mode. To make 266 ! things as simple as possible, we do no register set-up or anything, 267 ! we let the gnu-compiled 32-bit programs do that. We just jump to 268 ! absolute address 0x00000, in 32-bit protected mode. 269 mov ax,#0x0001 ! protected mode (PE) bit 270 lmsw ax ! This is it! 271 jmpi 0,8 ! jmp offset 0 of segment 8 (cs) 272 273 ! This routine checks that the keyboard command queue is empty 274 ! No timeout is used - if this hangs there is something wrong with 275 ! the machine, and we probably couldn't proceed anyway. 276 empty_8042: 277 .word 0x00eb,0x00eb 278 in al,#0x64 ! 8042 status port 279 test al,#2 ! is input buffer full? 280 jnz empty_8042 ! yes - loop 281 ret 282 283 gdt: 284 .word 0,0,0,0 ! dummy 285 286 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) 287 .word 0x0000 ! base address=0 288 .word 0x9A00 ! code read/exec 289 .word 0x00C0 ! granularity=4096, 386 290 291 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) 292 .word 0x0000 ! base address=0 293 .word 0x9200 ! data read/write 294 .word 0x00C0 ! granularity=4096, 386 295 296 message: ! 19byte 297 .ascii "Now we are in SETUP" 298 299 exist: ! 12byte 300 .ascii "There is hd1" 301 302 no: ! 15byte 303 .ascii "There isn't hd1" 304 ! .byte 13,10,13,10 305 306 idt_48: 307 .word 0 ! idt limit=0 308 .word 0,0 ! idt base=0L 309 310 gdt_48: 311 .word 0x800 ! gdt limit=2048, 256 GDT entries 312 .word 512+gdt,0x9 ! gdt base = 0X9xxxx 313 314 .text 315 endtext: 316 .data 317 enddata: 318 .bss 319 endbss: