Эмуляция Линуса Торвальдса: создайте свою собственную операционную систему с нуля (III)

Мы продолжаем эту серию статей о том, как создать нашу операционную систему. Сегодня мы не собираемся останавливаться на одной теме, но с этого момента мы собираемся определить некоторые полезные функции. Сначала мы собираемся определить 3 функции, которые выполняют функцию тетсру, мемсет y память:

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 смоделированные функции, но для управления строками. Они будут выполнять функцию зЬгсру, strcat y стркмп.

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 внешний. Чтобы легко вызвать ASM из C, воспользуйтесь инструкцией 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. Ответственный за данные: Мигель Анхель Гатон
  2. Назначение данных: контроль спама, управление комментариями.
  3. Легитимация: ваше согласие
  4. Передача данных: данные не будут переданы третьим лицам, кроме как по закону.
  5. Хранение данных: база данных, размещенная в Occentus Networks (ЕС)
  6. Права: в любое время вы можете ограничить, восстановить и удалить свою информацию.

  1.   Имя сказал

    Посмотрим, прокомментируете ли вы, как исправить ошибку, потому что я не продвигался с первой части.

    1.    О_Pixote_O сказал

      Думаю, они прокомментировали ошибку в комментариях к посту 2. Они подумали, что это что-то из жратвы, если я правильно помню

  2.   Синий череп сказал

    Скопировать до свидания?

    1.    Синий череп сказал

      Байт за байтом очевидно ..., 2 последовательных отказа не приводят к успеху, подтверждено.

  3.   ruby232 сказал

    Большое спасибо за очень хороший пост, я слежу за ним, у меня есть несколько вопросов:
    1. Когда вы говорите: «Чтобы легко вызвать ASM из C, используется инструкция asm, с опасностью, что это влечет за собой непереносимость», что вы имеете в виду, когда говорите «с опасностью, что это влечет за собой непереносимость. '?

    2. Если бы должна была быть создана «профессиональная» операционная система (так сказать), эта часть доступа к Аппаратному обеспечению была бы выполнена на Ассемблере.

    3. Как это сделать на Ассемблере?

    1.    АдрианАрройоУлица сказал

      Спасибо, что подписались, отвечу на вопросы по очереди:
      1- Проблема с инструкцией asm в том, что она не существует ни в одном стандарте C, поэтому каждый компилятор реализует ее по-своему (если он это реализует). В этом случае он может быть скомпилирован с помощью GCC и Clang (в этом отношении он очень похож на GCC), но вы не сможете это сделать в других компиляторах, таких как Intel C (здесь используется синтаксис Intel в ASM).
      2- Профессионально одна часть должна быть четко разделена архитектурой и другой общей частью. Необязательно делать это на ассемблере (в Linux это внутри C)
      3- На ассемблере это тоже очень просто, но у вас это в отдельном файле. С другой стороны, имея аргументы, мы должны сначала передать их регистрам, и это может быть немного более запутанным, затем вызывается outb или inb, и функция объявляется как глобально видимая. Затем из C вы должны создать заголовок, объявляющий «внешнюю» функцию. В NASM (синтаксис Intel) это будет примерно так:
      выход:
      толкнуть ebp
      мов эбп, особенно

      mov eax, [ebp + 12]
      мов edx, [ebp + 8]

      вне дх, ал

      мов всп, эбп
      поп-эбп
      в отставке

  4.   Max сказал

    Вопрос, какой синтаксис вы используете? Я не понимаю, почему столько разных ассетов xD MASM, FASM, NASM, AT&T ...
    И если у вас будет время, не могли бы вы объяснить строчку:
    asm volatile ("outb% 1,% 0" :: "dN" (порт), "a" (значение));

    До "asm volatile" я понял xD "outbyte 1,0?"
    Или это 1 -> »dN» (порт), 0 -> «a» (значение)?
    Если последнее, я не понимаю, что такое «дн», а что «а» ...

    Большое спасибо за ваш вклад! Невероятно !!

    1.    АдрианАрройоУлица сказал

      Я использую синтаксис AT&T, который GCC использует для внутренних целей, хотя это может быть выполнено без проблем в NASM (адаптация синтаксиса). Что касается этого сложного оператора asm volatile, я могу только сказать вам, что это так из-за GCC, поскольку он использует некоторые параметры, чтобы знать, как должны передаваться данные. Например, «a» - это специальный операнд x86, используемый для представления регистра a. Весь список здесь: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   charizardfire52 сказал

    ну, мне действительно нужна помощь, я новичок в этом и не имею ни малейшего представления, что делать с тем, что написано в терминале, может кто-нибудь мне помочь?