In che modo le lingue hanno influenzato la progettazione della CPU? [chiuso]


44

Spesso ci viene detto che all'hardware non importa in quale lingua è scritto un programma poiché vede solo il codice binario compilato, tuttavia questa non è tutta la verità. Ad esempio, considera l'umile Z80; le sue estensioni al set di istruzioni 8080 includono istruzioni come CPIR che è utile per scansionare stringhe di tipo C (terminate con NULL), ad es. per eseguire strlen(). I progettisti devono aver identificato che l'esecuzione di programmi C (al contrario di Pascal, in cui la lunghezza di una stringa è nell'intestazione) era qualcosa per cui il loro progetto sarebbe stato probabilmente utilizzato. Un altro esempio classico è la macchina Lisp .

Quali altri esempi ci sono? Ad esempio istruzioni, numero e tipo di registri , modalità di indirizzamento, che rendono un processore particolare favorevole alle convenzioni di una lingua particolare? Sono particolarmente interessato alle revisioni della stessa famiglia.


3
Non dimenticare che lo Z-80 aveva anche l'istruzione LDIR, molto utile quando si copiano le stringhe quando si conosce la lunghezza (come in Pascal, dove la lunghezza era memorizzata nell'intestazione).
TMN,

27
1. La Z-80 è stata progettata nel 1975, quando Unix e C erano un sistema operativo e un linguaggio oscuri su pochi computer, 3 anni prima della prima edizione di K&R. 2. Non c'è nulla in Pascal che imponga che la lunghezza della stringa sia "in un'intestazione". 3. Le stringhe in CP / M, il principale sistema operativo per microcomputer dell'epoca, venivano terminate con il carattere "$", non "\ 0". CPIR potrebbe cercare qualsiasi personaggio. 4. CPIR è abbinato a CPDR (ricerca all'indietro), così come ad altre istruzioni -IR e -DR. Conclusione: CPIR non ha nulla a che fare con il linguaggio di programmazione C. È solo un'istruzione di ricerca byte.
librik,

4
Il più grande (e uno dei più fastidiosi per i progettisti dell'hardware) delle cose forzate da C è l'indirizzamento dei byte. Le CPU sarebbero state più semplici e veloci senza questo abominio.
SK-logic

1
@ SK-logic: sebbene lo standard POSIX richieda l'indirizzamento dei byte, lo standard C no. Qualsiasi implementazione in cui sizeof(int)uguale a 1 deve richiedere che il tipo charsia firmato (poiché intdeve essere in grado di contenere tutti i valori di tipo char). Ho scritto il codice per una macchina dove chare intsono interi sia a 16-bit con segno; le maggiori difficoltà sono che non è possibile utilizzare i sindacati per la conversione del tipo e l'archiviazione efficiente di un gran numero di byte richiede l'imballaggio e il disimballaggio manuali. Questi problemi sono minori rispetto alla possibilità in C che sizeof (int) == sizeof (long), dal ...
supercat

2
... ciò significa che non esiste un tipo standard che garantisca la differenza tra due unsigned intvalori. C99 ha migliorato questa situazione, ma prima di C99 non esisteva un modo sicuro in un solo passaggio per confrontare un valore potenzialmente negativo con un valore di tipo unsigned int(si dovrebbe verificare se il numero era negativo prima di fare il confronto).
supercat

Risposte:


20

Le risposte esistenti si concentrano sui cambiamenti ISA . Ci sono anche altre modifiche hardware. Ad esempio, C ++ usa comunemente vtables per le chiamate virtuali. A partire da Pentium M , Intel ha un componente "predittore di filiali indirette" che accelera le chiamate di funzione virtuale.


6
E l'architettura RISC di Berkeley includeva il concetto di "file di registro", quindi invece di creare funzioni che "versavano" registri nello stack, a ciascuna funzione veniva dato un blocco di 8 registri. Questo accelera notevolmente il codice orientato agli oggetti, poiché tende a consistere in molte chiamate di metodi a metodi brevi.
TMN

1
Questo non è un esempio valido. Il design "Tabella dei puntatori a funzione" viene utilizzato anche in molti scenari di collegamento dinamico, ad esempio tramite l'importazione e l'esportazione di DLL su Windows e utilizzato anche nei programmi C. Anche se immagino che potresti argomentare che mostra che il processore è ottimizzato per un uso specifico, non è specifico della lingua.
DeadMG

@DeadMG: altri casi hanno beneficiato, è vero. Ma fino a quando il C ++ non è diventato popolare, i progetti della CPU non sono stati influenzati . E questa era la domanda posta. Allo stesso modo, TMN ha un punto sui file di registro. L'Assemblea non aveva un concetto così chiaro di funzioni. Le funzioni, come oggi le capiamo comunemente, risalgono ad Algol 60, e quindi possiamo dire che Algol 60 ha influenzato la progettazione del file di registro della CPU.
Salmi

14

Il set di istruzioni Intel 8086 include una variante di "ret" che aggiunge un valore al puntatore dello stack dopo aver visualizzato l'indirizzo di ritorno. Ciò è utile per molte implementazioni Pascal in cui il chiamante di una funzione spingerà gli argomenti nello stack prima di effettuare una chiamata di funzione e li farà saltare in seguito. Se una routine accettasse, ad esempio, parametri di quattro byte, potrebbe finire con "RET 0004" per ripulire lo stack. In assenza di tale istruzione, una convenzione di chiamata del genere avrebbe probabilmente richiesto che il codice inserisse l'indirizzo di ritorno in un registro, aggiornasse il puntatore dello stack e quindi passasse a quel registro.

È interessante notare che la maggior parte del codice (comprese le routine del sistema operativo) sul Macintosh originale utilizzava la convenzione di chiamata Pascal nonostante la mancanza di istruzioni di facilitazione nel 68000. L'uso di questa convenzione di chiamata ha salvato 2-4 byte di codice in un tipico sito di chiamata, ma ha richiesto un extra 4-6 byte di codice nel sito di ritorno di ogni funzione che ha assunto parametri.


C'è anche una ENTERcontroparte in questo RET n...
Herby il

1
@herby: non credo ENTEResistesse nell'8086 originale; è arrivato con processori successivi. Ciò solleva un punto interessante, tuttavia: le modalità di indirizzamento basate su BP sono chiaramente progettate intorno all'uso di parametri sovrapposti e locali a cui si accede tramite il puntatore al frame. Trovo questa convenzione interessante in vari modi, specialmente considerando che (1) il codice del linguaggio assembly puro è più adatto all'uso di valori nei registri rispetto allo stack, ma (2) i vantaggi di [BP + nn] indirizzarsi su [SP + nn] gli indirizzi sono più significativi per i programmi in linguaggio assembly che accedono alle cose nello stack di ...
supercat

... per codice assembly scritto a mano. Un compilatore saprà generalmente, per ogni istruzione generata, come confrontare SP e BP; se SP è BP-8, ad esempio, non è davvero più facile per il compilatore indirizzare [BP + 12] di [SP + 20]. Se in una ricompilazione il compilatore deve aggiungere un altro PUSH / POP attorno a un blocco di codice, può regolare gli offset basati su SP in modo appropriato. D'altra parte, nell'assemblaggio scritto a mano, l'aggiunta di un PUSH / POP richiederebbe probabilmente di modificare il codice tra di loro. Quindi i puntatori di frame sono principalmente un vantaggio del codice combinato di alto livello / asm.
supercat

Forse la possibilità di riutilizzare il codice senza la sua ricompilazione è anche un punto marginale di usabilità per l'indirizzamento BP. E Dio sa se le istruzioni di indirizzamento BP non sono più veloci nei circuiti rispetto a quelle indirizzate a SP, poiché l'indirizzamento BP è una specie di standard ...
Herby

3
@herby: In realtà, sospetto che gran parte del motivo per cui i compilatori hanno generalmente usato i frame pointer ha molto a che fare con il debug. Per eseguire il debug di un programma che non utilizzava tale convenzione sarebbe necessario che il compilatore generasse - e il debugger utilizzasse - un file che elenca l'offset SP-BP per ogni istruzione. Tali metadati dettagliati sono comuni oggi (ed è una parte essenziale di ciò che rende pratiche le lingue raccolte con la spazzatura) ma la quantità di RAM richiesta sarebbe stata inaccettabile 30 anni fa.
supercat

10

Un esempio è MIPS, che ha sia adde adduper il trapping e l'ignoramento rispettivamente dell'overflow. (Anche sube subu.) Aveva bisogno del primo tipo di istruzione per linguaggi come Ada (penso - non ho mai usato Ada in realtà) che si occupano esplicitamente di overflow e il secondo tipo per linguaggi come C che ignorano gli overflow.

Se ricordo bene, la CPU effettiva ha alcuni circuiti aggiuntivi nell'ALU per tenere traccia degli overflow. Se l'unica lingua a cui la gente tenesse era C, non ne avrebbe bisogno.


Non sono sicuro se correlato, ma quelle istruzioni sono probabilmente utili anche in altre situazioni, come l'allocazione sicura della memoria, ad esempio se si stanno allocando nmemb*size+offsetbyte e è necessario assicurarsi che non si verifichi un overflow.
NikiC,

@NikC: Stavo pensando che le istruzioni addue subu(quelle che non controllano gli overflow) erano quelle aggiunte per rendere C felice. Certo, non lo so davvero - l'abbiamo trattato solo vagamente durante le lezioni e certamente non sono un esperto di architettura: P.
Tikhon Jelvis,

Oh sì, stavo pensando il contrario, scusa: /
NikiC

8

La serie 5000 di Burroughs è stata progettata per supportare in modo efficiente ALGOL e l'iAPX-432 di Intel è stata progettata per eseguire in modo efficiente Ada. Inmos Transputer aveva la sua lingua, Occam. Penso che il processore "Propeller" di Parallax sia stato progettato per essere programmato usando la sua variante di BASIC.

Non è un linguaggio, ma il set di istruzioni VAX-11 ha una singola istruzione per caricare un contesto di processo, che è stato progettato su richiesta del team di progettazione VMS. Non ricordo i dettagli, ma ISTR ha impiegato così tante istruzioni per implementare che ha messo un limite massimo al numero di processi che potevano programmare.


Cos'è che rende questi design particolarmente adatti? Ad esempio, di quale caratteristica dell'iAPX beneficia particolarmente Ada?
Gaius,

ISTR afferma che il target Ada di iAPX-432 stava più cercando di salvare un progetto fallito collegandolo a qualcosa con ancora grandi aspettative di ogni altra cosa.
Programmatore

@AProgrammer: sono abbastanza sicuro che iAPX-432 sia stato progettato fin dall'inizio per utilizzare Ada. Ricordo persino alcune voci secondo cui Intel non avrebbe pubblicato il set di istruzioni, per scoraggiare la programmazione del linguaggio assembly e costringere le persone a utilizzare Ada per tutto.
TMN

1
@TMN, il progetto 432 di Intel è iniziato nel 1975 e introdotto nel 1981 (Wikipedia). Ironman (requisiti finali per Ada), è stato pubblicato nel gennaio 1977 e il verde è stato scelto nel maggio 1979, modificato e il risultato finale è stato pubblicato come standard militare nel luglio 1980. Esiste un problema cronologico nel dichiarare che iAPX-432 è stato progettato da l'inizio dell'uso di Ada. (È un processore tardivo e tipico "colmare il divario semantico" con i soliti inconvenienti in un momento in cui le alternative iniziarono a cercare; commercializzarlo come processore Ada era un tentativo per salvare un progetto fallito - ISTR che nessuno tranne Intel lo usava )
Approgrammatore

1
@AProgrammer: Hmmm, sembra che tu abbia ragione. Mi sono imbattuto in questo documento dall'architetto capo del 432 e nel sommario dice "Questa stretta corrispondenza di architettura e linguaggio non si è verificata perché il 432 è stato progettato per eseguire Ada, non lo è stato". Dovrò scavare il mio vecchio libro 432 e vedere cosa dice.
TMN

8

Una cosa che nessuno sembra aver menzionato finora è che i progressi nell'ottimizzazione del compilatore (dove il linguaggio di base è in gran parte irrilevante) ha spinto il passaggio dai set di istruzioni CISC (che erano in gran parte progettati per essere codificati dagli umani) a set di istruzioni RISC (che erano in gran parte progettato per essere codificato dai compilatori.)


5

La famiglia Motorola 68000 ha introdotto alcuni modi di indirizzamento automatico che hanno reso la copia dei dati attraverso la cpu molto efficiente e compatta.

[Esempio aggiornato]

questo era un codice c ++ che influenzava l'assemblatore 68000

while(someCondition)
    destination[destinationOffset++] = source[sourceOffset++]

implementato in assemblatore convenzionale (pseudocodice, ho dimenticato i comandi dell'assemblatore 68000)

adressRegister1 = source
adressRegister2 = destination
while(someCondition) {
    move akku,(adressRegister1)
    move (adressRegister2), akku
    increment(adressRegister1, 1)
    increment(adressRegister2, 1)
}

con la nuova modalità indirizzo è diventato qualcosa di simile

adressRegister1 = source
adressRegister2 = destination
while(someCondition) {
    move akku,(adressRegister1++)
    move (adressRegister2++), akku
}

solo due istruzioni per loop anziché 4.


1
In che modo ciò è stato influenzato dalle convenzioni di una determinata lingua?
Gaius,

vedi esempio aggiornato
k3b

Ah, mi ricorda l'ottimizzazione del loop DBxx nel 68010.
Gaius

7
In realtà, penso che tu abbia questo al contrario. L'indirizzamento automatico del frammento [in | de] faceva parte del set di istruzioni PDP-11, che probabilmente ha influenzato la progettazione di C.
TMN,

5

Il mainframe della serie Z di IBM, è il discendente dell'IBM 360 dagli anni '60.

Ci sono state diverse istruzioni che sono state messe lì appositamente per accelerare i programmi COBOL e Fortran. L'esempio classico è il BXLE- "Branch on Index Low or Equal" che è la maggior parte di un forciclo Fortran o un COBOL PERFORM VARYING x from 1 by 1 until x > nincapsulato in una singola istruzione.

Esiste anche un'intera famiglia di istruzioni decimali impaccate per supportare l'aritmetica decimale a virgola fissa comune nei programmi COBOL.


Penso che intendi discendente .
Clockwork-Muse

@ X-Zero - oops! Mattina presto, non abbastanza caffiene nel sistema ecc .......
James Anderson

1
Più interessante è l'istruzione di ripetizione del blocco del DSP 32050 DSP. Il suo operando è l'indirizzo dell'istruzione che segue l'ultimo nel ciclo; il caricamento di un registro di conteggio dei loop e quindi l'esecuzione dell'istruzione di ripetizione del blocco causano la ripetizione delle istruzioni fino al target (ma non incluso) per il numero di volte specificato. Ricorda fortemente un DOciclo FORTRAN .
supercat

@supercat Ogni DSP degno di questo nome include tre funzioni: loop zero-overhead, singola istruzione si moltiplica-accumula e una modalità di indirizzamento bit-reverse di qualche tipo. Quasi tutti gli algoritmi DSP conosciuti da Man utilizzano i loop. I due algoritmi più comuni sono il filtro FIR, che è un ciclo attorno a un moltiplicarsi, e FFT, per cui l'indirizzamento a bit invertiti è fondamentale. Molti DSP includono un'operazione a farfalla FFT a una istruzione radix-2 o una doppia moltiplicazione / aggiunta che può essere utilizzata per creare una farfalla a una istruzione.
John R. Strohm,

@ JohnR.Strohm: ogni DSP che ho visto include una ripetizione moltiplica-accumula, ma non tutti includono loop a zero overhead più generalizzati. In realtà, non sono del tutto sicuro del perché tali loop debbano essere considerati solo una funzionalità "DSP", dal momento che sarebbero utili anche in molti codici di "processori convenzionali".
supercat

3

Le prime CPU Intel avevano le seguenti funzionalità, molte delle quali ormai obsolete in modalità 64 bit:

  • ENTER, LEAVE e RET nn istruzioni [i primi manuali spiegavano esplicitamente quelli introdotti per i linguaggi strutturati a blocchi, ad esempio Pascal, che supporta le procedure nidificate]
  • istruzioni per accelerare l'aritmetica BCD (AAA, AAM, ecc.); anche supporto BCD in x87
  • Istruzioni JCXZ e LOOP per l'implementazione di loop contati
  • INTO, per generare una trappola sull'overflow aritmetico (ad es. In Ada)
  • XLAT per ricerche da tavolo
  • BOUND per il controllo dei limiti dell'array

Il flag di segno, che si trova nel registro di stato di molte CPU, esiste per eseguire facilmente l'aritmetica con segno E senza segno.

Il set di istruzioni SSE 4.1 introduce le istruzioni per l'elaborazione delle stringhe, sia conteggio che a terminazione zero (PCMPESTR, ecc.)

Inoltre, potrei immaginare che una serie di funzionalità a livello di sistema siano state progettate per supportare la sicurezza del codice compilato (controllo del limite di segmenti, porte di chiamata con copia dei parametri, ecc.)


3

Alcuni processori ARM, principalmente quelli nei dispositivi mobili, includono (d) l'estensione Jazelle, che è un interprete JVM hardware; interpreta direttamente il bytecode Java. JVM consapevole di Jazelle può utilizzare l'hardware per accelerare l'esecuzione ed eliminare gran parte di JIT, ma il fallback al software VM è ancora garantito se il bytecode non può essere interpretato su chip.

I processori con tale unità includono l'istruzione BXJ, che mette il processore in una speciale "modalità Jazelle", o se l'attivazione dell'unità non è riuscita, viene semplicemente interpretata come normale istruzione di diramazione. L'unità riutilizza i registri ARM per mantenere lo stato JVM.

Il successore della tecnologia Jazelle è ThumbEE


2

Per quanto ne so, questo era più comune in passato.

C'è una sessione di domande in cui James Gosling ha affermato che c'erano persone che cercavano di creare hardware in grado di gestire meglio il bytecode JVM, ma poi queste persone avrebbero scoperto un modo per farlo con il comune intel x86 "generico" (forse compilando il bytecode in qualche modo intelligente).

Ha detto che esiste un vantaggio nell'uso del chip generico generico (come quello di Intel) perché ha una grande società che lancia ingenti somme di denaro sul prodotto.

Vale la pena dare un'occhiata al video. Ne parla al minuto 19 o 20.



2

La CPU Intel iAPX è stata progettata specificamente per i linguaggi OO. Tuttavia, non ha funzionato del tutto.

L' iAPX 432 ( intel Advanced Processor architecture ) è stato il primo design a microprocessore a 32 bit di Intel, introdotto nel 1981 come set di tre circuiti integrati. Doveva essere il principale progetto di Intel per gli anni '80, implementando molte funzionalità avanzate di multitasking e gestione della memoria. Il design è stato quindi chiamato Micromainframe ...

L'iAPX 432 è stato "progettato per essere programmato interamente in linguaggi di alto livello" , con Ada come principale e supportava la programmazione orientata agli oggetti e la garbage collection direttamente in hardware e microcodice . Il supporto diretto per varie strutture di dati era inoltre destinato a consentire l'implementazione dei moderni sistemi operativi per iAPX 432 utilizzando un codice di programma molto inferiore rispetto ai normali processori. Queste proprietà e caratteristiche hanno portato a una progettazione hardware e microcodice molto più complessa rispetto alla maggior parte dei processori dell'epoca, in particolare i microprocessori.

Utilizzando la tecnologia dei semiconduttori del suo tempo, gli ingegneri di Intel non sono stati in grado di tradurre il progetto in una prima implementazione molto efficiente. Insieme alla mancanza di ottimizzazione in un compilatore Ada prematuro, ciò ha contribuito a sistemi di computer piuttosto lenti ma costosi, eseguendo benchmark tipici a circa 1/4 della velocità del nuovo chip 80286 alla stessa frequenza di clock (all'inizio del 1982).

Questo gap prestazionale iniziale con il profilo piuttosto basso e la linea 8086 a basso prezzo era probabilmente il motivo principale per cui il piano di Intel di sostituire quest'ultimo (in seguito noto come x86) con l'iAPX 432 non è riuscito. Sebbene gli ingegneri abbiano visto modi per migliorare un design di nuova generazione, l' architettura iAPX 432 Capability ora aveva iniziato a essere considerata più come un overhead di implementazione piuttosto che come il supporto semplificante che doveva essere.

Il progetto iAPX 432 è stato un fallimento commerciale per Intel ...


Leggendo il documento, sembra che molti aspetti del design possano essere utili in quadri orientati agli oggetti come quelli popolari oggi. Un'architettura che utilizzava una combinazione di un ID oggetto a 32 bit e un offset a 32 bit poteva in molti casi offrire migliori prestazioni di memorizzazione nella cache rispetto a quella in cui gli ID oggetto erano tutti a 64 bit (nella maggior parte dei casi, un'applicazione che utilizza miliardi di oggetti essere meglio serviti invece di avere più, più grandi; uno che memorizzerebbe miliardi di byte in un oggetto sarebbe meglio servire suddividendolo in oggetti più piccoli.
supercat

1

Il 68000 aveva MOVEM che era più adatto a spingere più registri nello stack in un'unica istruzione, che è ciò che molte lingue si aspettavano.

Se hai visto MOVEM (MOVE Multiple) che precede JSR (Jump SubRoutine) in tutto il codice, allora generalmente sapevi che hai a che fare con il codice C rispettato.

MOVEM ha consentito l'incremento automatico del registro di destinazione, consentendo a ciascun utilizzo di continuare a impilare sulla destinazione o di rimuoverlo dallo stack in caso di decremento automatico.

http://68k.hax.com/MOVEM


1

L'architettura AVR di Atmel è interamente progettata da zero per essere adatta per la programmazione in C. Ad esempio, questa nota applicativa elabora ulteriormente.

L'IMO è strettamente correlato con l'eccellente risposta di rockets4kids , con i primi PIC16 sviluppati per la programmazione diretta dell'assemblatore (40 istruzioni in totale), con le famiglie successive destinate a C.


1

Quando è stato progettato il coprocessore numerico 8087, era abbastanza comune per le lingue eseguire tutte le operazioni matematiche in virgola mobile utilizzando il tipo di massima precisione e arrotondare il risultato solo per ridurne la precisione quando lo si assegna a una variabile di precisione inferiore. Nello standard C originale, ad esempio, la sequenza:

float a = 16777216, b = 0.125, c = -16777216;
float d = a+b+c;

favorirebbe ae bad double, aggiungerli, di promuovere ca double, inserirlo, e quindi memorizzare il risultato arrotondato a float. Anche se in molti casi sarebbe stato più veloce per un compilatore generare codice che avrebbe eseguito operazioni direttamente sul tipo float, era più semplice disporre di una serie di routine in virgola mobile che avrebbero funzionato solo sul tipo double, insieme alle routine da convertire in / da float, piuttosto che avere serie separate di routine per gestire le operazioni su floate double. L'8087 fu progettato attorno a quell'approccio all'aritmetica, eseguendo tutte le operazioni aritmetiche usando un tipo a virgola mobile a 80 bit [80 bit fu probabilmente scelto perché:

  1. Su molti processori a 16 e 32 bit, è più veloce lavorare con una mantissa a 64 bit e un esponente separato rispetto a lavorare con un valore che divide un byte tra la mantissa e l'esponente.

  2. È molto difficile eseguire calcoli che siano accurati con la massima precisione dei tipi numerici che si stanno utilizzando; se si sta tentando, ad esempio, di calcolare qualcosa come log10 (x), è più facile e veloce calcolare un risultato che è accurato entro 100 ppm di un tipo a 80 bit piuttosto che calcolare un risultato che è preciso entro 1 ppm di un 64 bit digitare e arrotondare il primo risultato alla precisione a 64 bit produrrà un valore a 64 bit che è più accurato del secondo.

Sfortunatamente, le versioni future della lingua hanno cambiato la semantica di come dovrebbero funzionare i tipi a virgola mobile; mentre la semantica 8087 sarebbe stata molto piacevole se le lingue li avessero supportati in modo coerente, se le funzioni f1 (), f2 (), ecc. restituiscono il tipo float, molti autori di compilatori si prenderebbero il caso di creare long doubleun alias per il doppio tipo a 64 bit piuttosto che il tipo a 80 bit del compilatore (e non fornisce altri mezzi per creare variabili a 80 bit) e per valutare arbitrariamente qualcosa come:

double f = f1()*f2() - f3()*f4();

in uno dei seguenti modi:

double f = (float)(f1()*f2()) - (extended_double)f3()*f4();
double f = (extended_double)f1()*f2() - (float)(f3()*f4());
double f = (float)(f1()*f2()) - (float)(f3()*f4());
double f = (extended_double)f1()*f2() - (extended_double)f3()*f4();

Si noti che se f3 e f4 restituiscono gli stessi valori di f1 e f2, rispettivamente, l'espressione originale dovrebbe restituire chiaramente zero, ma molte di queste ultime espressioni potrebbero non esserlo. Ciò ha portato le persone a condannare la "precisione in più" dell'8087 anche se l'ultima formulazione sarebbe generalmente superiore alla terza e - con un codice che utilizzava il doppio tipo esteso in modo appropriato - raramente sarebbe inferiore.

Negli anni successivi, Intel ha risposto alla tendenza del linguaggio (sfortunato IMHO) a forzare i risultati intermedi da arrotondare alla precisione degli operandi progettando i loro processori successivi in ​​modo da favorire quel comportamento, a scapito del codice che trarrebbe vantaggio dall'uso di precisione sui calcoli intermedi.


Nota che hai già una risposta ( sopra ) in questo post. Sono risposte che potrebbero / dovrebbero essere fuse in una sola?

@MichaelT: Io non la penso così - una riguarda la progettazione dello stack e l'altra riguarda la semantica in virgola mobile.
supercat

Solo per essere sicuro. Personalmente, credo che sarebbe possibile dare una risposta più forte (usando le intestazioni per separare le sezioni), ma questo è il mio punto di vista. Potresti voler usare ancora le intestazioni per identificare chiaramente in alto ciò a cui ciascuna parte di risposta si rivolge ( ## How the stack changed the processore ## How floating point changed the processor) in modo che le persone possano entrare nella propria mentalità quando la leggono e hanno meno probabilità di pensare che eri assente nel rispondere o ripubblicare il stesse risposte (simili).

@MichaelT: Le due risposte sono sufficientemente disgiunte da ritenere che debbano essere votate separatamente. Sebbene l'80486 abbia assorbito le funzioni precedentemente svolte dall'8087/80287/80387, l'8086 e l'8087 sono stati progettati come chip separati con architetture quasi indipendenti. Sebbene entrambi eseguissero il codice da un flusso di istruzioni comune, che è stato gestito facendo in modo che l'8086 trattasse determinate sequenze di byte come richieste per generare richieste di lettura / scrittura di indirizzi ignorando il bus dati e facendo in modo che l'8087 ignorasse tutto ciò che stava succedendo.
supercat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.