Sistemi Operativi Introduzione a IA-32 Lez. 7 A.A. 2006/2007 1 Corso: Sistemi Operativi © Danilo Bruschi I processori 80x86 • • • • • • • • • • 8088, 8086: processori a16 bit, real-mode 80286: 16-bit con protected mode 80386: 32-bit registers, 32-bit protected mode 80486/Pentium/Pentium Pro: Adds few features, speed-up Pentium MMX: Introduces the multimedia extensions (MMX) Pentium II: Pentium Pro with MMX instructions Pentium III: Speed-up, introduces the Streaming SIMD Extensions (SSE) Pentium 4: Introduces the NetBurst architecture Xeon: Introduces Hyper-Threading A.A. 2006/2007 2 Corso: Sistemi Operativi © Danilo Bruschi Modalità CPU • Un processore IA-32 opera con tre diverse modalità operative che determinano le istruzioni e le caratteristiche accessibili: • Protected mode — lo stato This mode is the native state of the processor. Among the capabilities of protected mode is the ability to directly execute “real-address mode” 8086 software in a protected, multi-tasking environment. • Real-address mode — This mode implements the programming environment of the Intel 8086 processor with extensions • System management mode (SMM) — This mode provides an operating system or executive with a transparent mechanism for implementing platform-specific functions such as power management and system security. The processor enters SMM when the external SMM interrupt pin (SMI#) is activated A.A. 2006/2007 3 Corso: Sistemi Operativi © Danilo Bruschi Basic Execution environment A.A. 2006/2007 4 Corso: Sistemi Operativi © Danilo Bruschi Basic Program Execution Register • Il processore possiede 16 registri utilizzabili, che possono essere così raggruppati • General-purpose registers: si tratta di 8 registri che possono essere usati per memorizzare operandi di istruzioni e indirizzi • Segment registers: sei registri che contengono i selettori di segmento, per selezionare dati e programmi in memoria • EFLAGS (program status and control) register: un registro che contiene informazioni sullo stato del programma in esecuzione e consente un limitato controllo sull’operato del processore • EIP (instruction pointer) register: contiene l’indirizzo (un puntatore di 32-bit) alla prossima istruzione da eseguire A.A. 2006/2007 5 Corso: Sistemi Operativi © Danilo Bruschi Memoria • La memoria indirizzata dal processore attraverso il bus è la memoria fisica • Organizzata come una sequenza di byte di 8-bit. Ad ogni byte è assegnato un indirizzo unico • Un indirizzo fisico è un numero compreso tra 0 e 0xFFFFFFFFF ( 236 – 1) • Segmented memory model : la memoria è presentata ad un programma applicativo come un insieme di blocchi di memoria indipendenti. Le componenti di codice, dati, e stacks che compongono un processo sono contenute in segmenti separati. Per accedere ad un byte contenuto in un segemento un programma deve generare un indirizzo logico A.A. 2006/2007 6 Corso: Sistemi Operativi © Danilo Bruschi Formato indirizzi A.A. 2006/2007 7 Corso: Sistemi Operativi © Danilo Bruschi Segment Register A.A. 2006/2007 8 Corso: Sistemi Operativi © Danilo Bruschi A.A. 2006/2007 9 Corso: Sistemi Operativi © Danilo Bruschi Segment register • Ciascun segment register è associato ad uno dei tre tipi di dati memorizzabili: codice, dati, o stack. • CS contiene il selettore per il codice • il processore esegue le istruzioni dal segmento il cui indirizzo logico è contenuto nel registro CS e nel registro EIP • Il registro CS non può essere manipolato dalle applicazioni • Il registro SS contiene il selettore per l’area di stack associata al processo in esecuzione. Tutte le istruzioni che operano sullo stack (push, pop) fanno riferimento al registro SS per individuare lo stack su cui operare A.A. 2006/2007 10 Corso: Sistemi Operativi © Danilo Bruschi Registri • • • • • • • • EAX — Accumulatore per risultati e operandi EBX — indirizzi nell’area dati ECX — Contatore per operazioni su stringhe e cicli EDX — I/O pointer ESI — indirizzi nell’area dati; e indirizzi per operazioni su stringhe EDI — Pointer a dati nell’area puntata dal registro ES; puntatore per operazioni su stringhe ESP — Stack pointer EBP — Pointer ai dati presenti sullo stack A.A. 2006/2007 11 Corso: Sistemi Operativi © Danilo Bruschi EFLAGS A.A. 2006/2007 12 Corso: Sistemi Operativi © Danilo Bruschi EIP • Contiene l’offset rispetto al segmento codice corrente della prossima istruzione da eseguire, viene aggiornato automaticamente dopo l’esecuzione di ogni istruzione o per eseguire istruzioni come JMP, Jcc, CALL, RET, e IRET • Il registro EIP non può essere acceduto direttamente dal software; il suo valore è implicitamente dall e istruzioni per il controllo del flusso d’esecuzione del programma (JMP, Jcc, CALL, RET), interrupt, e eccezioni A.A. 2006/2007 13 Corso: Sistemi Operativi © Danilo Bruschi x86 Assembly Language • (Slightly) higher-level language than machine language • Program is made of: • directives: commands for the assembler • data identifies a section with variables • instructions: actual operations • jmp 8048f3f • Two possible syntaxes, with different ordering of the operands! • AT&T syntax (objdump, GNU Assembler) • DOS/Intel syntax (Microsoft Assembler, Nasm) A.A. 2006/2007 14 Corso: Sistemi Operativi © Danilo Bruschi Minix assembly language • Un programma è costituito da 4 sezioni: • Code section (.sect .text): contiene le istruzioni • Read only data section (.sect .rom): sezione dedicata ai dati non modificabili • Read and writetable data section (.sect .data): sezione dati • Global read and writetable data section (.sect .bss): sezione destinata a contenere le variabili globali. Il valore di queste variabili è inizializzato a zero. Un valore diverso da zero in fase di dichiarazione provoca un errore di “compilazione” A.A. 2006/2007 15 Corso: Sistemi Operativi © Danilo Bruschi Sezioni • Tutte le sezioni vanno dichiarate all’inizio di un programma, e possono avere un qualuqnue nome preceduto da un “.”, le dichiarazioni standard sono: • .sect .text ! codice • .sect .rom ! read only data • .sect .data ! read and write data • .sect .bss ! global data • I contenuti di una sezione non devono essere necessariamente contigui, il compilatore alloca i diversi contenuti alla sezione alla sezione che che li precede immediatamente A.A. 2006/2007 16 Corso: Sistemi Operativi © Danilo Bruschi Convenzioni • Nomi e Identificatori • Possono essere formati usando “.” "_", lettere (a--z and A--Z) e cifre (0--9). • Stringhe di caratteri: vanno racchiuse tra apice (') o doppio apice (") • Le parentesi tonde () sono usate per l’indirizzamento indiretto • Commenti: tutti le frasi precedute da un ! sono considerate commenti • Le stringhe "o16" e "o32“ prefisse ad un’istruzione indicano che gli operandi della stessa sono a 16/32 bits. • La stringa "rep" prefissa ad un’istruzione indica che l’istruzione va ripetuta finchè il valore del registro CX diventa zero A.A. 2006/2007 17 Corso: Sistemi Operativi © Danilo Bruschi Convenzioni • Segment prefix: la stringa “cseg/dseg/eseg/fseg/gseg/sseg” prefissa ad un’istruzione indicate che nell’indirizzamento vanno usati rispettivamente i registri cs/ds/es/fs/gs/ss • Quando si usano registri di 8 bit all’istruzione va aggiunto il suffisso “b“, es.: movb(edi), ah • Identificatori: Minix: A.A. 2006/2007 18 Corso: Sistemi Operativi © Danilo Bruschi Pseudo-istruzioni • .extern: dichiara l’uso di una variabilie definita in un altro file • .define: serve per definire una variabile globale che sarà refernziata come extern in altri file • .data: definisce una variabile di un byte • .data2 : definisce una variabile di 2 byte • .data4 : definisce una variabile di 4 byte • .ascii: definisce una stringa di caratteri • .asciz: definisce una stringa di caratteri terminata con il carattere 0x00 A.A. 2006/2007 19 Corso: Sistemi Operativi © Danilo Bruschi Pseudoistruzioni • .align 16: allinea gli indirizzi al word • .space NUM: definisce una spazio di memoria che contiene NUM byte a zero • .comm VAR NUM: definisce una varibile di nome VAR di NUM byte inizializzati a zero A.A. 2006/2007 20 Corso: Sistemi Operativi © Danilo Bruschi Istruzioni • Any instructions printed in your cpu’s assembly language manual can be used. Using comma"," to separate two operands. If more than one statement is written in one line, you must use semicolon”;” to separate them; if one statement is too long to be written in one line, using backlash”\” to connect the next line to the end of this line. A.A. 2006/2007 21 Corso: Sistemi Operativi © Danilo Bruschi Istruzioni • Data transfer • mov, xchg, push, pop • Binary arithmetic • add, sub, imul, mul, idiv, div, inc, dec • Logical • and, or, xor, not • Control transfer • jmp, jne, call, ret, int, iret • Input/output • in, out A.A. 2006/2007 22 Corso: Sistemi Operativi © Danilo Bruschi Operandi • registri: 8 bit (al, ah...), 16 bit (ax , ...), 32 bit (eax , ...), flag register (flags), segment register(cs , ds , ...), ... • espressioni: esempio 6*[3+2]-2 ! result=28 (3) • (register): il valore del registro è l’operando dell’istruzione e quindi costituisce l’indirizzo del dato a cui accedere all’interno del segamento indirizzato dal registro ds • (expression) : il valore dell’espressione costituisce l’indirizzo dell’operando a cui accedere • expression (register): la somma tra il valore dell’espressione e quello del registro costituiscono l’inidirzzo dell’operando a cui accedere • expression (register*SCALE):la somma tra il valore dell’espressione ed il contneuto del registro moltiplicato SCALE determinano l’indirizzo dell’operando a cui accedere. SCALE può assumere i valori 2, 4 or 8 A.A. 2006/2007 23 Corso: Sistemi Operativi © Danilo Bruschi Operandi • expression (register1)(register2): la somma del valore dell’espressione e dei contenuti di register1 e register2 formano l’indirizzo dell’operando a cui accedere • expression (register1)(register2*SCALE): la somma del valore dell’espressione, di register1 e di register2*SCALE formano l’indirizzo dell’operando a cui accedere • In questi casi register1 svolge le funzion di registro base, il segmento di default dell’operando determinato dall’istruzione è quello a cui si riferisce register1 A.A. 2006/2007 24 Corso: Sistemi Operativi © Danilo Bruschi Call ANSI C da codice assembly • La funzione C deve essere dichiarata “.extern” ed il suo nome deve essere preceduto dal prefisso _ • Se la funzione C ha dei parametri questi devono essere passati, prima della chiamata, attraverso lo stack • Al ritorno della funzione, il suo codice di ritorno e memorizzato in eax e lo stack deve essere ripristinato int c_function(int a, int b, int c); (in assembly language code file) extern _c_function push c push b push a call _c_function add esp,3*4 A.A. 2006/2007 25 Corso: Sistemi Operativi © Danilo Bruschi Call assembly language from ANSI C • La funzione va dichiarata in modo tale da poter vessere utilizzata al di fuori del programma assembler. • .define _s_function (in assembly language code file) • _s_function: • !get the parameters • Quando la funzione viene chiamata dal C il carattere di underscore va rimosso • s_function(a,b,c) A.A. 2006/2007 26 Corso: Sistemi Operativi © Danilo Bruschi Stack • Area di memoria organizzata in modalità LIFO il primo elemento acquisito è l’ultimo memorizzato • Le istruzioni che usano lo stack sono: CALL, RET, PUSH, POP, ENTER, e LEAVE • Tutte fanno riferimento al registro SS per individuare il segmento di memoria che contiene lo stack da usare (current stack) • Il registro ESP contiene l’indirizzo dell’ultimo elemento memorizzato sullo stack (top of the stack) A.A. 2006/2007 27 Corso: Sistemi Operativi © Danilo Bruschi Stack A.A. 2006/2007 28 Corso: Sistemi Operativi © Danilo Bruschi PUSH/POP • L’istruzione PUSH sottrae 4 dal registro ESP e inserisce 4 byte in (ESP) • L’istruzione POP legge 4 byte all’indirizzo (ESP) e somma 4 a ESP • Le istruzioni PUSHA/POPA operano su tutti i registri EAX, EBX, ECX, EDX, ESI, EDI and EBP • Nel seguente codice si asusme che il codice iniziale di ESP sia 0x1000 (1000h) A.A. 2006/2007 29 Corso: Sistemi Operativi © Danilo Bruschi PUSH/POP A.A. 2006/2007 30 Corso: Sistemi Operativi © Danilo Bruschi CALL/RET • CALL SUB effettua un salto incondizionato all’istruzione con label SUB e carica l’indirizzo dell’istruzione successiva alla CALL, sullo stack • RET effettua una POP e salta all’indirizzo così ottenuto • È importante gestire correttamente lo stack per evitare che RET effettui dei rientri errati A.A. 2006/2007 31 Corso: Sistemi Operativi © Danilo Bruschi Esempio mov ebx, input1 call get_int get_int: call read_int mov [ebx], eax push eax ret A.A. 2006/2007 32 Corso: Sistemi Operativi © Danilo Bruschi Parametri via Stack • I parametri ad un sottoprogramma sono solitamente passati attraverso lo stack, attraverso una o più istruzioni push prima della call • I parametri che devono esserem odificati dalla subroutine devon essere passati per indirizzo A.A. 2006/2007 33 Corso: Sistemi Operativi © Danilo Bruschi Stack Param • Il valore dei parametri passati sullo stack può essere recuperato attraverso l’indirizzamento indiretto (ESP+4) A.A. 2006/2007 34 Corso: Sistemi Operativi © Danilo Bruschi Stack • Se lo stack viene anche usato per memorizzare dati locali del sottoprogramma l’uso corretto di ESP può risultare un pò difficoltoso • Per risolvere questo problema viene fornito nell’architettura IA-32 un ulteriore registro che opera esclusivamente sullo stack: EBP. A.A. 2006/2007 35 Corso: Sistemi Operativi © Danilo Bruschi Epilogo/prologo • La convenzione imposta dal C, impone che la prima istruzione eseguita da un sottoprogramma sia il salvataggio del valore di EBP e successivamente il suo utilizzo per memorizzare il valore di ESP • Le variabili locali saranno allocate subito dopo aver salvato il valore di EBP sottraendo il numero di byte richiesto da ESP • ESP potrà quindi essere modificato a piacere, mentre il riferimento ai parametri del sottoprogramma sarà garantito da EBP • Al termine del sottoprogramma il valore originale di EBP deve essere ripristinato A.A. 2006/2007 36 Corso: Sistemi Operativi © Danilo Bruschi EBP A.A. 2006/2007 37 Corso: Sistemi Operativi © Danilo Bruschi Prologo/epilogo A.A. 2006/2007 38 Corso: Sistemi Operativi © Danilo Bruschi cal_sum: push ebp mov ebp, esp sub esp, 4 ! make room for local sum mov (ebp – 4),0 ! sum = 0 mov ebx, 1 ! ebx (i) = 1 for_loop: cmp ebx,(ebp+8) ! is i <= n? jnle end_for add (ebp-4),ebx ! sum += i inc ebx jmp short for-loop end for: mov mov mov mov pop ret ebx,(ebp+12) ! ebx = sump eax,(ebp-4) ! eax = sum (ebx), eax ! *sump = sum; esp,ebp ebp A.A. 2006/2007 39 Corso: Sistemi Operativi © Danilo Bruschi Stack frame A.A. 2006/2007 40 Corso: Sistemi Operativi © Danilo Bruschi Calling Convention • • Quando il sottoprogramma termina i parametri che erano stati caricati sullo stack vanno rimossi La convenzione C specifica che sia il chiamante a farsi carico di questo compito • Nella chiamata di una funzione C da un programma assembler, gli argomenti vanno passati nell’ordine inverso in cui appaiono nella dichiarazione della procedura • EBX, ESI, EDI, EBP, CS, DS, SS, ES: se una subroutine modifica i valori di questi registri deve ripirsitnarli prima di rientrare A.A. 2006/2007 41 Corso: Sistemi Operativi © Danilo Bruschi 00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 /* Constants for protected mode. */ /* Table sizes. */ #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) /* spec. and LDT's */ #define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */ #define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */ /* Fixed global descriptors. #define GDT_INDEX #define IDT_INDEX #define DS_INDEX #define ES_INDEX #define SS_INDEX #define CS_INDEX #define MON_CS_INDEX #define GDT_SELECTOR 0x08 00027 #define IDT_SELECTOR 00028 #define DS_SELECTOR 00029 #define ES_SELECTOR 00030 #define FLAT_DS_SELECTOR 00031 #define SS_SELECTOR 00032 #define CS_SELECTOR 00033 #define MON_CS_SELECTOR 00034 #define TSS_SELECTOR A.A. 2006/2007 1 2 3 4 5 6 7 1 to /* /* /* /* /* /* /* 7 are prescribed by the BIOS. */ GDT descriptor */ IDT descriptor */ kernel DS */ kernel ES (386: flag 4 Gb at startup) */ kernel SS (386: monitor SS at startup) */ kernel CS */ temp for BIOS (386: monitor CS at startup) */ /* (GDT_INDEX * DESC_SIZE) bad for asld */ 0x10 /* (IDT_INDEX * DESC_SIZE) */ 0x18 /* (DS_INDEX * DESC_SIZE) */ 0x20 /* (ES_INDEX * DESC_SIZE) */ 0x21 /* less privileged ES */ 0x28 /* (SS_INDEX * DESC_SIZE) */ 0x30 /* (CS_INDEX * DESC_SIZE) */ 0x38 /* (MON_CS_INDEX * DESC_SIZE) */ 0x40 /* (TSS_INDEX * DESC_SIZE) */ 42 Corso: Sistemi Operativi © Danilo Bruschi !*============================================* !* level0_call * !*========================================* 515 _level0_call: 516 call save 517 jmp (_level0_func) 518 A.A. 2006/2007 43 Corso: Sistemi Operativi © Danilo Bruschi !*=============================================================* 316 !* save * 317 !*=========================================================* 318 ! Save for protected mode. This is much simpler than for 8086 mode, because the stack already points into the process table, or has already been switched to the kernel stack. 322 .align 16 323 save: 324 cld ! set direction flag to a known value 325 pushad ! save "general" registers 326 o16 push ds ! save ds 327 o16 push es ! save es 328 o16 push fs ! save fs 329 o16 push gs ! save gs 330 mov dx, ss ! ss is kernel data segment 331 mov ds, dx ! load rest of kernel segments 332 mov es, dx ! kernel does not use fs, gs 333 mov eax, esp ! prepare to return 334 incb (_k_reenter) ! from -1 if not reentering 335 jnz set_restart1 ! stack is already kernel stack 336 mov esp, k_stktop 337 push _restart ! build return address for int handler 338 xor ebp, ebp ! for stacktrace 339 jmp RETADR-P_STACKBASE(eax) 341 .align 4 342 set_restart1: 343 push restart1 344 jmp RETADR-P_STACKBASE(eax) A.A. 2006/2007 44 Corso: Sistemi Operativi © Danilo Bruschi !*==============================================================* 520 !* idle_task * 521 !*==========================================================* 522 _idle_task: 523 ! This task is called when the system has nothing else to do.HLT 524 ! instruction puts the processor in a state where it draws minimum power. 525 push halt 526 call _level0 ! level0(halt) 527 pop eax 528 jmp _idle_task 529 halt: 530 sti 531 hlt 532 cli 533 ret 534 535!*===========================================================* 536 !* level0 * 537 !*==========================================================* 538 ! PUBLIC void level0(void (*func)(void)) 539 ! Call a function at permission level 0. This allows kernel tasks to do 540 ! things that are only possible at the most privileged CPU level. 541 ! 542 _level0: 543 mov eax, 4(esp) 544 mov (_level0_func), eax 545 int LEVEL0_VECTOR 546 ret 547 A.A. 2006/2007 45 Corso: Sistemi Operativi © Danilo Bruschi