Ons gaan hierdie reeks plasings voort oor hoe om ons bedryfstelsel te skep. Vandag gaan ons nie op een onderwerp fokus nie, maar ons gaan voortaan 'n paar nuttige funksies definieer. Eerstens gaan ons drie funksies definieer wat die funksie van vervul 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;
}
Almal is self-implementerend. Hierdie funksies het ek uit 'n klein C-biblioteek geneem. Die implementering is gewoonlik in alle bedryfstelsels soortgelyk. Nou gaan ons drie gesimuleerde funksies doen, maar om snare te manipuleer. Hulle sou die funksie van strcpy, strkat 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;
}
Ons gaan nou met 'n paar baie interessante funksies. Met hierdie funksies kan ons die hardeware-poorte lees en skryf. Dit word normaalweg met ASM gedoen en stem ooreen (op x86) met die instruksies in y uit. Gebruik die instruksie om ASM maklik van C af te skakel asma, met die gevaar dat dit meebring dat dit nie draagbaar is nie. By hierdie sin voeg ons die vlugtige sodat GCC nie probeer om die teks te optimaliseer nie. Aan die ander kant het die asm-instruksie 'n vreemde manier om parameters te aanvaar, maar ek dink dit word beter verstaan deur na die voorbeelde te kyk.
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;
}
En tot dusver post 3, het ons vandag nog niks opsigtelik gedoen nie, maar ons het 'n funksie gedefinieer wat handig te pas kom vir die toekoms. Let op aan 64-bis-gebruikers dat ek besig is om 'n fout wat verhoed dat dit korrek saamgestel word in 64 bisse. In die volgende berig sien ons 'n belangrike komponent van die x86-argitektuur, die GDT.
9 kommentaar, los joune
Kom ons kyk of u kommentaar lewer oor hoe u die fout kan oplos, want ek het nie van die eerste deel af gevorder nie.
Ek dink hulle het kommentaar gelewer op die fout in die kommentaar van post 2. Hulle het gedink dat dit iets van die vuilnis was as ek reg onthou
Kopie tot siens?
Byte vir byte blykbaar ... 2 agtereenvolgende mislukkings maak nie 'n sukses nie, bevestig.
Baie dankie vir die baie goeie boodskap en ek volg dit, ek het 'n paar vrae:
1. As u sê 'Om ASM maklik van C af te roep, word die asm-instruksie gebruik, met die gevaar dat dit inhou dat dit nie draagbaar is nie', wat bedoel u dan as u sê 'met die gevaar dat dit inhou dat dit nie draagbaar is nie '?
2. As 'n 'professionele' bedryfstelsel gemaak word (so te sê), sal hierdie deel van die toegang tot die hardeware in Assembler gedoen word.
3. Hoe sou dit in Assembler gedoen word?
Dankie dat u dit gevolg het, ek sal die vrae een vir een beantwoord:
1- Wel, die probleem met die asm-instruksie is dat dit in geen C-standaard bestaan nie, dus implementeer elke samesteller dit op sy eie manier (as dit implementeer). In hierdie geval kan dit saamgestel word met GCC en Clang (dit lyk in hierdie opsig baie soos GCC), maar in ander samestellers soos Intel C (dit gebruik Intel Syntax in ASM) sal u nie kan nie.
2- Professioneel moet die een en die ander dele duidelik van mekaar geskei word deur argitekture en 'n ander algemene deel. Dit is nie nodig om dit in samesteller te doen nie (Linux het dit in C)
3- In die samesteller is dit ook baie eenvoudig, maar u het dit in 'n aparte lêer. Aan die ander kant, as ons argumente het, moet ons dit eers aan die registers gee en dit kan 'n bietjie meer deurmekaar raak, dan word outb of inb aangeroep en die funksie as wêreldwyd sigbaar verklaar. Van C sal u dan 'n kop moet maak wat 'n 'eksterne' funksie verklaar. In NASM (Intel Syntax) sou dit so wees:
uitb:
druk ebp
mov ebp, esp
mov eax, [ebp + 12]
mov edx, [ebp + 8]
uit dx, al
mov esp, ebp
pop ebp
ret
Vraag, watter sintaksis gebruik jy? Ek verstaan nie waarom so baie verskillende asms xD MASM, FASM, NASM, AT & T ...
En as u tyd het, kan u die reël verduidelik:
asm vlugtig ("outb% 1,% 0" :: "dN" (poort), "a" (waarde));
Tot "asm vlugtig" het ek verstaan xD "outbyte 1,0?"
Of is dit 1 -> »dN» (poort), 0 -> «a» (waarde)?
As dit laasgenoemde is, verstaan ek nie wat "dn" en wat "a" is nie ...
Baie dankie vir u bydraes! Ongelooflik !!
Die sintaksis wat ek gebruik, is AT&T, wat GCC intern gebruik, alhoewel dit sonder probleme in NASM gedoen kan word (om die sintaksis aan te pas). Wat die ingewikkelde stelling van asm-vlugtige betref, kan ek u slegs vertel dat dit so is as gevolg van die GCC, omdat dit sommige parameters gebruik om te weet hoe die data oorgedra moet word. Byvoorbeeld "a" is 'n spesiale x86-operand wat gebruik word om die a-register voor te stel. Die volledige lys is hier: http://gcc.gnu.org/onlinedocs/gcc/Constraints.html#Constraints
wel, ek het regtig hulp nodig, ek is nuut hieroor en ek het nie die minste idee wat ek moet doen met wat in die terminale staan nie, kan iemand my help?