Università degli Studi di Udine Corsi di laurea in Ingegneria Elettronica Architettura dei calcolatori (ex Fondamenti di Informatica II) 24 gennaio 2011 - Prova scritta Matricola __________________ Nome _____________________ Cognome __________________ ISTRUZIONI (da leggere attentamente) 1) Lo studente è tenuto a scrivere, correggere, compilare ed eseguire su computer (a casa o in laboratorio) gli esercizi di programmazione prima della prova orale. Alla prova orale lo studente deve portare un floppy disk contenente i sorgenti dei programmi corretti e le stampe dei relativi file. 2) Non è consentito l’uso di libri, appunti, calcolatrici programmabili, telefoni cellulari. 3) Rispondere sinteticamente negli spazi di fianco o seguenti le domande, oppure sul retro del foglio. 1. (4 punti) L’istruzione printf ("%X", *((int*)&x)) stampa in esadecimale il contenuto della memoria all’indirizzo dove è memorizzata la variabile float x, senza interpretarne la rappresentazione floating point. Il risultato ottenuto è BD400000. Ricordando che la rappresentazione dell’esponente è in eccesso 127, cosa stamperebbe l’istruzione printf ("%f", x)? Si scrivano tutti i passaggi e i calcoli effettuati. B D 4 0 0 0 0 0 1011 1101 0100 0000 0000 0000 0000 0000 segno (-) esponente mantissa (1.12 = 1.510 denormalizzata) calcolo del valore dell’esponente: 011110102 = 112eccesso 127 = 122-127 = -5 calcolo del valore della variabile: -1.5 · 2-5 = -1.5 * 0.3125 = -0.046875 2. (4 punti) Si illustri brevemente la codifica entropica. (si vedano il libro di testo, gli appunti e i lucidi delle lezioni) Si consideri la libreria in linguaggio C per manipolare file bitmap vista a lezione, così definita: typedef typedef typedef unsigned char unsigned short int unsigned long int byte; word; dword; #define BMPFILETYPE 0x4D42 typedef struct tagCOLORTRIPLE { byte blue; byte green; byte red; } COLORTRIPLE; 3. typedef struct tagFILEHEADER { word ImageFileType; dword FileSize; word Reserved1; word Reserved2; dword ImageDataOffset; } FILEHEADER; typedef struct tagBMPHEADER { dword HeaderSize; dword ImageWidth; dword ImageHeight; word NumberOfImagePlanes; word BitsPerPixel; dword CompressionMethod; dword SizeOfBitmap; dword HorizonalResolution; dword VerticalResolution; dword NumberOfColorsUsed; dword NumberOfSignificantColors; } BMPHEADER; typedef struct tagBITMAP { dword width; dword height; COLORTRIPLE *pixel; FILEHEADER fileheader; BMPHEADER bmpheader; } BITMAP; #define PIXEL(image, row, column) \ image.pixel [(row( * image.width + (column)] BITMAP void BITMAP void ReadBitmap (FILE *fp); WriteBitmap (BITMAP bitmap, FILE *fp); CreateEmptyBitmap (dword height, dword width); ReleaseBitmapData (BITMAP *bitmap); (7 punti) Per pilotare un proiettore a tre LCD è necessario scomporre l’immagine a colori in tre immagini in bianco e nero, ciascuna rappresentante uno dei colori primari, da inviare poi a un pannello a cui è associato un filtro semitrasparente del colore corrispondente. Si scriva un programma in linguaggio C che riceva sulla riga di comando il nome di un file bitmap, senza estensione. Il programma deve creare altri tre file bitmap, i cui nomi sono quello del file originale più “_RED”, “_GREEN” e “_BLUE”, il cui contenuto è l’immagine in bianco e nero della sola componente rossa, verde e blu rispettivamente. Esempio: Immagine originale (ovviamente a colori) #include #include #include #include componente RED componente GREEN <stdio.h> <stdlib.h> <string.h> "bmp.h" void CreaComponenti (BITMAP bmp, BITMAP bmp_R, BITMAP bmp_G, BITMAP bmp_B); int main (int argc, char *argv[]) { FILE *fpin, *fpoutR, *fpoutG, *fpoutB; BITMAP bmp, bmp_R, bmp_G, bmp_B; char filename[64], filenameR[64], filenameG[64], filenameB[64]; if (argc != 2) { printf ("USO:componenti_RGB <bmp>\n"); exit (EXIT_FAILURE); } strcpy strcat strcpy strcat strcpy strcat strcpy strcat (filename, argv[1]); (filename, ".bmp"); (filenameR, argv[1]); (filenameR, "_RED.bmp"); (filenameG, argv[1]); (filenameG, "_GREEN.bmp"); (filenameB, argv[1]); (filenameB, "_BLUE.bmp"); if ((fpin = fopen (filename, "rb")) == NULL) { printf ("Error opening input file\n"); exit (EXIT_FAILURE); } if ((fpoutR = fopen (filenameR, "wb")) == NULL) { printf ("Error opening output file\n"); exit (EXIT_FAILURE); } if ((fpoutG = fopen (filenameG, "wb")) == NULL) { printf ("Error opening output file\n"); exit (EXIT_FAILURE); } if ((fpoutB = fopen (filenameB, "wb")) == NULL) { printf ("Error opening output file\n"); exit (EXIT_FAILURE); } bmp = bmp_R bmp_G bmp_B ReadBitmap (fpin); = CreateEmptyBitmap (bmp.height, bmp.width); = CreateEmptyBitmap (bmp.height, bmp.width); = CreateEmptyBitmap (bmp.height, bmp.width); CreaComponenti (bmp, bmp_R, bmp_G, bmp_B); /* write the files */ WriteBitmap (bmp_R, fpoutR); WriteBitmap (bmp_G, fpoutG); WriteBitmap (bmp_B, fpoutB); componente BLUE ReleaseBitmapData ReleaseBitmapData ReleaseBitmapData ReleaseBitmapData fclose fclose fclose fclose (&bmp); (&bmp_R); (&bmp_G); (&bmp_B); (fpin); (fpoutR); (fpoutG); (fpoutB); return EXIT_SUCCESS; } void CreaComponenti (BITMAP bmp, BITMAP bmp_R, BITMAP bmp_G, BITMAP bmp_B) { int row, col; for (row = 0; row < bmp.height; row++) { for (col = 0; col < bmp.width; col++) { PIXEL(bmp_R, row, col).red = PIXEL(bmp_R, row, col).green = PIXEL(bmp_R, row, col).blue = PIXEL(bmp, row, col).red; PIXEL(bmp_G, row, col).red = PIXEL(bmp_G, row, col).green = PIXEL(bmp_G, row, col).blue = PIXEL(bmp, row, col).green; PIXEL(bmp_B, row, col).red = PIXEL(bmp_B, row, col).green = PIXEL(bmp_B, row, col).blue = PIXEL(bmp, row, col).blue; } } return; } Un elaboratore (il modello didattico SimCPU visto a lezione) dispone di CPU (a 16 bit) con 16 registri di uso generale (R0, R1, ..., R15) più il Program Counter, l’Instruction Register, lo Stack Pointer e 4 flag Z (zero), N (negative), C (carry) e V (overflow). Si ricorda che il linguaggio assembler di tale elaboratore dispone delle seguenti istruzioni: assembly inst. name machine code LDWI LDWA LDWR LDBI LDBA LDBR STWA STWR STBA STBR MV PUSH POP SPRD SPWR load word load word load word load byte load byte load byte store word store word store byte store byte move push pop read SP write SP 00010000dddd0000 00100000dddd0000 00110000ddddaaaa 00010001dddd0000 00100001dddd0000 00110001ddddaaaa 00100010ssss0000 00110010ssssaaaa 00100011ssss0000 00110011ssssaaaa 00000100ssssdddd 00001000ssss0000 00001001dddd0000 00001101ssss0000 00001110ssss0000 add subtract bitwise NOT bitwise AND bitwise OR bitwise XOR increment decrement left shift right shift 01000000ssssdddd 01000001ssssdddd 01000010rrrr0000 01000011ssssdddd 01000100ssssdddd 01000101ssssdddd 01001000rrrr0000 01001001rrrr0000 01001010rrrr0000 01001011rrrr0000 ADD SUB NOT AND OR XOR INC DEC LSH RSH 4. d d d d d d s s s s s s d d s s s r s s s r r r r X A a X A a A a A a d d d d d d DATA(16) ADDR(16) DATA(8) ADDR(16) ADDR(16) ADDR(16) action assembly inst. name machine code d <- X d <- mem[A] d <- mem[a] d <- X d <- mem[A] d <- mem[a] mem[A] <- s mem[a] <- s mem[A] <- s mem[a] <- s d <- s push (s) d <- pop () d <- SP SP <- s INW INB OUTW OUTB TSTI 10000000dddd0000 10000001dddd0000 10000010ssss0000 10000011ssss0000 1000010000000000 d d r d d d r r r r <<<<<<<<<<- d + s d - s ~r d & s d | s d ^ s r + 1 r + 1 r << 1 r >> 1 d d s s A A A A A input word input byte out word out byte test input action IN_ADDR(16) IN_ADDR(16) OUT_ADDR(16) OUT_ADDR(16) IN_ADDR(16) TSTO A test output 1000010100000000 OUT_ADDR(16) BR JMP JMPZ JMPNZ JMPN JMPNN JMPC JMPV CALL RET HLT branch jump jump if zero jump if not zero jump if negative jump if not neg. jump if carry jump if overflow subroutine call return from sub. halt A F F F F F F F A d <- read[A] d <- read[A] out[A] <- s out[A] <- s if completed then Z <- 1 else Z <- 0 if completed then Z <- 1 else Z <- 0 1100000000000000 ADDR(16) PC <- A 11000001FFFFFFFF PC <- PC + F 11000010FFFFFFFF if (z == 1) PC <- PC 11000011FFFFFFFF if (z == 0) PC <- PC 11000100FFFFFFFF if (N == 1) PC <- PC 11000101FFFFFFFF if (N == 0) PC <- PC 11000110FFFFFFFF if (C == 1) PC <- PC 11000111FFFFFFFF if (V == 1) PC <- PC 1100100000000000 ADDR(16) push (PC); PC <- A 1100100100000000 PC <- pop() 1100111100000000 halt + + + + + + F F F F F F LEGENDA: - lettere minuscole = registri; lettere maiuscole = dati numerici - ‘r’ = registro letto e modificato - ‘s’ = registro soltanto letto - ‘d’ = registro modificato - ‘a’ = registro il cui contenuto è usato come indirizzo - FFFFFFFF = offset (in complemento a 2) (6 punti) Si scriva in linguaggio assembler la funzione IN_INTERVALLO che riceve in ingresso tre valori interi nei registri R1, R2 e R3 e restituisce, nel registro R0, il valore uno se R2 ≤ R1 ≤ R3 e zero altrimenti. IN_INTERVALLO: MV R1 R10 SUB R2 R10 JMPN EXIT_FALSO MV R3 R10 SUB R1 R10 JMPN EXIT_FALSO LDWI R0 1 RET EXIT_FALSO: LDWI R0 0 RET 5. 1A 04 2A 41 0C C4 3A 04 1A 41 06 C4 00 10 01 00 00 C9 00 10 00 00 6. (4 punti) Si traduca in linguaggio macchina la funzione scritta nell’esercizio precedente. | IN_INTERVALLO: | | | | | | | | | | | | | | | | | | EXIT_FALSO: | | | MV R1 R10 SUB R2 R10 JMPN EXIT_FALSO MV R3 R10 SUB R1 R10 JMPN EXIT_FALSO LDWI R0 1 RET LDWI R0 0 (5 punti) Indicare quali dei seguenti elementi sono indispensabili per il funzionamento di un sistema operativo multitasking e, per ciascuno degli elementi selezionati, si scriva una breve descrizione specificando che ruolo ha nell’ambito del multitasking: INTERRUPT, INTERFACCIA GRAFICA A FINESTRE, MMU, PAGE FILE, MULTIPROGRAMMAZIONE (si vedano il libro di testo, gli appunti e i lucidi delle lezioni) 7. (2 punti) Cos’è una funzione di callback? A cosa serve? (si vedano il libro di testo, gli appunti e i lucidi delle lezioni)