화면에 그리기위해
vram에 뭔가 써야함.
naskfunc.nas에 write_mem8 함수 추가
;naskfunc
;TAB=4
[FORMAT "WCOFF"] ;오브젝트 파일 만드는 모드
[INSTRSET "i486p"] ;486명령사용하고싶다 작성
[BITS 32] ;32비트모드용 기계어 만듬
;오브젝트 파일 위한 정보
[FILE "naskfunc.nas"] ;소스파일명 정보
GLOBAL _io_hlt,_write_mem8 ;이프로그램에 포함된 함수명
; 실제 함수
[SECTION .text] ;오브젝트 파일에서는 이것을 쓴후에 프로그램을 쓴다.
_io_hlt: ;void io_hlt(void);
HLT
RET
_write_mem8: ; void write_mem8(int addr, int data);
MOV ECX, [ESP+4] ; [esp+4]에 addr이 들어있으니 ecx에 읽어들임
MOV AL, [ESP+8] ; [ESP+8]에 data가 있으니 al에 읽어들임
MOV [ECX], AL
RET
nask에 instrset으로 486용임을 알림
cpu를 32비트 모드로 사용중이라 32비트 레지스터 사용 ecx
vram 구간 전체에 15를 써서 하얗게 됨
bootpack.c
void io_hlt(void);
void write_mem8(int addr, int data);
void HariMain(void)
{
int i;
for (i = 0xa0000; i<= 0xaffff; i++)
{
write_mem8(i, 15); //move byte [i], 15
}
fin:
io_hlt(); //naskfunc.nas의 _io_hlt가 실행됨.
goto fin;
}
* vram이 0xa0000에서 시작하는 이유
haribote.nas에서 vram에 0x000a0000으로 지정

줄무늬 만들기
i와 0x0f and 연산으로 줄무늬 만들기
void io_hlt(void);
void write_mem8(int addr, int data);
void HariMain(void)
{
int i;
for (i = 0xa0000; i<= 0xaffff; i++)
{
write_mem8(i, i & 0x0f); //move byte [i], 15
}
fin:
io_hlt(); //naskfunc.nas의 _io_hlt가 실행됨.
goto fin;
}

포인터 사용하기
write_mem8대신 포인터사용해줘도 지정가능
void io_hlt(void);
void write_mem8(int addr, int data);
void HariMain(void)
{
int i;
char *p;
for (i = 0xa0000; i<= 0xaffff; i++)
{
p = i;
*p = i & 0x0f;
//write_mem8(i, i & 0x0f); //move byte [i], 15
}
fin:
io_hlt(); //naskfunc.nas의 _io_hlt가 실행됨.
goto fin;
}
색상 사용하기
색상 쓰기위해 rgb table 준비해서 팔레트 설정하는 내용
어셈블리 함수가 여러개 추가됨.
void io_hlt(void);
void io_cli(void);
void io_out8(int prot, 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 HariMain(void)
{
int i;
char *p; //p라는 변수는 byte[]용 번지
init_palette();
p = (char *)0xa0000;
for (i=0; i <= 0xffff; i++)
{
p[i] = i & 0x0f;
}
for(;;)
{
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00,
0xff, 0x00, 0x00,
0x00, 0xff, 0x00,
0xff, 0xff, 0x00,
0x00, 0x00, 0xff,
0xff, 0x00, 0xff,
0x00, 0xff, 0xff,
0xff, 0xff, 0xff,
0xc6, 0xc6, 0xc6,
0x84, 0x00, 0x00,
0x00, 0x84, 0x00,
0x84, 0x84, 0x00,
0x00, 0x00, 0x84,
0x84, 0x00, 0x84,
0x00, 0x84, 0x84,
0x84, 0x84, 0x84
};
set_palette(0, 15, table_rgb);
return;
}
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;
}
추가된 함수들
; 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
[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
이전보다 더 다양한 색상으로 줄무늬가 그려짐.

박스 그리기
boxfill8 함수 만들어 박스 띄움
void io_hlt(void);
void io_cli(void);
void io_out8(int prot, 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);
#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
void HariMain(void)
{
int i;
char *p; //p라는 변수는 byte[]용 번지
init_palette();
p = (char *)0xa0000;
boxfill8(p, 320, COL8_FF0000, 20, 20, 120, 120);
boxfill8(p, 320, COL8_00FF00, 70, 50, 170, 150);
boxfill8(p, 320, COL8_0000FF, 120, 80, 220, 180);
for(;;)
{
io_hlt();
}
}
void init_palette(void)
{
static unsigned char table_rgb[16 * 3] = {
0x00, 0x00, 0x00,
0xff, 0x00, 0x00,
0x00, 0xff, 0x00,
0xff, 0xff, 0x00,
0x00, 0x00, 0xff,
0xff, 0x00, 0xff,
0x00, 0xff, 0xff,
0xff, 0xff, 0xff,
0xc6, 0xc6, 0xc6,
0x84, 0x00, 0x00,
0x00, 0x84, 0x00,
0x84, 0x84, 0x00,
0x00, 0x00, 0x84,
0x84, 0x00, 0x84,
0x00, 0x84, 0x84,
0x84, 0x84, 0x84
};
set_palette(0, 15, table_rgb);
return;
}
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;
}

바탕화면 만들기
일단 박스필 4개만하면 이런식으로 화면이 만들어진다.
void HariMain(void)
{
char *vram;
int xsize, ysize;
init_palette();
vram = (char *) 0xa0000;
xsize = 320;
ysize = 200;
boxfill8(vram, xsize, COL8_008484, 0, 0, xsize-1, ysize-29); //녹하늘색 화면
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-28, xsize-1, ysize-28); // 바닥 표시줄구분선
boxfill8(vram, xsize, COL8_FFFFFF, 0, ysize-27, xsize-1, ysize-27); //바닥 표시줄 구분선
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-26, xsize-1, ysize-1); //바닥 표시줄
for(;;)
{
io_hlt();
}
}

박스필 몇개 더 추가하면
옛날 윈도우 화면 느낌으로 만들어진다.
void HariMain(void)
{
char *vram;
int xsize, ysize;
init_palette();
vram = (char *) 0xa0000;
xsize = 320;
ysize = 200;
boxfill8(vram, xsize, COL8_008484, 0, 0, xsize-1, ysize-29); //녹하늘색 화면
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-28, xsize-1, ysize-28); // 바닥 작업표시줄구분선
boxfill8(vram, xsize, COL8_FFFFFF, 0, ysize-27, xsize-1, ysize-27); //바닥 작업표시줄 구분선
boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-26, xsize-1, ysize-1); //작업 표시줄
boxfill8(vram, xsize, COL8_FFFFFF, 3, ysize - 24, 59, ysize - 24);
boxfill8(vram, xsize, COL8_FFFFFF, 2, ysize - 24, 2, ysize - 4);
boxfill8(vram, xsize, COL8_848484, 3, ysize - 4, 59, ysize - 4);
boxfill8(vram, xsize, COL8_848484, 59, ysize - 23, 59, ysize - 5);
boxfill8(vram, xsize, COL8_000000, 2, ysize - 3, 59, ysize - 3);
boxfill8(vram, xsize, COL8_000000, 60, ysize - 24, 60, ysize - 3);
boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 24, xsize - 4, ysize - 24);
boxfill8(vram, xsize, COL8_848484, xsize - 47, ysize - 23, xsize - 47, ysize - 4);
boxfill8(vram, xsize, COL8_FFFFFF, xsize - 47, ysize - 3, xsize - 4, ysize - 3);
boxfill8(vram, xsize, COL8_FFFFFF, xsize - 3, ysize - 24, xsize - 3, ysize - 3);
for(;;)
{
io_hlt();
}
}

day04.zip
0.01MB
'컴퓨터과학 > os' 카테고리의 다른 글
어셈블리 - 1. 개발환경 구축과 첫 프로젝트 (0) | 2024.04.14 |
---|---|
OS30 - 7. 글자쓰기 (0) | 2024.04.08 |
OS30 - 5. ipl 만들기, c언어 진입 (0) | 2024.04.05 |
OS30 - 4. 부트섹터 분할시키고 make 사용하기 (0) | 2024.04.05 |
OS30 - 3. 어셈블리 다루기 (0) | 2024.04.05 |