Domanda

modello di memoria di C, con il suo uso di aritmetica dei puntatori e tutti, sembra di modellare lo spazio di indirizzi piatta. i computer a 16 bit utilizzati di accesso alla memoria segmentata. Come hanno fatto i compilatori a 16 bit C affrontare questo problema e simulare uno spazio di indirizzamento piatta dal punto di vista del programmatore C? Per esempio, più o meno ciò che il montaggio istruzioni in linguaggio sarebbe il seguente codice di compilazione per su un 8086?

long arr[65536];  // Assume 32 bit longs.
long i;
for(i = 0; i < 65536; i++) {
    arr[i] = i;
}
È stato utile?

Soluzione

  

Come ha fatto compilatori a 16 bit C trattano   questo problema e simulare un indirizzo piatta   spazio dal punto di vista del C   programmatore?

Non lo fecero. Invece, hanno fatto la segmentazione visibile al programmatore C, estendendo il linguaggio avendo più tipi di puntatori: near, far e huge . Un puntatore near stato un offset solo, mentre far e huge puntatori erano un segmento combinato e offset. C'era un'opzione del compilatore per impostare modello di memoria del , che ha determinato se il tipo di puntatore predefinito era vicino o lontano.

Codice In Windows, ancora oggi, vedrete spesso typedef come LPCSTR (per const char*). La "LP" è un residuo dei giorni a 16 bit; è l'acronimo di "Long (lontano) Pointer".

Altri suggerimenti

modello di memoria C non lo fa in alcun modo implica spazio di indirizzamento piatto. Non si è mai fatto. Infatti, specifica C linguaggio è specificamente progettato per consentire spazi di indirizzi non piane.

Nella maggior attuazione banale con spazio di indirizzamento segmentato, la dimensione del più grande oggetto continuo sarebbe limitata dalla dimensione del segmento (65536 byte su una piattaforma a 16 bit). Ciò significa che size_t in tale realizzazione sarebbe a 16 bit, e che il codice semplicemente non sarebbe compilare, dal momento che si sta tentando di dichiarare un oggetto che ha dimensioni maggiori rispetto al massimo consentito.

Una più complessa implementazione sosterrebbe cosiddetto enorme modello di memoria. Vedete, non c'è davvero nessun problema affrontare blocchi di memoria continui di qualsiasi dimensioni su un modello di memoria segmentata, si richiede solo alcuni sforzi supplementari in aritmetica puntatore. Così, all'interno del modello di memoria enorme, l'attuazione renderebbe questi sforzi supplementari, il che renderebbe il codice un po 'più lento, ma allo stesso tempo permetterebbe di indirizzamento oggetti di qualsiasi dimensione. Così, il vostro codice sarebbe compilare perfettamente bene.

Gli ambienti veri a 16 bit utilizzano 16 bit puntatori che raggiungono qualsiasi indirizzo. Esempi includono il PDP-11, 6800 famiglia (6802, 6809, 68HC11), e il 8085. Questo è un ambiente pulito ed efficiente, proprio come una semplice architettura a 32-bit.

La 80x86 famiglia costretta su di noi un ibrido spazio di indirizzi / 20-bit a 16 bit nella cosiddetta "modalità reale" -la nativa 8086 spazio di indirizzamento. Il meccanismo di solito a che fare con questo è stato valorizzare i tipi di puntatori in due tipi fondamentali, near (puntatore a 16 bit) e far (puntatore a 32 bit). L'impostazione predefinita per codice e dati puntatori può essere impostato in massa da un "modello di memoria":. tiny, small, compact, medium, far, e huge (alcuni compilatori non supportano tutti i modelli)

Il modello di memoria tiny è utile per piccoli programmi in cui l'intero spazio (codice + dati + stack) è inferiore a 64 KB. Tutti i puntatori sono (per default) 16 bit o near; un puntatore è implicitamente associato ad un valore di segmento per l'intero programma.

Il modello small presuppone che i dati + stack è inferiore a 64 KB e nello stesso segmento; il segmento di codice contiene solo codice, così può avere fino a 64K pure, per un ingombro memoria massima di 128K. puntatori di codice sono near e implicitamente associato con CS (il segmento di codice). puntatori di dati sono anche near e associati con DS (il segmento di dati).

Il modello medium ha fino a 64 KB di dati + pila (come la piccola), ma può avere qualsiasi quantità di codice. puntatori di dati sono a 16 bit e sono implicitamente legati al segmento di dati. puntatori di codice sono 32 puntatori po far e hanno un valore del segmento a seconda di come il linker ha istituito i gruppi di codice (una schifezza contabilità seccatura).

Il modello compact è il complemento di media: meno di 64 KB di codice, ma qualsiasi quantità di dati. puntatori di dati sono far e codice puntatori sono near.

In large o modello huge, il sottotipo di default di puntatori sono a 32 bit o far. La differenza principale è che i puntatori enormi sono sempre normalizzati automaticamente in modo che li incrementando evita problemi con 64K wrap around. Vedere questo .

In DOS a 16 bit, non mi ricordo di essere stato in grado di farlo. Si potrebbe avere più cose che erano ciascuno 64K (byte) (in quanto il segmento può essere regolata e l'offset azzerato), ma non ricordo se si potesse attraversare il confine con un singolo array. Lo spazio di memoria piatta dove si poteva volenti o nolenti allocare tutto quello che volevamo e la portata profondo come ti è piaciuto in un array non ha ancora accadere finché non abbiamo potuto compilare 32 programmi po 'DOS (su 386 o 486 processori). Forse altri sistemi operativi e compilatori diversi da Microsoft e Borland potrebbe generare matrici piane superiori 64Kbytes. Win16 Non mi ricordo che la libertà fino a quando ha colpito Win32, forse la mia memoria è sempre arrugginito ... Sei stato fortunato o ricco di avere un megabyte di memoria in ogni caso, una macchina 256Kbyte o 512 Kbyte non era inaudito. L'unità floppy avuto una frazione di meg a 1,44 meg alla fine, e il disco rigido se uno ha avuto una dozzina di alcuni mega, quindi basta non ha ancora calcolare cosa che di grandi dimensioni che spesso.

Mi ricordo la sfida particolare che avevo conoscere DNS quando è possibile scaricare l'intero database DNS di tutti i nomi a dominio registrati sul pianeta, infatti si doveva mettere il proprio server DNS che è stato quasi richiesto al momento di avere un sito web. Questo file è stato 35megabytes, e il mio hard disk è stato 100megabytes, oltre a DOS e Windows da masticare un po 'di quello. Probabilmente ha avuto 1 o 2 mega di memoria, potrebbe essere stato in grado di fare programmi DOS a 32 bit al momento. Parte se è stato me che vogliono analizzare il file ASCII che ho fatto in più passaggi, ma ogni passaggio l'uscita doveva andare a un altro file, e ho dovuto eliminare il file prima di avere spazio sul disco per il file successivo. Due controllori di disco su una scheda madre standard, una per il disco rigido e una per l'unità CD-ROM, di nuovo qui questa roba non era a buon mercato, non ci sono stati un sacco di slot ISA di ricambio se si poteva permettersi un'altra carta disco e controller del disco rigido.

C'era anche il problema della lettura 64Kbytes con C è stato superato fread il numero di byte che si voleva leggere in un int a 16 bit, il che significava 0 a 65535 non 65536 byte, e le prestazioni è sceso drasticamente se non ha ancora letto in anche di dimensioni settori, in modo che avete appena letto 32kBytes alla volta per massimizzare le prestazioni, 64k non ha ancora venire fino a buona parte dei giorni dos32 quando si erano finalmente convinto che il valore passato a fread era ormai un numero a 32 bit e sollecito compilatore andando a tagliare fuori la superiore 16 bit e utilizzare solo i 16 bit inferiori (che è accaduto spesso se si è utilizzato compilatori abbastanza / versioni). Attualmente stiamo soffrendo problemi simili in 32 bit a 64 di transizione come abbiamo fatto con il passaggio da 16 a 32 bit. Ciò che è più interessante è il codice dalla gente come me che ha imparato che va da 16 a 32 bit int cambiato dimensione, ma unsigned char e unsigned long non ha, in modo da adattato e raramente int utilizzato in modo che i programmi sarebbero compilare e lavorare per sia a 16 e 32 bit. (Il codice da gente da quel tipo di generazione si distingue per altre persone che hanno vissuto anche attraverso di essa e utilizzate lo stesso trucco). Ma per il 32-64 di transizione è il contrario e il codice non refactoring a dichiarazioni di tipo utilizzo uint32 stanno soffrendo.

La risposta di Reading wallyk che appena arrivato, l'enorme cosa puntatore che avvolto intorno fa suonare un campanello, pur non essendo sempre in grado di compilare per enorme. piccolo era il modello di memoria piatto ci sono confortevoli con l'oggi, e come con oggi è stata facile, perché non dovessi preoccupare di segmenti. Quindi è stata una desiderabile per compilare per le piccole quando si poteva. Ancora non dovessi un sacco di memoria o un disco floppy o lo spazio in modo da appena didnt normalmente a che fare con dati che di grandi dimensioni.

E d'accordo con un'altra risposta, la cosa di offset segmento è stato 8088/8086 Intel. Il mondo intero non era ancora dominato da Intel, quindi c'erano altre piattaforme che appena avuto uno spazio di memoria piatta, o utilizzati altri trucchi forse in hardware (al di fuori del processore) per risolvere il problem. A causa del segmento / intel compensato è stato in grado di guidare la cosa a 16 bit più a lungo di quello che probabilmente dovrebbe avere. Segmento / Offset aveva un po 'freddo e le cose interessanti che si possono fare con esso, ma era come il dolore di un tanto quanto qualsiasi altra cosa. Si sia semplificati di tua vita e vissuto in uno spazio di memoria flat o si costantemente preoccupati circa i limiti di segmento.

Davvero pinning giù la dimensione indirizzo sul vecchio x86 è una specie di complicato. Si potrebbe dire che la sua 16 bit, perché l'aritmetica è possibile eseguire su un indirizzo deve inserirsi in un registro a 16 bit. Si potrebbe anche dire che è a 32 bit, perché gli indirizzi effettivi sono calcolate rispetto un registro di uso generale a 16 bit e 16 bit registro di segmento (tutti i 32 bit sono significativi). Si potrebbe anche solo dire che è a 20 bit, perché i registri di segmento vengono spostate 4 bit a sinistra e ha aggiunto ai registri gp per l'indirizzamento hardware.

E 'in realtà non importa più di tanto che uno di questi si è scelto, perché sono tutte approssimazioni quasi uguali del c macchina astratta. Alcuni compilatori consentono di scegliere un modello di memoria si sta utilizzando per la compilazione, mentre altri solo supporre 32 indirizzi bit e quindi verificare attentamente che le operazioni che può traboccare 16 bit emettono istruzioni che maniglia questo caso in modo corretto.

questa voce di Wikipedia . A proposito di puntatori. In sostanza, la sua possibile indicare un segmento e un offset, rendendo possibile per passare a un altro segmento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top