Gewindecode

In der Informatik bezieht sich eingefädelter Code des Begriffes auf eine Bearbeiter-Durchführungstechnik, wo der erzeugte Code eine Form hat, die im Wesentlichen völlig aus Anrufen zu Unterprogrammen besteht. Der Code kann von einem Dolmetscher bearbeitet werden, oder kann einfach eine Folge von Maschinencodeanruf-Instruktionen sein.

Gewindecode hat bessere Codedichte als Code, der durch alternative Codegenerationstechniken und alternative rufende Vereinbarung, auf Kosten der ein bisschen langsameren Ausführungsgeschwindigkeit (gewöhnlich nur eine Maschineninstruktion) erzeugt ist. Jedoch kann ein Programm, das klein genug ist, um völlig in einem geheimen Computerverarbeiter-Lager zu passen, schneller laufen als ein größeres Programm, das vieles geheimes Lager Fräulein erträgt.

Gewindecode ist als die Durchführungstechnik am besten bekannt, die allgemein auf einigen Programmiersprachen, solcher als Hervor, viele Durchführungen von GRUNDLEGENDEN, einige Durchführungen des COBOL, frühe Versionen von B und andere Sprachen für kleine Minicomputer und Amateurradiosatelliten verwendet ist.

Vorbereitungsgeschichte

Die allgemeine Weise, Computerprogramme zu machen, soll ein auf einer symbolischen Sprache geschriebenes Computerprogramm 'übersetzen', um Code mit einem Bearbeiter maschinell herzustellen. Der Code ist normalerweise schnell, aber nichttragbar, da der binäre Code für eine spezifische Computerhardware-Plattform entworfen wird.

Eine verschiedene Annäherung verwendet einen virtuellen Maschinenbefehlssatz - der keine besondere Zielhardware hat. Ein Dolmetscher führt es auf jeder neuen Zielhardware durch.

Frühe Computer hatten relativ wenig Gedächtnis. Zum Beispiel hatten der grösste Teil von Datengeneral Nova, IBM 1130 und viele Computer des Apple II nur 4 K Wörter des installierten RAM. Folglich wurde viel Zeit verbracht versuchend, Weisen zu finden, die Größe von Programmen zu reduzieren, so würden sie das verfügbare Gedächtnis einfügen. Zur gleichen Zeit waren Computer relativ langsam, so war einfache Interpretation sehr merklich langsamer als Durchführung des Maschinencodes.

Anstatt jeden Schritt einer Operation in jedem Teil des Programms auszuschreiben, wo es erforderlich war, haben Programmierer Gedächtnis gespart, indem sie jeden Schritt über solche Operationen wie geschrieben haben (sieh "Wiederholen sich" nicht), und das Stellen davon in einem Unterprogramm.

Dieser Prozess - Codewiederfactoring - wird heute, obwohl aus verschiedenen Gründen verwendet. Die Anwendung auf höchster Ebene in diesen Programmen kann aus nichts als Unterprogramm-Anrufen bestehen. Viele dieser Unterprogramme bestehen abwechselnd auch aus nichts als Unterprogramm-Anrufen der niedrigeren Ebene.

Großrechner und einige frühe Mikroprozessoren wie RCA 1802 haben mehrere Instruktionen verlangt, ein Unterprogramm zu nennen. In der Anwendung auf höchster Ebene und in vielen Unterprogrammen wird diese Folge ständig, nur die Unterprogramm-Adresse wiederholt, die sich von einem Anruf zum folgenden ändert. Das Verwenden des Gedächtnisses, um dieselben Instruktionen zu versorgen, ist wiederholt verschwenderisch.

Um Raum zu sparen, haben Programmierer diese Reihe von Unterprogramm-Anrufen in eine Liste gedrückt, die nur aneinander grenzende Adressen der Unterprogramme enthält, und haben einen winzigen "Dolmetscher" verwendet, um jedes Unterprogramm der Reihe nach zu nennen.

Das ist zur Weise identisch, wie andere Programmierer eine Reihe von Sprüngen in einem Zweigtisch, Absendungstisch oder virtuellem Methode-Tisch in eine Liste gedrückt haben, die nur die Bestimmungsort-Adressen enthält, und einen kleinen Auswählenden am Zweig zum ausgewählten Bestimmungsort verwendet sind.

Im Gewindecode und diesen anderen Techniken wird das Programm eine Liste von Zugang-Punkten zum wirklichen durchzuführenden Code.

Im Laufe der Jahre haben Programmierer viele Schwankungen auf diesem "Dolmetscher" oder "kleinem Auswählendem" geschaffen.

Die besondere Adresse in der Liste von Adressen kann mit einem Index, allgemeinem Zweck-Register oder Zeigestock herausgezogen werden. Die Adressen können direkt oder indirekt, aneinander grenzend oder (verbunden durch Zeigestöcke) aneinander nichtgrenzend, relativ oder, aufgelösten während der Übersetzung oder dynamisch gebauten absolut sein.

Keine Schwankung ist "am besten".

Entwicklung

Um Raum zu sparen, haben Programmierer die Listen von Unterprogramm-Anrufen in einfache Listen von Unterprogramm-Adressen gedrückt, und haben eine kleine Schleife verwendet, um jedes Unterprogramm der Reihe nach zu nennen. Zum Beispiel:

Anfang:

ip =

&thread

Spitze:

springen Sie *ip ++

Faden:

&pushA &pushB &add

...

pushA:

*sp ++ = Ein

springen Sie Spitze

pushB:

*sp ++ = B

springen Sie Spitze

tragen Sie bei:

*sp ++ = * - sp + * - sp

springen Sie Spitze

</pre>

In diesem Fall wird Entzifferung des bytecodes einmal durchgeführt, während der Programm-Kompilation oder Programm-Last, so wird es jedes Mal nicht wiederholt, wird eine Instruktion durchgeführt. Das kann viel Zeit und Raum sparen, wenn decodieren und entsenden, oben ist im Vergleich zu den Ausführungskosten groß.

Bemerken Sie jedoch, Adressen in dafür, sind usw. zwei oder mehr Bytes im Vergleich zu einem Byte normalerweise für das Decodieren und entsenden Dolmetscher, der oben beschrieben ist. Im Allgemeinen können Instruktionen für einen Decodieren- und Absendungsdolmetscher jede Größe sein. Zum Beispiel decodiert ein Decodieren- und Absendungsdolmetscher, um Intel Pentium vorzutäuschen, Instruktionen diese Reihe von 1 bis 16 Bytes. Jedoch, bytecoded Systeme wählen normalerweise 1-Byte-Codes für die meisten - allgemeine Operationen. So hat der Faden häufig höhere Raumkosten als bytecodes. Im grössten Teil des Gebrauches decodiert die Verminderung dessen Kosten überwiegt die Zunahme in Raumkosten.

Bemerken Sie auch, dass, während bytecodes nominell maschinenunabhängig sind, das Format und der Wert der Zeigestöcke in Fäden allgemein von der Zielmaschine abhängen, die den Dolmetscher hinrichtet. So könnte ein Dolmetscher ein tragbares bytecode Programm laden, den bytecodes decodieren, um eingefädelten Code des Plattform-Abhängigen zu erzeugen, dann eingefädelten Code ohne weitere Verweisung auf den bytecodes durchzuführen.

Die Schleife ist einfach, so wird in jedem Dressierer kopiert, von der Liste von Maschineninstruktionen umziehend, musste jede Dolmetscher-Instruktion durchführen. Zum Beispiel:

Anfang: ip = &thread springen Sie *ip ++Faden: &pushA &pushB &add ...pushA: *sp ++ = Ein springen Sie *ip ++pushB: *sp ++ = B springen Sie *ip ++tragen Sie bei: *sp ++ = * - sp + * - sp springen Sie *ip ++</pre>

Das wird direkten Gewindecode (DTC) genannt. Obwohl die Technik älter ist, ist der erste weit in Umlauf gesetzte Gebrauch des Begriffes "Gewindecode" wahrscheinlich der Artikel "Threaded Code" von Bell von 1973.

Charles H. Moore hat eine kompaktere Notation 1970 für seine Hervor virtuelle Maschine erfunden: indirekter Gewindecode (ITC). Ursprünglich hat Moore das erfunden, weil es leicht und auf Minicomputern von Nova schnell war, die ein Umweg-Bit in jeder Adresse haben. Er hat gesagt (in veröffentlichten Bemerkungen, Byte-Zeitschrift Hervor Problem), dass er es so günstig gefunden hat, dass er es in alle später Hervor Designs fortgepflanzt hat.

Einige Hervor kompilieren Bearbeiter Hervor Programme in den direkt eingefädelten Code, während andere indirekt eingefädelten Code machen. Die Programme handeln derselbe jeder Weg.

Das Einfädeln von Modellen

Praktisch verwendet der ganze rechtskräftige Gewindecode ein, oder eine andere dieser Methoden, um Unterprogramme anzurufen (wird jede Methode ein "einfädelndes Modell" genannt).

Das direkte Einfädeln

Adressen im Faden sind die Adressen der Maschinensprache. Diese Form ist einfach, aber kann allgemeine Kosten haben, weil der Faden nur aus Maschinenadressen besteht, so müssen alle weiteren Rahmen indirekt auswendig geladen werden. Einige Hervor Systeme erzeugen direkt eingefädelten Code. Auf vielen Maschinen ist direkt einfädelnder schneller als einfädelndes Unterprogramm (sieh Verweisung unten).

Als Beispiel könnte eine Stapel-Maschine die Folge durchführen "stoßen A, stoßen B, tragen bei". Das könnte zum folgenden Faden und den Routinen übersetzt werden, wo zur Adresse initialisiert wird.

Faden: pushA: *sp ++ = Ein pushB: *sp ++ = B tragen bei: *sp ++ = * - sp + * - sp

&pushA springen *ip ++ Sprung *ip ++ Sprung *ip ++

&pushB &add ...</pre>

Wechselweise kann operands in den Faden eingeschlossen werden. Das kann einen Umweg entfernen, der oben erforderlich ist, aber macht den Faden größer:

Faden: Stoß: *sp ++ = *ip ++ tragen bei: *sp ++ = * - sp + * - sp

&push springen *ip ++ Sprung *ip ++

&A &push &B &add </pre>

Das indirekte Einfädeln

Indirekte einfädelnde Gebrauch-Zeigestöcke zu Positionen, die der Reihe nach zum Maschinencode hinweisen. Dem indirekten Zeigestock kann von operands gefolgt werden, die im indirekten "Block" versorgt werden, anstatt sie wiederholt im Faden zu versorgen. So ist indirekter Code häufig kompakter als direkt eingefädelter Code, aber der Umweg macht es auch normalerweise langsamer, obwohl noch gewöhnlich schneller als bytecode Dolmetscher. Wo der Dressierer operands sowohl Werte als auch Typen einschließt, können die Raumersparnisse über den direkt eingefädelten Code bedeutend sein. Älter HERVOR erzeugen Systeme normalerweise indirekt eingefädelten Code.

Als Beispiel, wenn die Absicht ist, "Stoß durchzuführen, tragen A, Stoß-B, bei" könnte der folgende verwendet werden. Hier, wird initialisiert, um, jedes Codebruchstück zu richten wird durch den doppelten-indirecting durch gefunden; und operands zu jedem Codebruchstück werden im Umweg des ersten Niveaus im Anschluss an die Adresse des Bruchstücks gefunden.

Faden: i_pushA: Stoßen Sie: Tragen Sie bei:

&i_pushA &push *sp ++ = * (*ip + 1) *sp ++ = * - sp + * - sp

&i_pushB &A springen * (*ip ++) Sprung * (*ip ++)

&i_add i_pushB:

&push &B

i_add:

&add </pre>

Einfädelndes Unterprogramm

So genannter "Unterprogramm-Gewindecode" (auch "Anruf-Gewindecode") besteht aus einer Reihe von maschinensprachigen "Anruf"-Instruktionen (oder Adressen von Funktionen, im Vergleich mit dem Gebrauch des direkten threading "des Sprungs" "zu rufen"). Frühe Bearbeiter für Algol, Fortran, COBOL und einige Hervor Systeme haben häufig Unterprogramm-Gewindecode erzeugt. Der Code in vielen dieser Systeme hat auf in umgekehrter Reihenfolge (LIFO) Stapel von operands funktioniert, der Bearbeiter-Theorie gut entwickelt hatte. Die meisten modernen Verarbeiter haben spezielle Hardware-Unterstützung für das Unterprogramm "Anruf" und "Rück"-Instruktionen, so werden die Gemeinkosten einer Extramaschineninstruktion pro Absendung etwas verringert. Anton Ertl hat festgestellt, "dass, im Gegensatz zu populären Mythen, einfädelndes Unterprogramm gewöhnlich langsamer ist als das direkte Einfädeln." Jedoch zeigen die neusten Tests von Ertl, dass einfädelndes Unterprogramm schneller ist als das direkte Einfädeln in 15 aus 25 Testfällen. Die neusten Tests von Ertl zeigen, dass das direkte Einfädeln das schnellste einfädelnde Modell auf Xeon, Opteron und Verarbeitern von Athlon ist; das indirekte Einfädeln ist das schnellste einfädelnde Modell auf Pentium M Verarbeiter; und einfädelndes Unterprogramm ist das schnellste einfädelnde Modell auf Pentium 4, Pentium III und PPC-Verarbeiter.

Als ein Beispiel des Anrufs, der "Stoß A einfädelt, stoßen Sie B, tragen Sie bei":

Faden: pushA: pushB: Tragen Sie bei:

nennen Sie pushA *sp ++ = Ein *sp ++ = B *sp ++ = * - sp + * - sp

rufen Sie pushB rösten rösten rösten

Anruf fügt hinzu

</pre>

Das Scheineinfädeln

Jeton hat Codegebrauch-Listen von 8 oder 12 Bit-Indizes zu einem Tisch von Zeigestöcken eingefädelt. Eingefädelter Code des Jetons ist namentlich ohne viel spezielle Anstrengung durch einen Programmierer kompakt. Es ist gewöhnlich Hälfte zu Dreivierteln die Größe anderer Gewindecodes, die selbst ein Viertel zu einem achten die Größe des kompilierten Codes sind. Die Zeigestöcke des Tisches können entweder indirekt oder direkt sein. Einige Hervor Bearbeiter erzeugen eingefädelten Code des Jetons. Einige Programmierer betrachten den "P-Code" als erzeugt durch einige Bearbeiter von Pascal, sowie den bytecodes verwendet durch.NET, Java, GRUNDLEGEND und einige C Bearbeiter, um das Scheineinfädeln zu sein.

Eine einheitliche Methode ist historisch bytecode, der 8 Bit opcodes und, häufig, eine Stapel-basierte virtuelle Maschine verwendet. Ein typischer Dolmetscher ist bekannt, weil "decodieren und Dolmetscher entsenden", und der Form folgt

bytecode: Spitze: pushA: pushB: Tragen Sie bei:

0/*pusha*/i = decodieren (vpc ++) *sp ++ = Ein *sp ++ = B *sp ++ = * - sp + * - sp

1/*pushb*/addr = Tisch springe [ich] Spitzensprung-Spitzensprung-Spitze

2/*add*/springen *addr

</pre>

Wenn die virtuelle Maschine nur Instruktionen der Byte-Größe verwendet, einfach ein Abruf davon ist, aber häufig dort werden 1-Byte-Instruktionen plus etwas weniger - allgemeine Mehrbyte-Instruktionen allgemein verwendet, in welchem Fall komplizierter ist. Die Entzifferung des einzelnen Bytes opcodes kann sehr einfach durch einen Zweigtisch mit dem opcode direkt als ein Index und effizient behandelt werden.

Für Instruktionen, wo die individuellen Operationen wie "Stoß" einfach sind und "beitragen", ist das am Entscheiden beteiligte oberirdische, was man durchführt, größer als die Kosten der wirklichen Durchführung davon, so sind solche Dolmetscher häufig viel langsamer als Maschinencode. Jedoch für kompliziertere ("zusammengesetzte") Instruktionen ist der Oberprozentsatz proportional weniger bedeutend.

Huffman, der einfädelt

Huffmans eingefädelter Code besteht aus Listen von Codes von Huffman. Ein Code von Huffman ist eine Bit-Schnur der variablen Länge hat gepflegt, einen einzigartigen Artikel zu identifizieren. Ein Huffman-Gewindedolmetscher macht Unterprogramme mit einem Index-Tisch oder Baum von Zeigestöcken ausfindig, die durch den Code von Huffman befahren werden können. Huffmans eingefädelter Code ist eine der kompaktesten für ein Computerprogramm bekannten Darstellungen. Grundsätzlich werden der Index und die Codes durch das Messen der Frequenz organisiert, dass jedes Unterprogramm im Code vorkommt. Häufige Anrufe werden die kürzesten Codes gegeben. Operationen mit ungefähr gleichen Frequenzen werden Codes mit fast gleichen Bit-Längen gegeben. Die meisten Huffman-Gewindesysteme, sind wie direkt eingefädelt, Hervor Systeme durchgeführt und verwendet worden, um große Beträge des langsam laufenden Codes in kleine, preiswerte Mikrokontrolleure einzupacken. Der grösste Teil des veröffentlichten Gebrauches ist in Spielsachen, Rechenmaschinen und Bewachungen gewesen.

Das kleinere verwendete Einfädeln

  • Einfädelnde Schnur, wo Operationen durch Schnuren identifiziert werden, die gewöhnlich durch eine Hash-Tabelle geschaut sind. Das wurde in Charles H. Moore am frühsten Hervor Durchführungen und in der Universität von Illinois experimenteller Hardware-interpretierter Computersprache verwendet. Es wird auch in Bashforth verwendet.

Zweige

Beispiele zeigen oben keine Zweige. Für alle Dolmetscher ändert ein Zweig den Faden-Zeigestock (oben). Als Beispiel könnte ein bedingter Zweig, wenn der Wert der Spitze des Stapels Null ist, wie folgt verschlüsselt werden. Bemerken Sie, dass das die Position ist, um zu, nicht die Adresse eines Dressierers zu springen, und so ausgelassen werden muss , ob der Zweig genommen wird.

Faden: brz:

... tmp = *ip ++

&brz wenn (*sp ++ == 0)

&thread [123] ip = tmp

... springen Sie *ip ++

</pre>

Allgemeine Annehmlichkeiten

Das Trennen der Daten und Rückstapel in einer Maschine beseitigt sehr viel Stapel-Verwaltungscode, wesentlich die Größe des Gewindecodes reduzierend. Der Doppelstapel-Grundsatz wurde dreimal unabhängig hervorgebracht: Für Burroughs große Systeme, Hervor und PostScript, und wird im einem Java virtuelle Maschinen verwendet.

Drei Register sind häufig in einer virtuellen Gewindemaschine da. Ein anderer besteht für vorübergehende Daten zwischen Unterprogrammen ('Wörter'). Diese sind:

  • ip oder ich (Instruktionszeigestock) der virtuellen Maschine (um mit dem Programm-Schalter der zu Grunde liegenden Hardware nicht verwirrt zu sein, die den VM durchführt)
  • w (Arbeitszeigestock)
  • rp oder r (geben Stapel-Zeigestock zurück)
  • sp oder s (Parameter-Stapel-Zeigestock für vorübergehende Rahmen zwischen Wörtern)

Häufig haben virtuelle Gewindemaschinen wie Durchführungen dessen Hervor eine einfache virtuelle Maschine im Innersten, aus drei Primitiven bestehend. Diejenigen sind:

  • Nest, auch genannt docol
  • Unnest oder semi_s (s)
  • folgender

In einer indirekt eingefädelten virtuellen Maschine, ein gegebener hier, sind die Operationen:

als nächstes: (ip) +-> w; jmp (w) +

Nest: ip-> - (rp); w-> ip; folgender

Unnest: (rp) +-> ip; folgender

Das ist vielleicht der einfachste und schnellste Dolmetscher oder die virtuelle Maschine.

Siehe auch

  • Verlängerung passierender Stil, der die globale Variable durch einen Funktionsparameter ersetzt
  • Schwanz recursion
  • Gerade rechtzeitig Kompilation
  • Zweigtisch

Weiterführende Literatur


Das CDR Codieren / Instrumente von Texas
Impressum & Datenschutz