Gépi kód vs oprendszer

Sziasztok,

Az addig okés, hogy a processzorok architektúrája különböző. Az is, hogy ezért más és más assembly-t kell használni, hogy más gépi kódot fordítson.

De, ha a gépi kód speciálisan egy processzorfajtára készül, akkor az a kód miért nem fut minden oprendszer alatt a célprocesszoron?

Gondolom azért, mert az oprendszerek hasonlóan működnek mint a java/.net VM, és különböző kódokat fogadnak el, amit aztán valós gépi kódra alakítanak. Ebben az esetben viszont nem értem, hogy miért kell különböző assembly utasításokkal dolgozni, ha úgyis csak egy köztes virtuálgépnek megy? Miért nem tudja a virtuálgép (oprendszer) átfordítani magának a "gépi kódot" feldolgozható, valós gépi kóddá?

Hozzászólások

"Miért nem tudja a virtuálgép (oprendszer) átfordítani magának a "gépi kódot" feldolgozható, valós gépi kóddá?"

Talán mert nem is akarja?
Mert nem az a dolga?

Mit is szeretnél csinálni?

"De, ha a gépi kód speciálisan egy processzorfajtára készül, akkor az a kód miért nem fut minden oprendszer alatt a célprocesszoron?"

Az egy dolog, hogy az assembler gépi kódra fordítja az assembly programot, ami így már értelmezhető bináris adathalmazzá - gépi kód - vált az adott processzorra, de az eltérő operációs rendszerek, más-más módon valósítják meg a tárkezelést, a futó processzek adminisztrálását, a címfordítást, stb. Ezért jön a már gépi kódra alakított file és egy, az adott operációs rendszeren futó program, a linker felfalja azt, a kódból kimutató hivatkozásokat feloldja, és a megfelelő fejléccel és struktúrákkal ellátja a gépi kódú programodat. Mivel minden operációs rendszer más, így az api felületük is más, egy funkció megvan ebben, nincs meg a másikban, esetleg másképpen kell hívni....tehát képtelenség amit kérdezel. Amikor egy operációs rendszer egy programot futtat, akkor nem fordít semmit sehová, mindössze betölti a tár egy szabad részére - memória menedzsment - a programodat vagy egy részét, a benne lévő címeket a fizikai helynek megfelelően újraszámolja, elvégez egy csomó adminisztrációt, de erre ne térjünk ki és ha minden flottul ment, akkor a kódod belépési pontjára adja a vezérlést. Hát ezért van az, hogy egy assembly kódot minden eltérő operációs rendszeren, ami fut az adott processzoron, le kell fordítani és linkelni kell. Nincs ezzel semmi baj, az assembly elég alacsony szintű nyelv, nem elvárás a hordozhatósága. Az az elvárás vele szemben, hogy az adott környezetben mindent meg tudjál vele csinálni, amire a vas képes. Ezt tudnia kell.

Egyébként ha egy operációs rendszer ismeri egy másik rendszer program fejlécének a struktúráját és nincs logikailag feloldhatatlan eltérés, akkor amennyiben a készítői vették a fáradtságot, futtatni is tudja az idegen binárist. Erre remek példa a linux. Ő ismer idegen binárist. Más kérdés, hogy mi lesz az api hívásokkal....

Na jó, kezdjük az elején, mert itt masszív fogalmi zavarok vannak.

1, Az assembly egy programozási nyelv
2, A gépi kód az, amit az assembly kódból a fordító lefordít

Bizonyos processzorcsaládok azonos utasításokat ismernek, pl. AT sorozat, vagy a jól ismert intel/amd x86. Eddig nagyjából világos. Amikor viszont egy assembly kódot lefordítasz, akkor kicsit sarkítva nem csak egy bináris, processzor által értelmezhető adathalmazt kapsz, hanem ezek bizonyos struktúrába lesznek pakolva. (lásd még http://en.wikipedia.org/wiki/Portable_Executable, http://en.wikipedia.org/wiki/Executable_and_Linkable_Format).

Amikor elindul egy alkalmazás, akkor az OS betölti a programot (mivel számára ismert formátumban van), és elindítja a végrehajtást. Miért nem tud futni a linuxon készített bináris alapból windows-on? Azért, mert az operációs rendszernek van egy rakás szolgáltatása (file kezelés, socket kezelés, procesz kezelés, stb.) amit a bináris kódod használ (lett lészen az bármilyen programozási nyelven írva), viszont ezt a másik OS nem ismeri.

http://www.tankonyvtar.hu/informatika/operacios-rendszerek-080905-377

A virtuális gépes hülyeséget felejtsd el, egyáltalán nem így működik.

a proci ugyanaz, a gepi kod ugyanaz.
Azonban a proci, es a gepi kod onmagaban meg nem teljes program, a legfontosabb kimaradt: az interakcio.
A program az valami adatot var (akar egy egerkattintast) es valami adatot ad ki (mondjuk rajzol).

Az interakcio (Input/Output muvelet) az oprendszer feladata. A program nem maga kommunikal, hanem megkeri az oprendszert szepen, hogy olvasson be/irjon ki neki.

Hogy ezt megtehesse, a CPU (gepi kod)-ban van erre utasitas, mas es mas architecturan mas es mas a neve: syscall, supervisor call, soft interrupt, ilyesmik.

Az, hogy melyik syscall mit jelent, es milyen parameterekkel kell hivni, az roppant oprendszer-specifikus. Hasonloan roppant oprendszer specifikus, hogy hogyan kapja meg a program a vezerlest (hogyan indul el).
Azonban csak ennyi. Nincs tobb. Ezeket az interakciokat lehet emulalni, szoktak is.
Igy mukodik peldaul, hogy a linuxos mplayer (i386 gepi kod, linux syscall) futtat windows ala irt codeceket (i386 gepi kod, windows syscall). Hasonlo az elve a wine emulatornak, gepi kod transzlaciot nem vegez, csak a win syscallokat forgatja linux syscall-ra.
Van meg *bsd alatt "linux binary compatibility" amivel lehetoseg van a linux binarisok *bsd alatti futtatasara, ez szinten syscall transzlaciot takar.

a pontossag vegett: a vegso programok altalaban nem hivnak kozvetlenul syscallt, hanem inkabb egy library rutint, ami majd syscallt hiv, ez az elven nem valtoztat, csak az emulator bonyolultsagan.