2008-09-24 7 views
6

Ho deciso di insegnarmi il linguaggio dell'assemblaggio.Perché non è possibile modificare il valore di un registro segmenti? (MASM)

Ho capito che il mio programma non verrà compilato se tento di cambiare il valore di qualsiasi registro di segmento.

Ogni articolo che ho trovato dice che posso davvero cambiare il valore di almeno 4 registri di segmenti, quindi cosa dà?

Sono davvero interessato solo al motivo per cui a questo punto, non ho alcun reale scopo nel cambiare questi indirizzi.

+2

Qual è l'errore? – Blorgbeard

+0

Sotto un SO o indipendente? 16 modalità protetta reale o 32 bit? Quale codice non è stato compilato? Esempio a 16 bit minimo con effetti osservabili: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d4aae6183b98564819107b44a77641979c35d2c3/segment_registers.S –

risposta

8

Hai detto che erano interessati a questo il motivo per cui, in modo da:

in modalità reale, un segmento è una "finestra" 64K di memoria fisica e queste finestre sono distanziate di 16 byte. In modalità protetta, un segmento è una finestra per la memoria fisica o virtuale, le cui dimensioni e posizione sono determinate dal sistema operativo e ha molte altre proprietà, tra cui il livello di privilegi che un processo deve avere per accedervi.

Da qui in poi, tutto ciò che dico si riferisce alla modalità protetta.

C'è una tabella in memoria chiamata tabella dei descrittori globali (GDT), che è dove vengono conservate le informazioni su queste dimensioni e posizioni delle finestre e altre proprietà. Potrebbero esserci anche tabelle di descrittori locali su una base per processo e funzionano in modo simile, quindi mi concentrerò solo sul GDT.

Il valore caricato in un registro segmenti è noto come selettore segmento . È un indice nel GDT o nel LDT, con un po 'di informazioni di sicurezza extra. Naturalmente se un programma tenta di caricare un descrittore che è fuori dai limiti del GDT, si verifica un'eccezione. Inoltre, se il processo non ha privilegi sufficienti per accedere al segmento, o qualcos'altro non è valido, si verifica un'eccezione.

Quando si verifica un'eccezione, il kernel lo gestisce. Questo tipo di eccezione verrebbe probabilmente classificato come un errore di segmentazione. Quindi il sistema operativo uccide il tuo programma.

C'è un'ultima avvertenza: nel set di istruzioni x86, non è possibile caricare i valori immediati nei registri di segmento. È necessario utilizzare un registro intermedio o un operando di memoria o POP nel registro dei segmenti.

 
MOV DS, 160 ;INVALID - won't assemble 

MOV AX, 160 ;VALID - assembles, but will probably result in an 
MOV DS, AX ;exception, and thus the death of your program 

Penso che si debba sottolineare che l'architettura consente cumuli di segmenti. Ma per quanto ne so, quando si tratta di principali sistemi operativi x86, registri di segmento servono solo un paio di scopi:

  • meccanismi di sicurezza, come il mantenimento processi dello spazio utente di danneggiare l'altro o il sistema operativo
  • affrontare con più/processori multi-core
  • Memorizzazione locale dei thread: come ottimizzazione, alcuni sistemi operativi (incluso Linux e Windows) utilizzano i registri di segmento per lo storage locale thread (TLS). Poiché i thread condividono lo stesso spazio di indirizzamento, è difficile per un thread "sapere" dove si trova la sua regione TLS senza utilizzare una chiamata di sistema o sprecare un registro ... ma poiché i registri di segmento sono praticamente inutili, non c'è nulla di male nello "sprecare" per il veloce TLS. Si noti che durante l'impostazione, un sistema operativo può saltare i registri dei segmenti e scrivere direttamente nei registri della cache dei descrittori, che sono registri "nascosti" usati per memorizzare nella cache le ricerche GDT/LDT innescate dai riferimenti ai registri dei segmenti, nel qual caso se si prova per leggere dai registri dei segmenti non lo vedrai.

Oltre a un segmento per thread per TLS, vengono utilizzati solo pochi segmenti (moltiplicato il numero di processori) e solo dal sistema operativo. I programmi applicativi possono completamente ignorare i registri di segmento.

Ciò è dovuto al design del sistema operativo, non a eventuali limitazioni tecniche. Ci possono essere sistemi operativi incorporati che richiedono programmi di spazio utente per lavorare con i registri di segmento, anche se non ne conosco nessuno.

+1

Sei sicuro di non poter caricare un registro segmenti con un valore immediato su x86? Sto guardando il Manuale per gli sviluppatori del software Intel Architectures (325462, volumi combinati) e a pagina 1002 indica un'istruzione MOV con un codice operativo di 0x8E, che apparentemente sposta un 'r/m16' in un registro dei segmenti. – amn

2

Stai scrivendo gli eseguibili di Windows?

Nella modalità protetta (Win32), i registri di segmento non vengono più utilizzati.

Reference:

modello di memoria è anche drasticamente diverso dai vecchi giorni del mondo a 16 bit. Sotto Win32, non è necessario che lo riguardi il modello di memoria o il segmento ! C'è solo un modello di memoria : modello di memoria piatta. Non ci sono più segmenti da 64K. La memoria è un ampio spazio continuo di 4 GB. Ciò significa anche che non hai per giocare con i registri di segmento. È possibile utilizzare qualsiasi registro di segmento su in qualsiasi punto dello spazio di memoria. Questo è un grande aiuto per i programmatori. Questo è ciò che rende il montaggio Win32 programmazione facile come C.

+3

Questo è semplicemente * sbagliato *. Diversi registri di segmenti vengono utilizzati per l'archiviazione locale dei thread e la gestione delle eccezioni. –

+0

I (ovviamente?) Significava "usato per il loro scopo originale, dai programmi di spazio utente". OP si riferiva alla documentazione obsoleta. – Blorgbeard

Problemi correlati