Linus Torvaldsin jäljitteleminen: Luo oma käyttöjärjestelmäsi tyhjästä (III)

Jatkamme tätä viestisarjaa käyttöjärjestelmän luomisesta. Tänään emme keskity yhteen aiheeseen, mutta aiomme määritellä joitain hyödyllisiä toimintoja tästä lähtien. Ensin aiomme määritellä 3 toimintoa, jotka täyttävät funktion muisti, memeset 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;
}

Ne kaikki ovat itse toteuttavia. Nämä toiminnot olen ottanut pienestä C-kirjastosta, toteutus on yleensä samanlainen kaikissa käyttöjärjestelmissä. Nyt aiomme tehdä kolme simuloitua toimintoa, mutta manipuloida merkkijonoja. Ne täyttävät 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;
}

Menemme nyt melko mielenkiintoisilla toiminnoilla. Näillä toiminnoilla voimme lukea ja kirjoittaa laitteistoportteihin. Tämä tehdään yleensä ASM: llä ja vastaa (x86: lla) ohjeita in y ulos. Soita ASM: lle helposti C: stä käyttämällä ohjetta ASM, vaaralla, että se merkitsee sitä, että sitä ei ole kannettava. Tähän lauseeseen lisätään haihtuva jotta GCC ei yritä optimoida tekstiä. Toisaalta asm-käskyllä ​​on utelias tapa hyväksyä parametrit, mutta mielestäni se ymmärretään paremmin tarkastelemalla esimerkkejä.

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

Ja toistaiseksi postitse 3, tänään emme ole tehneet mitään näyttävää, mutta olemme määrittäneet toiminnot, jotka ovat hyödyllisiä tulevaisuuden kannalta. Huomaa 64-bittisille käyttäjille, että työskentelen a vika mikä estää oikean 64-bittisen kokoamisen. Seuraavassa viestissä näemme tärkeä osa x86-arkkitehtuuria, GDT.


Jätä kommentti

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

*

*

  1. Vastuussa tiedoista: Miguel Ángel Gatón
  2. Tietojen tarkoitus: Roskapostin hallinta, kommenttien hallinta.
  3. Laillistaminen: Suostumuksesi
  4. Tietojen välittäminen: Tietoja ei luovuteta kolmansille osapuolille muutoin kuin lain nojalla.
  5. Tietojen varastointi: Occentus Networks (EU) isännöi tietokantaa
  6. Oikeudet: Voit milloin tahansa rajoittaa, palauttaa ja poistaa tietojasi.

  1.   nimi dijo

    Katsotaanpa, kommentoitko virheen, koska en edennyt ensimmäisestä osasta.

    1.    O_Pixote_O dijo

      Luulen, että he kommentoivat virhettä postin 2 kommenteissa. He ajattelivat sen olevan jotain grubista, jos muistan oikein

  2.   SininenKallo dijo

    Kopioidaanko hei hei?

    1.    SininenKallo dijo

      Tavu tavuilta tietysti ..., 2 peräkkäistä epäonnistumista ei onnistu, vahvisti.

  3.   ruby232 dijo

    Paljon kiitoksia erittäin hyvästä viestistä ja seuraan sitä, minulla on joitain kysymyksiä:
    1. Kun sanot "Jos haluat soittaa ASM: lle helposti C: ltä, käytetään asm-käskyä, vaarana, että se merkitsee sitä, että se ei ole kannettava", mitä tarkoitat, kun sanot "vaaralla, että se merkitsee, että sitä ei ole kannettava" '?

    2. Jos "ammattimainen" käyttöjärjestelmä tehdään (niin sanotusti), tämä osa laitteiston käyttämistä suoritetaan Assemblerissä.

    3. Kuinka se tehdään Assemblerissä?

    1.    AdrianArroyoKatu dijo

      Kiitos, että noudatit sitä, vastaan ​​kysymyksiin yksi kerrallaan:
      1 - No, asm-käskyn ongelma on, että sitä ei ole missään C-standardissa, joten jokainen kääntäjä toteuttaa sen omalla tavallaan (jos se toteuttaa sen). Tässä tapauksessa se voidaan kääntää GCC: n ja Clangin kanssa (se näyttää tältä osin paljon GCC: ltä), mutta et voi muissa kääntäjissä, kuten Intel C: ssä (tämä käyttää Intel Syntaxia ASM: ssä).
      2 - Ammatillisesti yksi ja toinen osa tulisi erottaa selkeästi arkkitehtuureilla ja toinen yhteinen osa. Sitä ei tarvitse tehdä assemblerissa (Linuxilla on se C: n sisällä)
      3- Assemblerissä se on myös hyvin yksinkertainen, mutta sinulla on se erillisessä tiedostossa. Toisaalta, kun meillä on argumentteja, meidän on ensin siirrettävä se rekistereihin ja se voi sekoittaa hieman enemmän, sitten kutsutaan outb tai inb ja funktio julistetaan maailmanlaajuisesti näkyväksi. Sitten C: stä sinun on tehtävä otsikko, joka ilmoittaa "ulkoinen" -funktion. NASM: ssä (Intel Syntax) se olisi jotain tällaista:
      ulkoinen:
      työnnä ebp
      mov ebp, esp

      mov eax, [ebp + 12]
      mov edx, [ebp + 8]

      ulos dx, al

      mov esp, ebp
      pop ebp
      ret

  4.   max dijo

    Kysymys, mitä syntaksia käytät? En ymmärrä miksi niin monta erilaista asm xD MASM, FASM, NASM, AT & T ...
    Ja jos sinulla on aikaa, voisitko selittää rivin:
    asm haihtuva ("outb% 1,% 0" :: "dN" (portti), "a" (arvo));

    Kunnes "asm volatile" ymmärsin xD "outbyte 1,0?"
    Vai onko se 1 -> »dN» (portti), 0 -> «a» (arvo)?
    Jos se on jälkimmäinen, en ymmärrä mikä on "dn" ja mikä on "a" ...

    Paljon kiitoksia panoksestasi! Uskomatonta!

    1.    AdrianArroyoKatu dijo

      Syntaksi, jota käytän, on AT&T, jota GCC käyttää sisäisesti, vaikka se voidaan tehdä ongelmitta NASM: ssä (syntaksin mukauttaminen). Tästä monimutkaisesta asm volatile -lausekkeesta voin vain kertoa teille, että näin on GCC: n vuoksi, koska se käyttää joitain parametreja tietääkseen kuinka tiedot tulisi välittää. Esimerkiksi "a" on erityinen x86-operandi, jota käytetään edustamaan rekisteriä. Koko luettelo on täällä: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   charizardfire52 dijo

    Tarvitsen todella apua, olen tässä uusi ja minulla ei ole aavistustakaan, mitä tehdä terminaaliin kirjoitetulla.