728x90

통계적 현상 statistical phenomena

- 여러번 관찰해서 법칙을 찾아낼수 있는 현상

 

확률 실험

- 반복 할수록 규칙성이 존재하는 행위

 

확률

- 특정 현상이 확실히 발생할 정도

 

확률 법칙

- 임의의 실험에서 사건에 확률을 배정하는 규칙

 

 

수학적 확률

- 표본 공간 S과 S를 구성하는 사건 A가 있을때, 다음의 P(A)를 수학적 확률

 * 수학적 확률은 각 사건들이 일어날 가능성이 모두 동일하다고 가정

 * 동전 2개를 던질때 앞면이 0개, 1개, 2개가 나올 확률을 다 동일하게 1/3, 1/3, 1/3이라고 가정하면 안됨.

 

통계적 확률

- 동일한 현상이 일어날지 불확실한 경우, 여러번 실험해서 얻은 사건에 대한 확률은 상대적인 횟수로 추정

- 상대적인 횟수 relative frequency는 n번 실험할때 r회 일어난 경우 r/n.

 * 동전 2개를 던질때 앞면이 0개, 1개, 2개가 나올 (통계적) 확률은 1/4, 1/2, 1/4

 

 

수학적 확률과 통계적 확률의 차이

- 수학적 확률은 표본 공간을 구성하는 사건들이 동일한 확률을 가지고 있다고 생각

- 통계적 확률은 여러번 반복했을때 나온 정도(상대적 횟수)로 확률을 추정

 

 

 

통계적 확률 정리

- n회 실험 할때, A의 상대 횟수 r/n이 특정한 수 p에 수렴하는 경우 => 통계적 확률

- 정확한 p 값은 알수 없으나, n이 충분히 크다면 근사적으로 상대 도수를 통계적 확률로 본다.

 

 

 

표본 공간 sample space과 확률 공간 probability space

- 표본 공간 : 관측으로 얻은 결과 집합

- 사건 : 표본 공간의 부분 집합

- 확률 공간 : 표본 공간을 확률에 대응시킨 결과 집합

 

 

주변 확률과 조건부 확률

- 주변 확률 marginal probability : 두 사건 A, B가 존재할때, A나 B 한 가지의 사건만 일어날 확률

- 조건부 확률 conditional probability : 두 사건 A, B가 발생 했는데, B의 확률을 알때 A가 일어날 확률

 

전체 확률 이론 total probability thorem

- 사건 A들의 합집합이 표본 공간이고, 서로 배타적일때 사건 B는 다음의 그림과 같이 구성됨.

- 사건 B의 확률은 B와 사건 A들의 교집합들의 합

 

 

 

 

 

 

 

 

 

 

귀납적 추론과 연역적 추론

- 통계학은 대부분의 경우 표본에서 모집단을 추정

 => 귀납적 추론 inductive inference : 개발적 사건으로 일반적 법칙 유도

- 연역적 추론 deductive inference : 일반적 법칙으로 개별적인 사건 유도

 

 

베이즈 정리 bayes thorem

- 일반적인 법칙을 알수 없는 불확실한 상황에서 의사 결정 문제를 다룰때 중요하게 사용됨

- (연역적 추론 방식인) 확률로 (일반적인 법칙을 유도하는) 귀납적 추론 방식을 행하는 행위

 

 

베이즈 정리와 확률의 의미

- 기존의 확률 : 직접 확률 direct probability

- 베이즈 정리 : 역확률 inverse probability

 

 

 

베이즈 법칙(정리?)로 정리하기

- 표본 공간 S와 분할 영역 A들이 주어질때, B가 난 경우 A_i에서 일어날 확률이 얼마나 될까?

- 조건부 확률 conditional probability 을 전체 확률 정리 total probability thorem으로 정리하면

 => 사건 B가 발생했을때 A_i가 일어날 확률을 알고 싶으나 모르는 경우

    사건 A_i가 일어났을때 B가 일어날 확률을 안다면 구할수 있다.

* 개별적 사건에 대한 확률로 일반적인 법칙을 추론해냈다?

 

 

 

 

 

통계적 패턴인식에서의 베이즈 정리

- 특징 벡터 x가 관측되었을때 클래스 omega_i를 찾자. P(omega_j | x) = ?

 => p(x | omega_i)를 알면 구할수 있다. (클래스가 주어질때, 특징 벡터 관측에 대한 조건부 확률)

- 베이즈 정리 : 우도를 알때 사후 확률을 구하는 정리

 

 

베이즈 정리 용어 정리

- 사전 확률 priori probability : P(omega_1). 클래스 omega_1의 확률

- 정규화 상수 : p(x), x 확률 결정에 영향을 주지않는 정규화 상수

- p(omega_1 교집합 x ) = 1/10 (임의로 정의)

- 우도 likelihood : 클래스 omega_i가 주어질때, 관측 x이 일어날 확률

 

- 사후 확률 posterior probaility : 관측 x이 있을때, 클래스 omega_1에 속할 확률

 => 특징 벡터 x가 관측되었을때, 분류한 결과가 omega_1일 확률은 0.3

 => 특징 벡터 x는 30%의 확률로 omega_1로 분류된다!!

 

 

 

 

 

 

 

300x250
728x90

회귀분석 regression analysis

- 변수들간의 관계를 정리하여 모델링하는 통계 기법

 => 자연 과학, 사회과학에서 널리사용됨

- 수학적 모델을 가정하고, 실제 데이터로 모델을 추정하는 방법. 예측에 주로 사용

=> 표본을 잘 나타내는 적합한 근사 함수를 구할 수 있음

 * 근사 함수 : 회귀 직선, 회귀 곡선

 

 

 

 

 

선형 회귀 linear regression

- 회귀 직선 : 데이터를 가장 잘 수학적으로 모델링 하는 선

- 선형 회귀는 샘플 데이터를 통해 이를 가장 잘 표현하는 회귀 직선을 구하는 과정

 

 

선형 회귀 모델의 종류

 

https://m.blog.naver.com/PostView.nhn?blogId=istech7&logNo=50152984368&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

 

최소 자승법 Method of Least Mean Square 

- 샘플 데이터와 임의의 직선의 제곱 오차를 최소로하는 직선을 구하는 방법

1. 아래의 직선을 가정

2. 데이터가 하나가 아니라 두개인 이변량인 경우 측정값은 아래와 같이 정리하자

 * 단변량 : 하나인경우 univariate,  이변량 bivariate : 두개인 경우,    다변량 multivariate : 여러개인 경우

3. 각 x의 값에 대한 y의 값들을 정리하면 아래와 같다.

4. 측정값 y_i와 위 직선과의 평균 제곱 오차 MSE Mean Squared Error는

 

5. MSE가 최소가 되는 alpha와 beta가 구하면 회귀 직선이 됨.

6. MSE를 alpha와 beta에 대해 편미분 하고, 0과 같다고 가정하여 각 변수에 대해 정리하면

 

 

 

회귀 곡선 regression curve(다항식 회귀? polynomial regression)

- 회귀 직선과 달리 1차식이 아니라 2차식으로 나타낸 회귀식

1. 아래와 같이 회귀 곡선 모델을 정의

2. 이에 대한 계수 a, b, c는 평균 제곱 오차를 최소화하도록 아래와 같이 정리할수 있음

- 아래는 회귀 곡선을 구하는 다항식 회귀 예시

300x250
728x90

통계 용어들

- 데이터 분석 과정 data analysis process : 데이터를 처리하여 정보 도출하는 과정 -> 요약, 추정 단계 수행

  => 아래의 그림은 데이터 분석 과정

https://www.tutorialspoint.com/excel_data_analysis/data_analysis_process.htm

- 요약 : 정보 손실을 줄이면서 정리

- 추론(추정) inference : 요약된 데이터로 특정 집단에 대한 사실을 추론해내는것

- 모집단 population : 데이터 분석 대상 전체

- 표본 sample : 수집된 모집단 데이터의 일부분

- 표본 분포 sampling distribution : 샘플들로 부터 얻은 통계적인 분포

 

데이터 분석의 성질

- 타당성 validity : 의도대로 수집하였는지

- 신뢰성 reliability : 항상 동일한 결과가 나오는지

 

 

 

 

 

 

 

 

통계학 매개변수(파라미터)들

- 파라미터 parameter : 모집단 population을 표현하기 위한 모수(고정된 값)

  => 추론 inference를 통해 파라미터를 구할수 있게 된다.

- 평균 mean : 데이터 총합을 데이터 갯수로 나눈 값 -> 데이터 분포의 무게 중심

- 분산 variance : 데이터들이 퍼진 정도. (데이터 - 평균) 제곱 합 / 데이터 갯수

- 표준 편차 standard deviation : 분산은 제곱 합을 통해 구하므로 데이터 단위가 달라짐.

                                      기존의 데이터 단위와 맞추기 위해 제곱근 수행

http://blog.naver.com/PostView.nhn?blogId=freewheel3&logNo=220847292476

- 바이어스(편향) bias : 데이터가 특정 위치에 집중(편향)된 정도

https://medium.com/@mp32445/understanding-bias-variance-tradeoff-ca59a22e2a83

- 공분산 covariance : 샘플 데이터가 단변수가 아니라 다변수 인경우 각 변화량에 대한 변화하는 정도.]

https://www.cs.princeton.edu/courses/archive/fall08/cos436/Duda/PR_Mahal/cov.htm

- 상관 계수 correlation : 서로 다른 두 변수 X, Y 간에 상관관계의 정도.

                            => 하나의 변수가 변함에 따라 다른 변수에 얼마나 영향을 미치는가

 

https://en.wikipedia.org/wiki/Correlation_and_dependence

- 왜도 skewness : 분포가 치우쳐진(asymmetry) 정도. 

https://m.blog.naver.com/PostView.nhn?blogId=moses3650&logNo=220880815585&proxyReferer=https:%2F%2Fwww.google.com%2F

- 첨도 kurtosis : 통계 분포가 뽀족한 정도

https://m.blog.naver.com/PostView.nhn?blogId=moses3650&logNo=220880815585&proxyReferer=https:%2F%2Fwww.google.com%2F

 

 

300x250
728x90

그리스어 표기

http://blog.naver.com/PostView.nhn?blogId=5002sesang&logNo=40019793977&parentCategoryNo=&categoryNo=4&viewDate=&isShowPopularPosts=true&from=search

 

 

고유치 eigen value, 고유벡터 eigen vector

- 패턴 인식 + 전기 + 사회 과학 분야 전반에서 사용되는 분석 도구

- 행렬의 중요한 특징을 표현

- 아래의 식을 만족하는 벡터 A가 eigen vector, 스칼라 lambda는 고유치

 

 

양의 정부호 행렬

- 0이 아닌 벡터 x와 행렬 A가 다음의 조건을 만족하는 경우

 => 행렬 A는 양의 정부호 행렬 positive definite matrix 

 => A > 0 이 A가 정부호 임을 알려줌

 

양의 준정부호 행렬

- 0이 아닌 벡터 x와 행렬 A가 다음 조건 만족

 => 행렬 A는 양의 준정부호행렬 positive semi-definite matrix

 => A >= 0. 즉, A는 준정부호

 

 

 

유사 변환 similarity transformation과 고유치

- 유사 변환 =  강체 변환(평행 이동 + 회전) + 스케일 변환

- 다음의 조건을 만족하는 역행렬 C가 존재하면 행렬 A와 B는 유사

- 유사 변환 행렬들은 동일한 고유치를 가짐

 

 

 

 

 

대각화 가능한 행렬 digonalizable

- 아래의 조건을 만족하는 대각행렬 C가 존재할때, 정방 행렬 A는 대각화 가능한 행렬

 * 이후 특이값 분해를 위해 대각화가 가능하여야 함

 

 

행렬의 대각화

- 대각 행렬 C가 아래와 같은 열벡터 v들을 모아 만든 행렬이라고 가정할때

- 정방 행렬 A의 고유치, 고유벡터들을  행렬 A와 행렬C의 곱으로 표현 가능

- 행렬 C는 선형 독립 -> 비특이 행렬 => C의 역행렬이 존재한다.

 => 행렬 A는 대각화가 가능함

 

 

직교 대각화 orthogonal diagonalization

- 직교 행렬의 성질 : 대각 행렬 C가 직교행렬인 경우 C의 전치행렬 = C의 역행렬

- 직교 행렬의 성질을 이용하면 역행렬을 전치행렬로 변환하여 간단하게 계산 가능

 

 

특이값 분해 singular value decomposition

- 복습 => 특이 행렬 : 역행렬이 존재하지 않음.   비특이 행렬 : 역행렬이 존재

- 특이 값 분해

 : 특이값 분해(SVD)는 고유값 분해(eigen value decomposition)처럼 행렬을 대각화하는 한 방법

  => 특이 행렬(비정방행렬)에서 특이값(고유값)들에 대한 대각 행렬을 분해한다.

 

- 특이값 분해의 장점

 :  행렬이 정방행렬이든 아니든 관계없이 모든 m x n 행렬에 대해 적용 가능하기 때문이다.

- 비정방 행렬 A가 주어질때 다음의 관계가 이루어짐.

 

고유값 분해 eigen value decomposition과 특이값 분해 Singular Value Decomposition의 차이

- 고유값 분해는 정방행렬 A의 고유값들을 대각행렬로 추출

- 특이값 분해는 비정방행렬들의 특이값(행렬의 특성을 가장 잘나내는 값)을 대각행렬로 추출

 

 

 

 

선형 변환 linear transform

- 아래와 같이 서로 다른 차원의 벡터 공간에서 변환(맵핑)을 의미

- 아래의 예시는 2차원 벡터공간 X에서 3차원 벡터공간 Y로의 선형 변환을 보여줌

- 선형 변환을 행렬로 표기하면 아래와 같다.

 

 

300x250
728x90

OS를 만들 때 잘 사용하는 BIOS 함수(AT 호환기종)

OS의 개발이 32 Bit 단계에 다다르면 사용할 수 없는 BIOS 함수들이기는 하지만, 부트 섹터나 OS 개발의 초반까지는 다음 BIOS 함수를 많이 사용하게 된다.

INT(0x10) : 비디오 관련

  • 비디오 모드 설정
    • AH = 0x00
    • AL = 모드(자주 사용되는 화면 모드만 설명)
      • 0x03:16색 텍스트, 80x25
      • 0x12:VGA 그래픽스, 640 x480x4bit 칼라
      • 0x13:VGA 그래픽스, 320 x200x8bit 칼라, Packed Pixel
      • 0x6a:확장 VGA 그래픽스, 800 x600x4bit 칼라
    • 반환값:없음

 

  • 커서 모양 설정
    • AH = 0x01
    • CH = 시작 라인
    • CL = 종료 라인
      • CH < CL라면 1개의 부분으로부터 되는 보통 커서
      • CH > CL라면 2개의 부분으로부터 되는 커서
      • CH == 0x20이면 커서는 표시되지 않는다
    • 반환값:없음

 

  • 커서 위치 지정
    • AH = 0x02
    • BH = 0(페이지 번호)
    • DL = x 좌표
    • DH = y 좌표
    • 반환값:없음

 

  • 점 출력
    • 굳이 이 함수를 이용하지 않고 바로 Video 메모리를 이용할 수도 있다.
    • AH = 0x0c
    • AL = 색상 코드(0 ~ 15)
    • CX = x좌표
    • DX = y좌표
    • 반환값:없음

 

  • 한 문자 출력
    • AH = 0x0e
    • AL = 문자 코드
    • BH = 0(페이지 번호)
    • BL = 문자의 색
    • 반환값:없음
    • 주의) beep(0x07), 백 스페이스(0x08), CR(0x0d), LF(0x0a)는 제어 코드로서 인식된다

 

  • 색상 코드를 대응되는 팔레트에 저장한다.
    • 16색 모드일 때만 사용가능하다.
    • AX = 0x1000
    • BL = 색상 코드(0 ~ 15)
    • BH = 팔레트 코드(0 ~ 63)
    • 주의) EGA 그래픽 카드와의 호환성을 유지하기 위해서 사용됩니다. 잘못 사용하면 상당히 복잡해지기 때문에 기본값 그대로 두고 사용하는 것이 좋습니다.

 

  • 팔레트 설정
    • AX = 0x1010
    • BX = 팔레트 번호(0 ~ 255)
    • DH = Red(0 ~ 63)
    • CH = Green(0 ~ 63)
    • CL = Blue(0 ~ 63)
    • 반환값:없음

 

  • 문자열 출력
    • AH = 0x13
    • AL = 옵션
      • 0x00:문자열의 속성을 BL 레지스터로 지정하고 커서는 이동시키지 않는다.
      • 0x01:문자열의 속성을 BL 레지스터로 지정하고 커서를 이동시킨다.
      • 0x02:문자열을 출력하고 커서는 이동시키지 않는다.
      • 0x03:문자열을 출력하고 커서를 이동시킨다.
      • 실제 데이터는 메모리에 [문자 코드] [칼라 코드] [문자 코드] [칼라 코드]와 같이 저장된다고 보면된다.
    • BH = 0(페이지 번호)
    • BL = 칼라 코드(AL 레지스터의 값이 0x01, 0x02일 경우에만 적용)
    • CX = 문자열의 길이
    • DL = x좌표
    • DH = y좌표
    • ES:BP = 출력할 문자열이 있는 곳의 주소
    • 반환값:없음

 

  • 제일 간단하게 사용할 수 있는 화면모드인 0x13의 사용법
    • 0x13번 화면모드는 그다지 해상도가 좋지는 않지만 Packed Pixel 모드이기 때문에 프로그래밍 하기가 편합니다. 우선 화면 모드를 변경하고 팔레트를 설정합니다.
    • 이 모드는 Video Ram의 0xa0000 ~ 0xafff의 64KB에 위치하게 됩니다. 정확히 말하면 320 x 200 = 64000이 되므로 62.5 KB라고 해야겠지만, VRAM는 0xa0000 ~ 0xaffff의 64 KB입니다.엄밀하게 말하면(자), 320 x200=64000이므로, 62.5 KB가 됩니다. 이 모드에서는 점 하나가 1바이트에 해당되기때문에 읽고 쓰기도 아주 간단합니다.

 

INT(0x11) : H/W 구성 확인

  • 컴퓨터에 설치된 H/W의 리스트를 확인한다.
    • 입력값 없음
    • 반환값:
    • AH == 장치 코드
      • 사용하는 사람이 거의 없기때문에 정확한 내용은 생략하겠습니다.

 

INT(0x12) : 시스템에 있는 메모리의 크기를 조사

  • 시스템에 있는 메모리의 크기를 조사
    • 입력값 없음
    • 반환값:
    • AX == 메모리의 크기(KB 단위)

INT(0x13) : 디스크 관련 함수

  • 디스크 시스템 리셋
    • AH = 0x00
    • DL = 드라이브 번호(0x00 ~ 0x7f:FDD, 0x80 ~ 0xff:HDD)
    • 반환값:
    • FLAGS.CF == 0 : 에러 없음
    • FLAGS.CF == 1 : 에러 발생, AH에 에러 코드가 저장된다.
      • 에러 코드 (FDD, HDD 모두 발생 가능한 에러 코드)
      • 0x01:디스크 Parameter가 잘못 전달되었다.
      • 0x02:Address Mark가 발견되지 않음
      • 0x04:섹터를 찾지 못했다
      • 0x09:DMA 오버플로우
      • 0x10:데이터 에러
      • 0x20:콘트롤러 이상
      • 0x40:탐색 실패(Seek Failure)
      • 0x80:타임 아웃
      • 에러 코드 (FDD일 경우의 에러코드)
      • 0x03:쓰기 금지된 디스크에 쓰기를 시도
      • 0x06:디스크를 찾지 못함
      • 0x08:DMA 오버플로우
      • 에러 코드 (HDD일 경우의 에러코드)
      • 0x05:리셋 실패
      • 0x07:Parameter 테이블이 정확하지 않음
      • 0x0a:섹터 Flag이 잘못되었음
      • 0x11:ECC 데이터 에러
      • 0xaa:드라이브가 아직 준비되지 않음
      • 0xbb:미정의 에러
      • 0xcc:쓰기 에러
      • 0xe0:상태(Status) 에러

Retrieved from "http://osguru.net/index.php/AT-BIOS"

[출처] [펌] OS를 만들 때 잘 사용하는 BIOS 함수(AT 호환기종)

 

 

osguru.net는 들어갈수 없어 다른 분이 펌해온걸 다시가져옴

300x250
728x90

행렬의 트레이스 trace

- 정방 행렬의 대각 성분들의 합 => 트레이스

 

행렬의 계수 rank

- 선형 독립인 열벡터(행벡터)의 갯수

- 3 x 3행렬이라고 항상 계수가 3은 아님

 => 크기가 n x n이더라도 선형 독립인 행벡터가 1개 뿐이면, rank(A) = 1

- 행렬의 랭크는 다음의 조건을 따른다.

 

 

특이 행렬과 비특이 행렬

- 크기가 n x n 인 행렬 A가 주어질때 rank(A) = n이면 비특이 행렬, rank(A) < n이면 특이행렬

 

 

 

역행렬 inverse matrix

- 행렬 A가 주어질때, A와 곱했을때 단위 행렬 I가 나오는 행렬.

- ex. AB = I => A의 역행렬은 B

 

수치 해석적으로 역행렬을 구하는 방법

- 소행렬식 전개

- 가우스 조던 소거법

 

 

행렬식 determinant of matrix

- 행렬을 하나의 실수 값으로 표현하는 식

+ 역행렬이 존재하는지를 판별하기 위한 식

- 행렬 A의 행렬식은 아래와 같이 표기

- 크기가 2 x 2인 경우, 3 x 3인 경우 행렬식 계산법( 사루스 전개법으로 쉽게 계산 가능)

* 4차 이상 행렬의 경우 소행렬식 사용하여 계산 가능

 

 

300x250
728x90

잠깐

- 벡터 공간 : n차원 벡터들이 존재하는 n차원 공간

- 유클리드 공간 : 선형독립인 n개의 n차원 벡터로 생성될수 있는 공간

- 함수 공간 : 벡터 차원이 무한대인경우

- 널 공간 : 행렬 A가 주어질떄 Ax = 0을 만족하는 벡터 x들로 이루어진 공간

벡터 공간

 

유클리디안 공간
함수공간?
널 공간?

 

 

 

행렬론

- 행렬 : 행 M개와 열 N개로 이루어진 수들의 나열

- 차원 : M x N으로 행렬의 크기

 

 

 

행렬의 종류

- 전치행렬 tranposed matrix : 행과 열을 바꾼 행렬

- 정방행렬 square matrix : 행과 열의 크기가 동일한 행렬

- 대각 행렬 diagonal matrix : 대각 요소만 존재하는 행렬

- 상삼각 행렬 upper triangular matrix : 대각 성분 아래가 모두 0인행렬

 

- 하삼각 행렬 lower triangular matrix : 대각 성분 위가 모두 0인행렬

 

- 항등 행렬 identity Matrix : IA = AI = A를 만족하는 행렬 I

- 대칭 행렬 symmetric matrix : 대각선을 축으로 모든 선분이 대칭인 행렬. 전치를해도 자기자신인 정방행렬

- 영행렬 zero matrix : 모든 원소가 0 인 행렬

 

 

직교 행렬 orthogonal matrix

- 행렬 A가 아래의 조건을 만족하는 행렬

=> 다변량 통계 분석에서 요인 분석 factor analysis나 주성분 분석 principal component analysis, 판별 분석 discriminant analysis 에서 많이 사용되는 행렬

 

 

정규 직교 행렬 orthonomal matrix

- 행렬 A가 직교 행렬이며 다음의 조건을 만족하는 경우 정규 직교 행렬임

 

 

 

300x250
728x90

가끔 오마르님 유튜브를 보곤한다.

 

오 ..

 

 

300x250

'미분류' 카테고리의 다른 글

한 선배 개발자의 덧글  (0) 2020.08.07
omar  (0) 2020.08.05
2020.07 학습 후기 및 8월 계획  (0) 2020.08.02
2020-08-02  (0) 2020.08.02
카이스트 vr-ar  (0) 2020.08.01
728x90
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);

#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)
{
	char *p;

	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,	/*  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;
}

 

 

현재 그래픽 모드

- 320 x 200 ( =64,000)개 화소 존재

- (y,x) 픽셀의 VRAM 번지 : 0xa000 + x + y * 320 번지

 * 

- 해당 메모리에 올바른 색 번호를 저장하면 화면상 그위치에 지정한 색이 나오게 됨.

 

boxfill8 함수

- 위와 같은 방식으로 시작점 (x0, y0), 끝점 (x1, y1)사이에 색 번호를 채워넣는 함수

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;
}

 

 

상자 3개 그리기

- HariMain에서 x의 크기가 320인 화면 모드에서 빨강색을 (20, 20) ~ (120, 120),

   파란색, 녹색을 해당 위치에 그리도록 정리

* 어느 색이 색번호에 해당하는지 구분하기 위해서 #define으로 정의

void HariMain(void)
{
	char *p;

	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 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);

#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)
{
	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();
	}
}


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;
}

태스크바 만들기

- boxfill로 다음과같이 태스크바 그림 => 옛날 윈도우 화면같은 창이 만들어졌다.

- 부트섹터를 제외한 운영체제 파일 haribote.sys는 1,216 바이트 밖에 되지 않는다.

 

 

300x250
728x90

현황

- 방금전 C언어에서 직접 메모리 번지를 지정하는 방법이 없다고 하여 write_mem8 함수를 직접 어셈블리어로 구현

- 하지만 포인터를 이용하면 메모리 접근 가능

 

 

 

문제

- 어셈블리어의 문제 : 데이터가 byte인지 word인지, dword인지 알수 없음.

- c언어에서는 공간의 크기에 따라 다양한 자료형 제공

 ex. char 1바이트, short 2바이트, int 4바이트

 

 

 

 

포인터로 메모리 접근하자

- write_mem8로 i번째 주소에 접근했다면

- 지금은 포인터 변수 p에다가 주소를 담아 접근해서 사용

=> naskfunc.nas에서 wirte_mem8은 필요없으므로 지우기

 

 

 

 

색번호 설정하기

- 이제 포인터로 VRAM에 접근해서 값을 읽고 쓸수 있다. 하지만 단색은 재미없으니 색상도 바꿔보자

- 8비트 컬러 모드에서 0~255색을 표현 가능 -> 색번호 지정하는 구조를 팔레트라 부름

- 우리가 사용할 OS에서 16색만 있으면 충분할것같으니 다음과 같이 색들을 지정해주자

#000000 : 검은색 #00ffff : 밝은 청색 #000084 : 군청색
#ff0000 : 밝은 적색 #ffffff : 흰색 #840084 : 어두운 보라색
#00ff00 : 밝은 녹색 #c6c6c6 : 밝은 회색 #008484 : 어두운 청색
#ffff00 : 밝은 노란색 #840000 : 어두운 적색 #848484 : 어두운 회색
#0000ff : 밝은 청색 #008400 : 어두운 녹색  
#ff00ff : 밝은 보라색 #848400 : 어두운 노란색  

 

c언어 코드

- 맨앞의 함수들은 어셈블리어에서 정의함

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);

/* 같은 소스 내에 있어도 C언어에서 사용하기 위해선 우선 선언 필요 */

void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);

void HariMain(void)
{
	int i;
	char *p;

	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,	/*  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;
}

 

 

 

c언어와 어셈블리어 문법 잠깐 보기

- char a[3] a라는 이름의 길이가 3인 배열 공간 생성( 값들은 0)

 => 아래와 동일

     a :

           RESB 3

 

- 색상 테이블은 어셈블리어 상에서 아래와 같이 값을 대입해주는게 경제적임

 => static char로 선언한 변수에 값을 넣는게, DB 명령어로 대입하는것과 동일함

   table_rgb:

      DB 0x00, 0x00, 0x00, 0xff, 0x00, 0xff ....

 

 

 

set_palette 보기

- io_out8 함수 : 장치 번호로 지정한 장치에 데이터를 보내는 함수

- CPU와 메모리만 연결되어있으면 계산과 기억밖에 하지못함.

 => 하드디스크, 그래픽, 사운드 카드 등과 연결되어 다양한 입출력이 가능해짐

 

 

out/in 명령어

- out 명령어 : 특정 장치로 전기 신호를 보내기 위한 명령어

- in 명령어 : 특정 장치로부터 신호를 받기 위한 명령

 

 

그래픽 관련 장치 번호

- 0x03c8, 0x03c9는 그래픽 관련 장치번호

- 팔레트 액세스 순서

- 액세스 중에는 인터럽트 발생해선 안됨 ex. CLI

- 0x03c08에 사용할 팔레트 번호를 쓰고, RGB 순서대로 0x03c9에 입력

  * 다음 팔레트도 같이 설정한다면 팔레트 번호 설정 생략하고 계속 RGB순서로 쓰면됨.

- 팔레트 상태 읽을때 0x03c7에 팔레트 번호 쓰고, 0x03c9를 3번 읽음 => RGB순서대로 처리됨.

- 최초 CLI(인터럽트 금지)를 한경우 마지막에 STI(io_store_eflags, 인터럽트 허가 플래그 원위치)를 한다.

 

 

CLI와 STI

- CLI : 인터럽트 플래그 interrupt flag를 0으로 만듬( clear interrupt flag)

- STI : 인터럽트 플래그를 1로 만드는 명령 (set interrupt flag)

=> 인터럽트 플래그가 0이면 인터럽트 반응 회로가 동작 안함, 1이면 동작함

 

 

EFLAGS

- 16비트 레지스터인 FLAGS가 32비트로 레지스터로 확장된 레지스터.

- FGLAS는 캐리 플래그, 인터럽트 플래그 등으로 구성됨.

- 아래의 그림은 16비트 8086 아키택처의 FLAGS 레지스터

http://mmrcse.blogspot.com/2018/12/write-function-of-segment-register-and.html

 

 

 

set_palette에서 하는일

- 팔레트 설정하기전에 CLI실행. 

- 팔레트 설정후

- 인터럽트 플래그 허용 STI

 

 

 

naskfunc.nas

- PUSHFD : push flags double-word : vmfformfmf ejqmf dnjemfh alfdjsjgsmsek.

- POPFD : pop EFLAGS라는 뜻

=> EFLAGS를 읽거나 쓰는데 ㅏ용.

 

; naskfunc
; TAB=4

[FORMAT "WCOFF"]				; 오브젝트 파일 만드는 모드
[INSTRSET "i486p"]				; 이 프로그램이 486 아키텍처 용 프로그램임을 nask에 알림
[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

 

 

실행 결과

- 색상있는 줄무늬들이 출력됨

 

 

300x250

+ Recent posts