런 유니티 vr 과정 진행중에

퀘스트 링크 실행한 상태에서

빌드 세팅을 데스크탑으로 놓고 실행하면

정상적으로 동작하는걸 확인했다.

 

 

 

하지만 다음의 안드로이드 빌드에서 문제가 생김

https://learn.unity.com/tutorial/1-1-vr-peurojegteu-seoljeong?uv=2021.3&pathwayId=653b58e7edbc2a51bac472f3&missionId=653b0664edbc2a43b6c4e79d#653b126eedbc2a4a1888da36

 

1.1 - VR 프로젝트 설정 - Unity Learn

이 수업을 마치면 크고 빈 방이 있는 새 Unity 프로젝트를 VR로 경험하게 됩니다. 이 단원은 VR로 창작하기 교육 과정의 일부입니다.

learn.unity.com

 

 

 

분명 usb로 연결했는데 찾질못한다

 

ip를 입력해봐도 연결안되는건 여전하다.

 

 

 

 

구글링하다보니 여기서 개발자모드로 들어가야된다고한다.

 

https://discussions.unity.com/t/oculus-quest-not-showing-up-in-run-device/865989/2

 

 

개발자 모드 어떻게 들어가는지 찾다보니 이 글에서 메타 퀘스트 휴대폰 앱을 스면된다고한다.

https://aixr.org/insights/how-to-enable-developer-mode-on-oculus-quest-2/

 

How to enable developer mode on Oculus Quest 2

Learn how to enable developer mode options for the Oculus Quest 2 in addition to creating a developer account to sideload applications.

aixr.org

 

 

퀘스트 앱으로 진행하다보니 이 페이지를 안내해주는데 

퀘스트2에서는 여기서 말하는데로 진행할수가 없다. 어떻게 하라는 걸까..?

https://developer.oculus.com/documentation/native/android/mobile-device-setup/

 

Device Setup | Oculus Developers

 

developer.oculus.com

 

 

 

가 아니라

메타 호라이즌 모바일 앱을

메타 퀘스트2 기본 설정앱과 착각했다.

휴대폰에서 보니 메타 호라이즌 앱이 따로 있더라..

 

잠깐 뭔가 이상한데

매타 퀘스트랑 호라이즌이랑 같은건가?

 

왜 개발자 모드 옵션이 안되나 햇는데

다시 글을 읽어보니

게정 조직가입이랑 인증을 안해서 그런듯하다.

 

 

 

조직 만들고 계정인증을하니 마참네 

메타 호라이즌 앱에서 개발자모드를 열었다!

 

 

 

 

 

아직 유니티에서 찾질 못하니 한번 퀘스트랑 유니티 재시작해보고

 

 

미인증된 장치를 찾았다고하는데 여전히 연결이 되진 않는다.

 

 

계속 진해앟다보니 이젠 미인증 장치 찾았다는 내용도안뜬다 --

 

오 개발자 모드로 하고 몇번껏다켯더니 usb 디버깅모드 할지 묻는글이 나온다.

 

디버깅모드 온하니 이제 정상적으로 찾아내서 빌드까지 가능

 

 

근대 퀘스트2에서도 앱이실행되기는한데 뭔가 이상하다 이유는 모르겠음.

화면 전환도 안되고 세로로 길고 

오랜만에 본 책인 그림으로배우는 http & network

 

이거 보기전에 다른것도 짧게 몇개 보긴했지만

책 리뷰글 쓰기 귀찬아서 게으름피우다가

간만에 쓴다.

 

그래봣자 리뷰 글이라고 할만큼 

책을 열심히 본것도 아니고 중간에 대충 넘어간 부분이 대부분이라 쓸내용이 없긴한데

 

일단 책 제목에 베이직이라는 단어가 있지만

생각보다 깊이 있는 내용들을 그림으로 가능한 쉽게 표현하려고 노력한 책으로 보이는데

 

HTTP 프로토콜에 대한 왠만한 대부분 내용들이 들어가 있다.

 

물론 지금은 HTTP만 쓰는게 아니라 보안을 위한 HTTPS 프로토콜에 대한 내용도

보안쪽을 내가 잘아는건아니지만 빈틈없이 포함되어 있다.

 

내가 이 책을 보기전에 생각한건

간단하게 그림으로 배우는 서버, 웹서버 통신 책 같이 얕고 넓은 내용인줄 알았는데

 

생각보다 깊이있는 내용들을 그림으로 표현해서 알려주려고한게 

이 책의 특징이 아닌가 싶다.

 

오라일리에서 나온 HTTP 책 두꺼운거?에 비하면

정말 친절한 책이라 생각된다.

 

https://www.yes24.com/Product/Goods/15894097

 

그림으로 배우는 HTTP & Network - 예스24

이 책은 웹의 근간을 이루는 HTTP를 중심으로 하여 웹, 인터넷 데이터 통신 분야의 기초가 되는 내용들을 다루고 있다. 관련 분야를 배우고자 하는 독자들을 위해 만화 캐릭터와 일러스트를 활용

www.yes24.com

 

오랜만에 쓰는 책 리뷰글이다.

 

이번에 본 책은 효율적 개발로 이끄는 파이썬 실천 기술

 

 

 

평소 개발 서적을 보면서 초급서는 엄청많은데에 비해 

읽기 좋은 중급서가 너무 없다 생각이 들때가 많았는데

 

이 책은 파이썬 기초 문법에서 패키징, 병렬처리 등 중급 내용까지 아우른다.

 

진지한 파이썬같이 다른 파이썬 중급서보다

가장 간단한 예시로 읽기 좋았던건 이책인듯하다.

 

이 책을 통해

그동안 이해가 잘 안되던 파이썬 패키지 __init__.py나

sdist, venv 구조가 조금은 감이 잡히더라

 

 

 

중고급서에 병렬처리니 단위테스트니 하는 내용들은 많은데

쓸일이 없으니 눈에 잘안들어오는데

그래도 오픈소스 쓰면서 자주 마주치는 위 내용들은 좀 이해하는데 도움되었음.

 

 

 

 

https://www.yes24.com/Product/Goods/99123748

 

효율적 개발로 이끄는 파이썬 실천 기술 - 예스24

프로그래밍에 대한 지식은 어느 정도 있지만,파이썬은 잘 모르는 분들을 위한 실천적 입문서!『효율적 개발로 이끄는 파이썬 실천 기술』은 이런 분들을 위한 읽기 쉬우면서도 얕지 않은 입문

www.yes24.com

 

 

 

 

 

신호

- 시간 흐름에 따라 변화하는 정보를 가진 질량

- 시간의 연속 유무에 따른 분류 : 연속시간 신호(아날로그), 이산시간 신호(디지털)

 

시스템

- 신호를 변형,저장 등 가공하는 과정

 

시스템 예시

1. 잡음 제거 시스템

2. 흐려짐 제거 시스템

 

 

신호의 예시

음성신호

영상신호

 

 

신호의 변환

- AD 변환 : 아날로그 신호 -> 디지털 신호

- DA 변환 : 디지털 신호 -> 아날로그 신호

 

 

원랜 오늘 사칙연산까지만 하려했는데

잠깐 시간도 남아서 논리연산 조금 해보려고한다.

 

시프트연산

- SHR para1, para2

 para1 : 작업 장소

 para2 : 오른쪽(왼쪽)로 이동할 비트수 주로 4배수

- SHL para1, para2

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov ax,0x1234
    
    PRINT_HEX 2,ax
    NEWLINE
    
    shl ax,4
    
    PRINT_HEX 2,ax
    NEWLINE
    
    mov [a], word 0x1234
    PRINT_HEX 2,a
    NEWLINE
    
    shr word [a], 4
    PRINT_HEX 2,a
    NEWLINE
    
    xor rax, rax
    ret

section .bss
    a resw 1

 

 

 

 

AND, OR, XOR, NOT 연산

- AND, OR, XOR para1, para2(para1 = para1연산para2)

- NOT para(para = not para)

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov al, 0b10110110
    mov bl, 0b01010101
    PRINT_HEX 1,al
    NEWLINE
    PRINT_HEX 1,bl
    NEWLINE
    
    and al, bl
    PRINT_HEX 1,al
    NEWLINE
    
    mov al, 0b10110110
    mov bl, 0b01010101
    or al,bl
    PRINT_HEX 1,al
    NEWLINE
    
    mov al, 0b10110110
    mov bl, 0b01010101
    xor al,bl
    PRINT_HEX 1,al
    NEWLINE
    
    mov al, 0b10110110
    not al
    PRINT_HEX 1,al
    NEWLINE
    
    xor rax, rax
    ret

 

 

문자열 출력하기

- PRINT_STRING : SASM에서 제공하는 문자열 출력 매크로 함수

- ssection .data에 바이트 연속으로 선언

PRINT_STRING param(출력할곳 주소)

* 문자열 종료시 0x00으로 표기

* NASM에선 ''나 ""둘다 문자열로 허용

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    PRINT_STRING msg1
    NEWLINE
    PRINT_STRING msg2
    NEWLINE
    PRINT_STRING msg3
    
    xor rax, rax
    ret
    
section .data
    msg1 db 'haha ',0x00
    msg2 db 'hellow !',0x00
    msg3 db "mnsg3 ok",0x00

 

 

입력받기

- SASM에서는 아래 두함수로 받을수 있음

- GET_DEC para1, para2 입력된 문자열 10진수로 인식

 para1 입력할 바이트 수 para2 입력받을 곳 레지스터나 메모리주소

- GET_HEX para1, para2 입력된 문자열 16진수로 인식

 para1 입력할 바이트 수 para2 입력받을 곳 레지스터나 메모리주소

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    GET_DEC 1,al    ;1바이트 입력
    GET_DEC 2,a     ;2바이트 입력
    
    PRINT_DEC 1,al
    NEWLINE
    PRINT_DEC 2,a
    xor rax, rax
    ret
    
section .bss
    a resw 1    ;2바이트 초기화되지않은 변수 a1개 선언

 

 

 

 

 

덧셈연산

- ADD para1, para2(para1 = para 1 + para2)

 para 1 : 레지스터나 메모리에있는값

 para2 : 레지스터, 메모리, 값

 *para1,2둘다 메모리인 경우는 안됨

 

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov ax,1    ;2바이트 레지스터에 1대입
    mov bx,3    ;2바이트레지스터 bx에 3대입
    
    add ax, bx
    PRINT_DEC 2,ax
    NEWLINE
    
    mov [a], word 7 ;2바이트 변수 a에 7대입
    add ax, [a]
    PRINT_DEC 2,ax
    NEWLINE
    
    mov bx, 2
    add [a], bx
    PRINT_DEC 2,a
    NEWLINE
    
    mov [b], byte 2
    ;add [a], [b] <= error!

    xor rax, rax
    ret
    
section .bss
    a resw 1
    b resw 1

 

 

 

뺄셈연산

- SUB para1, para2(para1 = para1 - para2)

 para1 : 레지스터 나 메모리 값

 para2 : 레지스터, 메모리, 값

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov ax,1
    mov bx,3
    
    sub ax, bx
    PRINT_DEC 2, ax
    NEWLINE
    
    mov [a], word 7
    sub ax, [a]
    PRINT_DEC 2,ax
    NEWLINE
    
    mov bx,2
    sub [a],bx
    PRINT_DEC 2,a
    NEWLINE
    
    mov [b], byte 2
    PRINT_DEC 2,b
    ;sub [a], [b] <= 에러
    
    xor rax, rax
    ret
    
section .bss
    a resw 1
    b resw 1

 

 

 

1바이트 곱샘연산

- MUL para(1바이트)

* para가 1바이트일때 AX = AL * para

* para는 레지스터만 허용

*곱되는값은 무조건 AL레지스터에

*결과는 AX레지스터에 반환

 

아래 코드에서 ax레지스터를 0으로 초기화안하면 ah 레지스터값에 따라 영향받기 때문

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    PRINT_DEC 2,ax
    NEWLINE
    
    ;2*3
    mov ax,0
    mov al, 2
    mov bl, 3
    mul bx
    
    PRINT_DEC 1,ax
    NEWLINE

    xor rax, rax
    ret

 

 

 

1바이트 나누기 연산

- DIV para(1바이트)

* para가 1바이트일때 : AX / para : AL(몫), AH(나머지)

* 나눠지는값은 AX에

* 연산결과는 AL, AH로 리턴됨

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    ; 7(AX) / 2 = 3(AL, 몫), 1(AH, 나머지)
    
    mov ax, 7
    mov bl, 2
    div bl
    
    mov bl, ah
    
    PRINT_DEC 1,al
    NEWLINE
    PRINT_DEC 1,bl
    NEWLINE

    xor rax, rax
    ret

 

 

 

실행파일만들고 콘솔에서 실행해보기

코드작성 -> file에서 .exe 로 저장하기 -> 콘솔로 실행

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    PRINT_STRING msg1
    NEWLINE
    
    mov ax,3
    
    PRINT_DEC 2,ax
    NEWLINE

    xor rax, rax
    ret

section .data
    msg1 db "hello",0x00

 

 

 

 

 

사칙연산 계산기 만들기

- 2개의 변수를 1바이트 단위로 받아 메모리에 저장

- 사칙연산 한 값을 1바이트 단위 메모리에 각각 저장

- 나누기 결과는 몫과 나머지를 나누어 저장

- 곱의 경우 결과를 2바이트 변수로 선언하고 사용

- 이후 결과 모두 출력

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    ;input
    PRINT_STRING msg1
    GET_DEC 1,mya
    PRINT_DEC 1,mya
    NEWLINE
    
    PRINT_STRING msg1
    GET_DEC 1,myb
    PRINT_DEC 1,myb
    NEWLINE
    
    
    ;calc
    ;+
    mov al, [mya]
    mov bl, [myb]
    add al, bl
    mov [a], al
    
    ;-
    mov al, [mya]
    mov bl, [myb]
    sub al, bl
    mov [b], al
    
    ;*
    mov al, [mya]
    mov bl, [myb]
    mul bl
    mov [c], ax
    
    ;/
    mov ax,0
    mov al,[mya]
    mov bl,[myb]
    div bl;
    mov [d],al
    mov [e],ah
    
    
    
    
    ;output
    PRINT_STRING msg2
    PRINT_DEC 1,a
    NEWLINE
    
    PRINT_STRING msg3
    PRINT_DEC 1,b
    NEWLINE
    
    PRINT_STRING msg4
    PRINT_DEC 2,c
    NEWLINE
    
    PRINT_STRING msg5
    PRINT_DEC 1,d
    NEWLINE
    
    PRINT_STRING msg6
    PRINT_DEC 1,e
    NEWLINE
    

    xor rax, rax
    ret

section .data
    msg1 db 'input data:',0x00
    msg2 db '+:',0x00
    msg3 db '-:',0x00
    msg4 db '*:',0x00
    msg5 db '/(q):',0x00
    msg6 db '/(r):',0x00

section .bss
    mya resb 1; input 1
    myb resb 1; input 2
    a resb 1 ; +
    b resb 1 ; -
    c resw 1 ; *
    d resb 1 ; /(몫)
    e resb 1 ; /(나머지)

 

콘솔로 돌리기

 

 

워드

- CPU에서 처리하는 단위

- 16비트 CPU의 경우

- 16bit = 2byte = 1word

 

16진수 표기

- 10진수 10 = 16진수 0x0A

 

레지스터 크기

- 64bit OS는 64비트, 32bit os는 32비트 크기 레지스터 사용

- RAX :  64bit

- EAX : 32bit

- AX : 16bit

- AH, AL : 8bit

 

 

SASM 어셈블리 구조

- %include "io64.inc" : OS에 무관한 입출력 매크로 함수 지원

- section .text

  * section : 데이터나 명령을 모은 블록

- global main : 프로그램 시작점

 

 

 

레지스터 데이터 입력하기

- 주로 ABCD 레지스터 사용 (eax, ax, bx)

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov eax, 0x1234 ;A레지스터 32bit 크기에 0x1234저장
    mov ax, 0x1234  ;A레지스터 16bit 크기에 0x1234 저장
    mov ax, bx      ;bx의 값을 ax로 복사
    mov ax,ebx      ;[에러발생] ebx(32bit)값을 ax(16bit)에 저장시
    xor rax, rax도
    ret

 

 

 

 

 

어셈블리 메모리

- 메모리 사용 필요한것 : 메모리 크기, 메모리 위치

- 개발자는 메모리 크기 결정은 가능하나 주소는 모르므로 심벌(변수)로 설정하여 사용함.

아래의 경우

변수 명 : a

크기 : 2바이트

시작 주소 : 1

저장 값 : 0x1234

 

 

리틀엔디언 빅엔디언

- 메모리에 값(바이트) 저장하는 순서

- 위에서 0x1234가 1에 0x34, 2에 0x12가 들어가는것은 리틀엔디언방식

https://ko.wikipedia.org/wiki/%EC%97%94%EB%94%94%EC%96%B8

 

 

어셈블리 변수선언 (초기화 x)

- 초기화 하지 않은 변수는 .bss 블록에 언해야함

section .bss

    변수명    크기지시자    개수

 

크기지시자

resb 1바이트  byte?

resw 2바이트 word?

resd 4바이트 double word?

resq  8바이트 qaurd word?

 

 

 

어셈블리 변수선언 (초기화 o)

- 초기값이 있는 경우 section .data 블록에서 선언함

변수명    크기지시자    초기값

 

크기지시자

db 1바이트 바이트

dw 2바이트 워드

dd 4바이트 더블워드?

dq 8바이트 쿼드워드?

 

 

 

메모리 이용하기, 

- mov : 메모리에 데이터 보내기

 ex) 변수 a에 저장된 값을 ax 레지스터로 가져오라

  -> mov ax, [a]

변수명 = 주소, [변수명] = 주소에 있는값

* []는 c언어의 포인터 느낌으로 생각하면 될듯 []가 없는 변수는 주소 []가 있는 변수는 가리키는 곳

 

(주의) 어셈블리에서 변수 선언시 크기 지정해줘도 데이터는 크기를 명시해야함.

 

10번라인에서 데이터 크기 명시하지 않아 빌드 에러
바이트 명시시 빌드 성공

 

 

레지스터와 메모리 값 출력하기

- 레지스터, 메모리에 있는 값을 CPU 어셈블리만으로 출력은 힘듬. OS에 포함되어있기 때문.

- 운영체제와 무관하게 SASM에서 제공해주는 매크로 함수 사용하여 출력해보기

PRINT_HEX 바이트수, 레지스터혹은변수명 : 레지스터혹은변수명을 16진수로 출력

PRINT_DEC 바이트수, 레지스터혹은변수명 : 레지스터혹은변수명을 10진수로 출력

NEWLINE : 화면에 줄변경

 

* 0x12는 10진수로 16 + 2 = 18이 되므로 PRINT_DEC 2, ax(0x12)는 18이 맞음

 

 

데이터 옮기기 예제

1. 초기값 있는 메모리 변수 4개 선언 크기는 1,2,4,8바이트로 값은 16진수로 초기화

2. 초기값없는 메모리 변수 1, 2,4,8바이트 1개씩 선언하고 앞에서 선언한 값을 아래 선언한 변수로 이동

3. 변수 8개 모두 16진수로 출력

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov al,[a]      ;1바이트 크기 변수 a를 1바이트 레지스터 al에 저장
    mov [mya],al    ;1바이트 레지스터 al값을 mya에 저장
    
    mov ax,[b]      ;2바이트 크기 변수 b를 2바이트 레지스터 ax에 저장
    mov [myb],ax    ;2바이트 레지스터 ax값을 myb에 저장
    
    mov eax,[c]     ;4바이트 크기 변수 c를 4바이트 레지스터 eax에 저장
    mov [myc],eax
    
    mov rax,[d]
    mov [myd],rax
    
    
    PRINT_HEX 1,a   ;1바이트 단위로 변수 a값 16진수로 출력
    NEWLINE
    
    PRINT_HEX 2,b   ;2바이트 단위로 변수 b값 16진수로 출력
    NEWLINE
    
    PRINT_HEX 4,c   ;4바이트 단위로 변수 c값 16진수로 출력
    NEWLINE
    
    PRINT_HEX 8,d   ;8바이트 단위로 변수 d값 16진수로 출력
    NEWLINE
    
    PRINT_HEX 1,mya
    NEWLINE
    
    PRINT_HEX 2,myb
    NEWLINE
    
    PRINT_HEX 4,myc
    NEWLINE
    
    PRINT_HEX 8,myd
    
    xor rax, rax
    ret

section .data
    a db 0x12                   ;1바이트 변수 0x12
    b dw 0x1234                 ;2바이트 변수 0x1234
    c dd 0x12345678             ;4바이트 변수 c
    d dq 0x1234567812345678     ;8바이트 변수 d
  
section .bss
    mya resb 1  ;1바이트 초기화안된변수 선언
    myb resw 1  ;2바이트 초기화안된변수 myb선언
    myc resd 1  ;4바이트 초기화안된변수 myc선언
    myd resq 1  ;8바이트 초기화안된변수 myq선

 

주로 쓰는 어셈블러

- 윈도우 : MASM

- 리눅스/유닉스 : GAS

- 둘다 가능 : NSAM

 

 

사용할 어셈블러 ide

https://dman95.github.io/SASM/english.html

 

SASM - Simple crossplatform IDE for NASM, MASM, GAS, FASM assembly languages

SASM SASM (SimpleASM) - simple Open Source crossplatform IDE for NASM, MASM, GAS, FASM assembly languages. SASM has syntax highlighting and debugger. The program works out of the box and is great for beginners to learn assembly language. SASM is translated

dman95.github.io

 

 

 

 

 

보다보니

맨위에 

include io64.inc를 안해준게 문제더라

%include "io64.inc"

section .text
global main
main:
    ;write your code here
    mov eax,10
    PRINT_DEC 1, eax
    
    xor eax, eax
    ret

'컴퓨터과학 > os' 카테고리의 다른 글

어셈블리 - 3. 사칙연산  (0) 2024.04.14
어셈블리 - 2. 기초 개념들  (0) 2024.04.14
OS30 - 7. 글자쓰기  (0) 2024.04.08
OS30 - 6. c언어 사용, 화면 만들기  (0) 2024.04.05
OS30 - 5. ipl 만들기, c언어 진입  (0) 2024.04.05

먼저  어셈블리코드에서 부팅정보 가져오기

 

이전에 어샘해드.nas에 부트정보 표기했었는데 이걸 c에 가져와서 사용

 


void HariMain(void)
{
    char *vram;
    int xsize, ysize;
    short *binfo_scrnx, *binfo_scrny;
    int *binfo_vram;

    init_palette();
    binfo_scrnx = (short *)0x0ff4;
    binfo_scrny = (short *)0x0ff6;
    binfo_vram = (int *)0x0ff8;
    vram = (char *) *binfo_vram;
    xsize = *binfo_scrnx;
    ysize = *binfo_scrny;

 

 

구조체 사용해서 부트인포 정리

struct BOOTINFO {
    char cyls, leds, vmode, reserve;
    short scrnx, scrny;
    char *vram;
};

void HariMain(void)
{
    char *vram;
    int xsize, ysize;
    struct BOOTINFO *binfo;
 
 
    init_palette();
    binfo = (struct BOOTINFO *) 0x0ff0;
    xsize = (*binfo).scrnx;
    ysize = (*binfo).scrny;
    vram = (*binfo).vram;

 

 

화살표 연산자로 수정

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);
void init_screen(char *vram, int x, int y);

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

void HariMain(void)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
 
    init_palette();
    init_screen(binfo->vram, binfo->scrnx, binfo->scrny);

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

void init_screen(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;
}

 

 

 

글자 쓰기

putchar8로 폰트데이터 드로잉 구현

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);
void init_screen(char *vram, int x, int y);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);

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

void HariMain(void)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
    static char font_A[16] = {
        0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
        0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
    };

    init_palette();
    init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
    putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A);

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

void init_screen(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;
    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;}
    }

}

 

 

 

 

폰트 데이터 가져와 사용하기

위 예제에선 폰트 A 데이터를 직접 그려서 썻으나

아래 택스트 파일을 바이너리 이미지로 만들어 bootpack.obj와 합쳐서 사용함.

hankaku.txt
0.04MB

 

 

 

void HariMain(void)
{
    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
    extern char hankaku[4096];

    init_palette();
    init_screen(binfo->vram, binfo->scrnx, binfo->scrny);
    putfont8(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, hankaku + 'A' * 16);
    putfont8(binfo->vram, binfo->scrnx, 16, 8, COL8_FFFFFF, hankaku + 'B' * 16);
    putfont8(binfo->vram, binfo->scrnx, 24, 8, COL8_FFFFFF, hankaku + 'C' * 16);
    putfont8(binfo->vram, binfo->scrnx, 40, 8, COL8_FFFFFF, hankaku + '1' * 16);
    putfont8(binfo->vram, binfo->scrnx, 48, 8, COL8_FFFFFF, hankaku + '2' * 16);
    putfont8(binfo->vram, binfo->scrnx, 56, 8, COL8_FFFFFF, hankaku + '3' * 16);
    

    for(;;)
    {
        io_hlt();
    }
}

 

 

 

 

화면에 그리기위해

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

+ Recent posts