Kopiante Linus Torvalds: Kreu vian propran operaciumon de nulo (III)

Ni daŭrigas ĉi tiun serion da afiŝoj pri kiel krei nian operaciumon. Hodiaŭ ni ne celos unu temon, sed ni difinos iujn utilajn funkciojn de nun. Unue ni difinos 3 funkciojn, kiuj plenumas la funkcion de memcpy, 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;
}

Ĉiuj estas memefektivigaj. Ĉi tiujn funkciojn mi prenis de malgranda C-biblioteko, la efektivigo kutime similas en ĉiuj operaciumoj. Nun ni faros 3 simulitajn funkciojn sed manipuli kordojn. Ili plenumus la funkcion de 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;
}

Ni iras nun kun sufiĉe interesaj funkcioj. Per ĉi tiuj funkcioj ni povas legi kaj skribi al la aparatoj. Ĉi tio kutime fariĝas per ASM kaj respondas (ĉe x86) al la instrukcioj in y eksteren. Por facile voki ASM de C, uzu la instrukcion asm, kun la danĝero, ke ĝi implicas, ke ĝi ne estas portebla. Al ĉi tiu frazo ni aldonas la flamiĝemaj por ke GCC ne provu optimumigi tiun tekston. Aliflanke, la asm-instrukcio havas kuriozan manieron akcepti parametrojn, sed mi pensas, ke oni pli bone komprenas ĝin rigardante la ekzemplojn.

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

Kaj ĝis nun post 3, hodiaŭ ni faris nenion okulfrapan, sed ni difinis funkciojn, kiuj utilos por la estonteco. Rimarku al 64-bitaj uzantoj, ke mi laboras pri riparado de cimo kio malebligas kompili ĝuste en 64 bitoj. En la sekva afiŝo ni vidos gravan eron de la x86-arkitekturo, la GDT.


La enhavo de la artikolo aliĝas al niaj principoj de redakcia etiko. Por raporti eraron alklaku Ĉi tie.

9 komentoj, lasu la viajn

Lasu vian komenton

Via retpoŝta adreso ne estos eldonita. Postulita kampojn estas markita per *

*

*

  1. Respondeculo pri la datumoj: Miguel Ángel Gatón
  2. Celo de la datumoj: Kontrola SPAM, administrado de komentoj.
  3. Legitimado: Via konsento
  4. Komunikado de la datumoj: La datumoj ne estos komunikitaj al triaj krom per laŭleĝa devo.
  5. Stokado de datumoj: Datumbazo gastigita de Occentus Networks (EU)
  6. Rajtoj: Iam ajn vi povas limigi, retrovi kaj forigi viajn informojn.

  1.   nomo diris

    Ni vidu, ĉu vi komentas kiel solvi la cimon, ĉar mi ne antaŭeniris de la unua parto.

    1.    O_Piksoto_O diris

      Mi pensas, ke ili komentis la eraron en la komentoj de afiŝo 2. Ili pensis, ke ĝi estas io de la larvo, se mi bone memoras

  2.   Blua kranio diris

    Ĉu kopii ĝis revido?

    1.    Blua kranio diris

      Bajto post bajto evidente ..., 2 sinsekvaj malsukcesoj ne sukcesas, konfirmite.

  3.   ruby232 diris

    Koran dankon pro la tre bona afiŝo kaj mi sekvas ĝin, mi havas iujn demandojn:
    1. Kiam vi diras 'Por facile voki ASM de C la asm-instrukcio estas uzata, kun la danĝero, ke ĝi implicas, ke ĝi ne estas portebla', kion vi celas, kiam vi diras, 'kun la danĝero, ke ĝi implicas, ke ĝi ne estas portebla. '?

    2. Se 'profesia' operaciumo kreiĝus (por tiel diri) ĉi tiu parto de aliro al la Aparataro fariĝus en Assembler.

    3. Kiel ĝi estus farita en Asemblisto?

    1.    AdrianArroyoStreet diris

      Dankon, ke vi sekvis ĝin, mi respondos la demandojn unu post la alia:
      1- Nu, la problemo kun la asm-instrukcio estas, ke ĝi ne ekzistas en iu ajn C-normo, do ĉiu kompililo efektivigas ĝin laŭ sia maniero (se ĝi efektivigas ĝin). Ĉi-kaze ĝi kompileblas kun GCC kaj Clang (ĝi aspektas tre kiel GCC tiurilate) sed vi ne povos en aliaj kompililoj kiel Intel C (ĉi tio uzas Intel-Sintakson en ASM).
      2- Profesie, unu parto kaj alia estu klare apartigitaj per arkitekturoj kaj alia komuna parto. Ne necesas fari ĝin en asemblero (Linukso havas ĝin en C)
      3- Ankaŭ en muntilo ĝi estas tre simpla, sed vi havas ĝin en aparta dosiero. Aliflanke, havante argumentojn ni devas unue transdoni ĝin al la registroj kaj tio povas fuŝi iomete pli, tiam outb aŭ inb estas alvokitaj kaj la funkcio estas deklarita kiel tutmonde videbla. Tiam de C vi devas fari kaplinion, kiu deklaras "eksteran" funkcion. En NASM (Intel-Sintakso) estus io tia:
      outb:
      puŝi ebp
      mov ebp, esp

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

      ekster dx, al

      mov esp, ebp
      pop ebp
      malakcepto

  4.   maks diris

    Demando, kian sintakson vi uzas? Mi ne komprenas kial tiom da malsamaj asm xD MASM, FASM, NASM, AT & T ...
    Kaj se vi havas tempon, ĉu vi povus klarigi la linion:
    asm volatile ("outb% 1,% 0" :: "dN" (haveno), "a" (valoro));

    Ĝis "asm volatile" ĉu mi komprenis xD "outbyte 1,0?"
    Aŭ ĉu ĝi estas 1 -> »dN» (haveno), 0 -> «a» (valoro)?
    Se ĝi estas ĉi-lasta, mi ne komprenas kio estas "dn" kaj kio estas "a" ...

    Koran dankon pro viaj kontribuoj! Nekredebla !!

    1.    AdrianArroyoStreet diris

      La sintakso, kiun mi uzas, estas AT&T, kion GCC uzas interne kvankam ĝi povas esti farita senprobleme en NASM (adaptante la sintakson). Pri tiu kompleksa aserto de asm volatile, mi povas nur diri al vi, ke ĝi estas la kazo pro la GCC, ĉar ĝi uzas iujn parametrojn por scii kiel la datumoj devas esti transdonitaj. Ekzemple "a" estas speciala x86-operando, kiu estas uzata por reprezenti la registron. La tuta listo estas ĉi tie: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints

  5.   charizardfire52 diris

    nu, mi vere bezonas helpon, mi novas pri tio kaj mi tute ne scias, kion fari kun tio, kio estas skribita en la fina stacio, ĉu iu povas helpi min?