Linus Torvalds 에뮬레이션 : 처음부터 자신 만의 운영 체제 만들기 (III)

우리는 운영 체제를 만드는 방법에 대한이 일련의 게시물을 계속합니다. 오늘 우리는 한 가지 주제에 초점을 맞추지 않고 지금부터 몇 가지 유용한 기능을 정의 할 것입니다. 먼저 다음의 기능을 수행하는 3 가지 기능을 정의하겠습니다. 밈피, 멤셋 y memcmp:

void* ND::Memory::Set(void* buf, int c, size_t len)
{
unsigned char* tmp=(unsigned char*)buf;
while(len--)
{
*tmp++=c;
}
return buf;
}
void* ND::Memory::Copy(void* dest,const void* src, size_t len)
{
const unsigned char* sp=(const unsigned char*)src;
unsigned char* dp=(unsigned char*)dest;
for(;len!=0;len--) *dp++=*sp++;
return dest;
}
int ND::Memory::Compare(const void* p1, const void* p2, size_t len)
{
const char* a=(const char*)p1;
const char* b=(const char*)p2;
size_t i=0;
for(;i<len;i++)
{
if(a[i] < b[i]) return -1; else if(a[i] > b[i])
return 1;
}
return 0;
}

그들 모두는 자체 구현입니다. 작은 C 라이브러리에서 가져온 이러한 함수는 일반적으로 모든 운영 체제에서 구현이 유사합니다. 이제 우리는 3 개의 시뮬레이션 된 함수를 수행하지만 문자열을 조작 할 것입니다. 그들은의 기능을 수행 할 것입니다 strcpy, strcat y strcmp.

size_t ND::String::Length(const char* src)
{
size_t i=0;
while(*src--)
i++;
return i;
}
int ND::String::Copy(char* dest, const char* src)
{
int n = 0;
while (*src)
{
*dest++ = *src++;
n++;
}
*dest = '';
return n;
}
int ND::String::Compare(const char *p1, const char *p2)
{
int i = 0;
int failed = 0;
while(p1[i] != '' && p2[i] != '')
{
if(p1[i] != p2[i])
{
failed = 1;
break;
}
i++;
}
if( (p1[i] == '' && p2[i] != '') || (p1[i] != '' && p2[i] == '') )
failed = 1;
return failed;
}
char *ND::String::Concatenate(char *dest, const char *src)
{
int di = ND::String::Length(dest);
int si = 0;
while (src[si])
dest[di++] = src[si++];
dest[di] = '';
return dest;
}

우리는 이제 매우 흥미로운 몇 가지 기능을 살펴 보겠습니다. 이러한 기능을 사용하여 하드웨어 포트를 읽고 쓸 수 있습니다. 이것은 일반적으로 ASM으로 수행되며 x86에서 지침에 해당합니다. in y 아웃. C에서 ASM을 쉽게 호출하려면 다음 명령을 사용하십시오. asm, 휴대 할 수 없다는 위험이 있습니다. 이 문장에 우리는 휘발성의 GCC가 해당 텍스트를 최적화하지 않도록합니다. 반면에 asm 명령어는 매개 변수를 받아들이는 흥미로운 방법이 있지만 예제를 보면 더 잘 이해할 수 있다고 생각합니다.

void ND::Ports::OutputB(uint16_t port, uint8_t value)
{
asm volatile("outb %1, %0" : : "dN"(port), "a"(value));
}
uint8_t ND::Ports::InputB(uint16_t _port)
{
unsigned char rv;
asm volatile("inb %1, %0" : "=a"(rv) : "dN"(_port));
return rv;
}

그리고 지금까지 포스트 3, 오늘 우리는 화려한 작업을하지 않았지만 미래에 도움이 될 기능을 정의했습니다. 64 비트 사용자에게 내가 버그 64 비트에서 올바르게 컴파일하는 것을 방지합니다. 다음 게시물에서는 x86 아키텍처의 중요한 구성 요소 인 GDT를 살펴 보겠습니다.


코멘트를 남겨주세요

귀하의 이메일 주소는 공개되지 않습니다. 필수 필드가 표시되어 있습니다 *

*

*

  1. 데이터 책임자 : Miguel Ángel Gatón
  2. 데이터의 목적 : 스팸 제어, 댓글 관리.
  3. 합법성 : 귀하의 동의
  4. 데이터 전달 : 법적 의무에 의한 경우를 제외하고 데이터는 제 XNUMX 자에게 전달되지 않습니다.
  5. 데이터 저장소 : Occentus Networks (EU)에서 호스팅하는 데이터베이스
  6. 권리 : 귀하는 언제든지 귀하의 정보를 제한, 복구 및 삭제할 수 있습니다.

  1.   이름

    나는 첫 부분부터 진행하지 않았기 때문에 버그를 해결하는 방법에 대해 언급하는지 보자.

    1.    O_피소테_O

      게시물 2의 댓글에 오류에 대해 댓글을 남긴 것 같아요

  2.   푸른 해골

    작별을 복사 하시겠습니까?

    1.    푸른 해골

      분명히 바이트 단위로 ..., 두 번의 연속 실패는 성공하지 못합니다.

  3.   ruby232

    아주 좋은 게시물에 대해 대단히 감사 드리며 나는 그것을 따르고 있습니다. 몇 가지 질문이 있습니다.
    1. 'C에서 ASM을 쉽게 호출하려면 asm 명령어를 사용하는데, 휴대가 불가능하다는 위험이 있습니다.'라고 말하면 '수반되는 위험이있는 그것은 휴대용 '?

    2. 만약 '전문적인'운영체제가 만들어 졌다면 (말하자면) 하드웨어에 접근하는이 부분은 어셈블러에서 이루어집니다.

    3. 어셈블러에서는 어떻게됩니까?

    1.    AdrianArroyoStreet

      팔로우 해주셔서 감사합니다. 질문에 하나씩 답해 드리겠습니다.
      1- 음, asm 명령어의 문제점은 C 표준에 존재하지 않기 때문에 각 컴파일러는 자체 방식으로 구현합니다 (구현하는 경우). 이 경우 GCC 및 Clang으로 컴파일 할 수 있지만 (이 점에서 GCC와 비슷해 보임) Intel C와 같은 다른 컴파일러에서는 컴파일 할 수 없습니다 (ASM에서 Intel 구문 사용).
      2- 전문적으로, 한 부분과 다른 부분은 아키텍처와 다른 공통 부분으로 명확하게 분리되어야합니다. 어셈블러에서 할 필요가 없습니다 (리눅스는 C 안에 있습니다)
      3- 어셈블러에서도 매우 간단하지만 별도의 파일에 있습니다. 반면에 인수가 있으면 먼저 레지스터에 전달해야하며 약간 더 엉망이 될 수 있습니다. 그런 다음 outb 또는 inb가 호출되고 함수가 전역 적으로 표시되는 것으로 선언됩니다. 그런 다음 C에서 "extern"함수를 선언하는 헤더를 만들어야합니다. NASM (Intel Syntax)에서는 다음과 같습니다.
      outb :
      ebp 푸시
      이동 ebp, esp

      이동 eax, [ebp + 12]
      이동 edx, [ebp + 8]

      아웃 dx, al

      이동 ESP, EBP
      팝 ebp
      배제

  4.   Max

    질문, 어떤 구문을 사용합니까? 나는 왜 그렇게 많은 asm xD MASM, FASM, NASM, AT & T ...
    시간이 있으시다면 다음과 같이 설명해 주시겠습니까?
    asm 휘발성 ( "outb % 1, % 0":: "dN"(포트), "a"(값));

    "asm volatile"까지 xD "outbyte 1,0"을 이해 했습니까?
    아니면 1->»dN»(포트), 0->«a»(값)입니까?
    후자의 경우 "dn"이 무엇인지 "a"가 무엇인지 이해하지 못합니다.

    기여 해주셔서 감사합니다! 놀랍습니다!

    1.    AdrianArroyoStreet

      내가 사용하는 구문은 AT & T로 GCC가 내부적으로 사용하는 것이지만 NASM에서 문제없이 수행 할 수 있습니다 (구문 조정). asm volatile의 복잡한 문장에 관해서는 GCC 때문에 데이터가 어떻게 전달되어야하는지 알기 위해 몇 가지 매개 변수를 사용하기 때문에 그렇다고 말할 수 있습니다. 예를 들어 "a"는 레지스터를 나타내는 데 사용되는 특수 x86 피연산자입니다. 전체 목록은 다음과 같습니다. http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   charizardfire52

    글쎄, 나는 정말로 도움이 필요합니다. 나는 이것에 익숙하지 않으며 터미널에 쓰여진 것을 어떻게 해야할지 조금도 모릅니다.