워드

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

 

 

 

 

+ Recent posts