일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- OS 제작
- OS
- 건프라
- rg
- os 만들기
- 쉽게 배우는 운영체제 연습문제
- 건담 엑스포
- 운영체제 문제 풀이
- 30일
- project euler
- Project Euler 해답
- hg
- 건담
- 맛집
- Gundam
- OS 강의
- 건담 프라모델
- 운영체제 정리
- 쉽게 배우는 운영체제
- OS 구조와 원리
- 운영체제
- OS강의
- Project Euler Problem
- 프라모델
- 운영체제 만들기
- 쉽게 배우는 운영체제 풀이
- 맛집 추천
- 운영체제 제작
- OS 그래픽 처리
- 쉽게 배우는 운영체제 솔루션
- Today
- Total
밤색모자이크의 개발이야기
5일차. 문자 표시와 마우스를 위한 GDT/IDT 초기화 본문
안녕하세요. 밤색모자이크입니다.
OS 개발 5일차입니다.
OS 화면 구성은 대충 끝냈고, 이번에는 문자를 표시하기 위해 파일들을 설정하고, 테스트로 표시해봅니다.
그리고 마우스를 사용하기 위해서 GDT와 IDT를 초기화를 하는 것을 배웠습니다.
세그먼테이션(Segmentation)
컴퓨터의 메모리를 각 블록단위로 분할하여, 각 블록의 처음 번지를 0으로 하여 다루는 기능입니다.
이렇게 하게 되면 복수의 프로그램을 사용할 때 메모리 이용범위가 겹치지않고 ORG를 0으로 설정하여 쉽게 사용할 수 있습니다.
세그먼트(Segment)
세그먼테이션으로 구분된 블록들을 세그먼트라고 합니다.
GDT (Global (segment) Descriptor Table)
전역 세그먼트 기술자 표라는 뜻으로, 메모리의 어딘가에 설정할 세그먼트들을 늘여세우고 놓고 그 선두 번지와 설정할 세그먼트 수를 CPU의 GDTR(Global (segment) Descriptor Table Register)에 설정해 놓는 것입니다.
즉, 세그먼트 정보를 가진다라고 생각하면 됩니다.
IDT(Interrupt Descriptor table)
외부상황(키보드, 마우스 입력 등)이나 내부에서 트러블이 일어나면 일시적으로 처리하는 기능인 인터럽트 기능을 설정하고 저장하는 것입니다. 역시 내부에 인터럽트 테이브렝 저장하겠죠.
개발환경
운영체제 : Windows10
텍스트 편집기 : Atom
PC 에뮬레이터 : QEMU
소스코드
수정된 파일
naskFunc.nas : GDT, IDT 함수 추가
Makefile : hankaku.txt을 같이 컴파일하는 것을 추가
bootpack.c : 문자 출력 함수, 마우스 형태 출력 함수, GDT, IDT 초기화 함수 추가
추가된 파일
hankaku.txt : 문자의 형태를 설정하는 기본 파일
naskFunc.nas
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | ; naskfunc ; TAB=4 [FORMAT "WCOFF"] ; 오브젝트 파일을 만드는 모드 [INSTRSET "i486p"] ; 486명령까지 사용하고 싶다고 하는 기술 [BITS 32] ; 32비트 모드용의 기계어를 만든다 [FILE "naskfunc.nas"] ; 원시 파일명 정보 GLOBAL _io_hlt, _io_cli, _io_sti, io_stihlt GLOBAL _io_in8, _io_in16, _io_in32 GLOBAL _io_out8, _io_out16, _io_out32 GLOBAL _io_load_eflags, _io_store_eflags GLOBAL _load_gdtr, _load_idtr [SECTION .text] _io_hlt: ; void io_hlt(void); HLT RET _io_cli: ; void io_cli(void); CLI RET _io_sti: ; void io_sti(void); STI RET _io_stihlt: ; void io_stihlt(void); STI HLT RET _io_in8: ; int io_in8(int port); MOV EDX,[ESP+4] ; port MOV EAX,0 IN AL,DX RET _io_in16: ; int io_in16(int port); MOV EDX,[ESP+4] ; port MOV EAX,0 IN AX,DX RET _io_in32: ; int io_in32(int port); MOV EDX,[ESP+4] ; port IN EAX,DX RET _io_out8: ; void io_out8(int port, int data); MOV EDX,[ESP+4] ; port MOV AL,[ESP+8] ; data OUT DX,AL RET _io_out16: ; void io_out16(int port, int data); MOV EDX,[ESP+4] ; port MOV EAX,[ESP+8] ; data OUT DX,AX RET _io_out32: ; void io_out32(int port, int data); MOV EDX,[ESP+4] ; port MOV EAX,[ESP+8] ; data OUT DX,EAX RET _io_load_eflags: ; int io_load_eflags(void); PUSHFD ; PUSH EFLAGS의 의미 POP EAX RET _io_store_eflags: ; void io_store_eflags(int eflags); MOV EAX,[ESP+4] PUSH EAX POPFD ; POP EFLAGS의 의미 RET _load_gdtr: ; void load_gdtr(int limit, int addr); MOV AX,[ESP+4] ; limit MOV [ESP+6],AX LGDT [ESP+6] RET _load_idtr: ; void load_idtr(int limit, int addr); MOV AX,[ESP+4] ; limit MOV [ESP+6],AX LIDT [ESP+6] RET |
13라인에 GDT와 IDT의 함수 이름을 설정하였습니다.
80라인과 86라인에 gdt와 idt를 로드하는 함수를 작성하였습니다.
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | TOOLPATH = ../z_tools/ INCPATH = ../z_tools/haribote/ MAKE = $(TOOLPATH)make.exe -r NASK = $(TOOLPATH)nask.exe CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet GAS2NASK = $(TOOLPATH)gas2nask.exe -a OBJ2BIM = $(TOOLPATH)obj2bim.exe MAKEFONT = $(TOOLPATH)makefont.exe BIN2OBJ = $(TOOLPATH)bin2obj.exe BIM2HRB = $(TOOLPATH)bim2hrb.exe RULEFILE = $(TOOLPATH)haribote/haribote.rul EDIMG = $(TOOLPATH)edimg.exe IMGTOL = $(TOOLPATH)imgtol.com COPY = copy DEL = del # 디폴트 동작 default : $(MAKE) img # 파일 생성 규칙 ipl10.bin : ipl10.nas Makefile $(NASK) ipl10.nas ipl10.bin ipl10.lst asmhead.bin : asmhead.nas Makefile $(NASK) asmhead.nas asmhead.bin asmhead.lst bootpack.gas : bootpack.c Makefile $(CC1) -o bootpack.gas bootpack.c bootpack.nas : bootpack.gas Makefile $(GAS2NASK) bootpack.gas bootpack.nas bootpack.obj : bootpack.nas Makefile $(NASK) bootpack.nas bootpack.obj bootpack.lst naskfunc.obj : naskfunc.nas Makefile $(NASK) naskfunc.nas naskfunc.obj naskfunc.lst hankaku.bin : hankaku.txt Makefile $(MAKEFONT) hankaku.txt hankaku.bin hankaku.obj : hankaku.bin Makefile $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku bootpack.bim : bootpack.obj naskfunc.obj hankaku.obj Makefile $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ bootpack.obj naskfunc.obj hankaku.obj # 3MB+64KB=3136KB bootpack.hrb : bootpack.bim Makefile $(BIM2HRB) bootpack.bim bootpack.hrb 0 haribote.sys : asmhead.bin bootpack.hrb Makefile copy /B asmhead.bin+bootpack.hrb haribote.sys haribote.img : ipl10.bin haribote.sys Makefile $(EDIMG) imgin:../z_tools/fdimg0at.tek \ wbinimg src:ipl10.bin len:512 from:0 to:0 \ copy from:haribote.sys to:@: \ imgout:haribote.img # 커맨드 img : $(MAKE) haribote.img run : $(MAKE) img $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin $(MAKE) -C ../z_tools/qemu install : $(MAKE) img $(IMGTOL) w a: haribote.img clean : -$(DEL) *.bin -$(DEL) *.lst -$(DEL) *.gas -$(DEL) *.obj -$(DEL) bootpack.nas -$(DEL) bootpack.map -$(DEL) bootpack.bim -$(DEL) bootpack.hrb -$(DEL) haribote.sys src_only : $(MAKE) clean -$(DEL) haribote.img |
43라인 등을 보게되면 문자 설정에 필요한 파일인 hankaku.txt.파일의 위치와 컴파일을 make하도록 수정하였습니다.
bootpack.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | #include <stdio.h> void io_hlt(void); void io_cli(void); void io_out8(int port, int data); int io_load_eflags(void); void io_store_eflags(int eflags); void init_palette(void); void set_palette(int start, int end, unsigned char *rgb); void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); void init_screen8(char *vram, int x, int y); void putfont8(char *vram, int xsize, int x, int y, char c, char *font); void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s); void init_mouse_cursor8(char *mouse, char bc); void putblock8_8(char *vram, int vxsize, int pxsize, int pysize, int px0, int py0, char *buf, int bxsize); #define COL8_000000 0 #define COL8_FF0000 1 #define COL8_00FF00 2 #define COL8_FFFF00 3 #define COL8_0000FF 4 #define COL8_FF00FF 5 #define COL8_00FFFF 6 #define COL8_FFFFFF 7 #define COL8_C6C6C6 8 #define COL8_840000 9 #define COL8_008400 10 #define COL8_848400 11 #define COL8_000084 12 #define COL8_840084 13 #define COL8_008484 14 #define COL8_848484 15 struct BOOTINFO { char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram; }; struct SEGMENT_DESCRIPTOR { short limit_low, base_low; char base_mid, access_right; char limit_high, base_high; }; struct GATE_DESCRIPTOR { short offset_low, selector; char dw_count, access_right; short offset_high; }; void init_gdtidt(void); void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar); void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar); void load_gdtr(int limit, int addr); void load_idtr(int limit, int addr); void HariMain(void) { struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; char s[40], mcursor[256]; int mx, my; init_gdtidt(); init_palette(); init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); mx = (binfo->scrnx - 16) / 2; /* 화면 중앙이 되도록 좌표 계산 */ my = (binfo->scrny - 28 - 16) / 2; init_mouse_cursor8(mcursor, COL8_008484); putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); sprintf(s, "(%d, %d)", mx, my); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "Hi, Chestnut Mosaic OS"); for (;;) { io_hlt(); } } void init_palette(void) { static unsigned char table_rgb[16 * 3] = { 0x00, 0x00, 0x00, /* 0:흑 */ 0xff, 0x00, 0x00, /* 1:밝은 빨강 */ 0x00, 0xff, 0x00, /* 2:밝은 초록 */ 0xff, 0xff, 0x00, /* 3:밝은 황색 */ 0x00, 0x00, 0xff, /* 4:밝은 파랑 */ 0xff, 0x00, 0xff, /* 5:밝은 보라색 */ 0x00, 0xff, 0xff, /* 6:밝은 물색 */ 0xff, 0xff, 0xff, /* 7:흰색 */ 0xc6, 0xc6, 0xc6, /* 8:밝은 회색 */ 0x84, 0x00, 0x00, /* 9:어두운 빨강 */ 0x00, 0x84, 0x00, /* 10:어두운 초록 */ 0x84, 0x84, 0x00, /* 11:어두운 황색 */ 0x00, 0x00, 0x84, /* 12:어두운 파랑 */ 0x84, 0x00, 0x84, /* 13:어두운 보라색 */ 0x00, 0x84, 0x84, /* 14:어두운 물색 */ 0x84, 0x84, 0x84 /* 15:어두운 회색 */ }; set_palette(0, 15, table_rgb); return; /* static char 명령은 데이터 밖에 사용할 수 없지만 DB명령 상당 */ } void set_palette(int start, int end, unsigned char *rgb) { int i, eflags; eflags = io_load_eflags(); /* 인터럽트 허가 플래그의 값을 기록한다 */ io_cli(); /* 허가 플래그를 0으로 하여 인터럽트 금지로 한다 */ io_out8(0x03c8, start); for (i = start; i <= end; i++) { io_out8(0x03c9, rgb[0] / 4); io_out8(0x03c9, rgb[1] / 4); io_out8(0x03c9, rgb[2] / 4); rgb += 3; } io_store_eflags(eflags); /* 인터럽트 허가 플래그를 원래대로 되돌린다 */ return; } void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1) { int x, y; for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) vram[y * xsize + x] = c; } return; } void init_screen8(char *vram, int x, int y) { boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29); boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28); boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27); boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1); boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24); boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4); boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4); boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5); boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3); boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3); boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24); boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4); boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3); boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3); return; } void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char *p, d /* data */; for (i = 0; i < 16; i++) { p = vram + (y + i) * xsize + x; d = font[i]; if ((d & 0x80) != 0) { p[0] = c; } if ((d & 0x40) != 0) { p[1] = c; } if ((d & 0x20) != 0) { p[2] = c; } if ((d & 0x10) != 0) { p[3] = c; } if ((d & 0x08) != 0) { p[4] = c; } if ((d & 0x04) != 0) { p[5] = c; } if ((d & 0x02) != 0) { p[6] = c; } if ((d & 0x01) != 0) { p[7] = c; } } return; } void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s) { extern char hankaku[4096]; for (; *s != 0x00; s++) { putfont8(vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return; } void init_mouse_cursor8(char *mouse, char bc) /* 마우스 커서를 준비(16 x16) */ { static char cursor[16][16] = { "**************..", "*OOOOOOOOOOO*...", "*OOOOOOOOOO*....", "*OOOOOOOOO*.....", "*OOOOOOOO*......", "*OOOOOOO*.......", "*OOOOOOO*.......", "*OOOOOOOO*......", "*OOOO**OOO*.....", "*OOO*..*OOO*....", "*OO*....*OOO*...", "*O*......*OOO*..", "**........*OOO*.", "*..........*OOO*", "............*OO*", ".............***" }; int x, y; for (y = 0; y < 16; y++) { for (x = 0; x < 16; x++) { if (cursor[y][x] == '*') { mouse[y * 16 + x] = COL8_000000; } if (cursor[y][x] == 'O') { mouse[y * 16 + x] = COL8_FFFFFF; } if (cursor[y][x] == '.') { mouse[y * 16 + x] = bc; } } } return; } void putblock8_8(char *vram, int vxsize, int pxsize, int pysize, int px0, int py0, char *buf, int bxsize) { int x, y; for (y = 0; y < pysize; y++) { for (x = 0; x < pxsize; x++) { vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x]; } } return; } void init_gdtidt(void) { struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000; struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) 0x0026f800; int i; /* GDT의 초기화 */ for (i = 0; i < 8192; i++) { set_segmdesc(gdt + i, 0, 0, 0); } set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092); set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a); load_gdtr(0xffff, 0x00270000); /* IDT의 초기화 */ for (i = 0; i < 256; i++) { set_gatedesc(idt + i, 0, 0, 0); } load_idtr(0x7ff, 0x0026f800); return; } void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar) { if (limit > 0xfffff) { ar |= 0x8000; /* G_bit = 1 */ limit /= 0x1000; } sd->limit_low = limit & 0xffff; sd->base_low = base & 0xffff; sd->base_mid = (base >> 16) & 0xff; sd->access_right = ar & 0xff; sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0); sd->base_high = (base >> 24) & 0xff; return; } void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar) { gd->offset_low = offset & 0xffff; gd->selector = selector; gd->dw_count = (ar >> 8) & 0xff; gd->access_right = ar & 0xff; gd->offset_high = (offset >> 16) & 0xffff; return; } |
정말 많이 추가됬습니다. 거의 300라인 가까이가 됬습니다.
세크멘트를 사용하기 위해서 GDT와 IDT 초기화 함수를 초기화하고 마우스 이미지를 출력하는 함수를 작성하였습니다.
그리고 제가 따로 글씨를 추가하였습니다.
hankaku.txt 일부
보시면 아시겠지만, 라인 수가 후덜덜합니다. 이거 누가 만들어서 무료로 사용하도록 허락했다고합니다.
문자표가 있다는걸 알았지만 실제로 보는건 처음이네요...
별모양과 점모양이 있는데 별과 점으로 구별하여 하나의 문자를 구성하여 각 OS에 맞게 출력하도록 하여 작성됩니다.
실행
make run 실행 전 파일 목록입니다. 4일차와 다르게 hankaku.txt 파일 추가된 것을 확인 할 수 있습니다.
make run 실행 후
컴파일 다 하고 나면 위와 같은 파일 목록이 표시됩니다.
결과
위에 가로로 보이는 것은 마우스 좌표로 초기에 설정한 것입니다.
마우스 모양이 웃기긴한데 중요한건 움직이지 않습니다.
인터럽트 처리를 아직 안해서 움직이지 않고 GDT, IDT 초기화만 설정했습니다.
그리고 Hi, Chestnut Mosaic OS 글씨는 제가 따로 추가한 것 입니다.
참고 자료
OS 구조와 원리, 카와이 히데미 저, 한빛미디어 출판
링크 : http://www.hanbit.co.kr/store/books/look.php?p_code=B9833754652
링크 : http://godrjsmgl.tistory.com/66
'Embedded > OS제작 with OS구조와원리' 카테고리의 다른 글
7일차. FIFO와 마우스 제어 (0) | 2017.08.06 |
---|---|
6일차. 분할 컴파일과 인터럽트 처리 (0) | 2017.08.01 |
4일차. C언어와 화면 표시 - (3) OS 화면 구성 (0) | 2017.07.09 |
4일차. C언어와 화면 표시 - (2) 사각형 띄우기 (0) | 2017.07.09 |
4일차. C언어와 화면 표시 - (1) 줄무늬 화면띄우기 (0) | 2017.07.09 |