ako_pytania_zadania_cz2_2010.doc

(77 KB) Pobierz

Zadania przykładowe do ćwiczeń z „Architektury komputerów”

cz. II, maj 2010

 


 


 

1. Podać liczbę, która zostanie wyświetlona na ekranie w wyniku wykonania poniższego fragmentu programu. Podprogram wyswietl32 wyświetla na ekranie w postaci dziesiętnej liczbę binarną zawartą w rejestrze EAX.

 

qxy              dw              254, 255, 256

—    —    —    —    —    —    —    —

mov              eax, dword PTR qxy + 1

call              wyswietl32

 

 

 

2. Funkcja MessageBoxA@16(0, adr1, adr2, 0) wyświetla komunikat na ekranie: adr1 jest adresem tekstu wyświetlanego w okienku komunikatu, adr2 jest adresem tekstu wyświetlanego w tytule komunikatu. Koniec tekstu wskazuje bajt o wartości 0. Rozkaz LEA oblicza adres efektywny rozkazu.

Określić postać komunikatu po wykonaniu poniższego fragmentu programu.

 

napis db     'informatyka', 0, 4 dup (?)

—    —    —    —    —    —    —    —    —

mov              ecx, 12

przepisz:              mov              al, napis[ecx-1]

mov              napis[ecx+3], al

loop              przepisz

 

push              0

push              OFFSET napis

lea              eax, napis[3]

push              eax

push              0

call              _MessageBoxA@16

 

 

 

3. W programach obsługi kalendarza MS Visual Studio dni świąteczne w miesiącu koduje się w postaci jedynek umieszczonych na odpowiednich bitach słowa 32-bitowego. Tablica zawierająca 12 takich elementów pozwala zakodować informacje obejmujące rok.

 

Napisać podprogram w asemblerze wyświetlający na ekranie daty dni świątecznych w podanym miesiącu. Parametry wywołania podprogramu znajdują się w rejestrach:

 

CL – numer miesiąca (1 – 12)

EBX – adres tablicy zawierającej zakodowane daty dni świątecznych w poszczególnych miesiącach.

 


4. W rejestrach EDX:EBX:EAX znajduje się 96-bitowy ciąg bitów. Napisać fragment programu, w którym ciąg ten zostanie przesunięty cyklicznie w lewo o 1 pozycję.

Wskazówka: wykorzystać rozkazy przesunięcia w lewo SHL (bity wychodzące z rejestru wpisywane są do CF) i RCL (zawartość CF wpisywana jest na najmłodszy bit rejestru, a bity wychodzące z rejestru wpisywane są do CF). Wykorzystać także rozkaz BT.

 

 

 

5. W programie asemblerowym zdefiniowano format 32-bitowych liczb mieszanych bez znaku, przyjmując, że najmniej znaczący bit ma wagę 2-7.

Napisać fragment programu w asemblerze, który wpisze 1 do znacznika CF (rozkaz STC) jeśli część całkowita liczby zawartej w rejestrze EBX jest różna od zera; w przeciwnym razie CF powinien zostać wyzerowany (rozkaz CLC).

 

 

 

6. Na poniższym rysunku pokazane są dwa formaty 32-bitowych liczb stałoprzecinkowych bez znaku używane w programie.

Zakładając, że w rejestrze ESI znajduje się liczba zakodowana wg pierwszego formatu (najmniej znaczący bit ma wagę 2-8), a w rejestrze EDI liczba zakodowana wg drugiego formatu (najmniej znaczący bit ma wagę 2-7), napisać fragmentu, który porówna obie liczby. Jeśli liczba w rejestrze ESI jest większa od liczby w rejestrze EDI, to do CF należy wpisać 1, w przeciwnym razie 0 (rozkazy STC/CLC).


7.  Poniżej podano fragment programu w języku C.

 

int a, b, * wsk, wynik;

wsk = &b;

a = 21; b = 25;

wynik = roznica(&a, &wsk);

 

Napisać podprogram w asemblerze przystosowany do wywoływania z poziomu języka C, którego prototyp ma postać:

 

int roznica (int * odjemna,

                                          int ** odjemnik);

 

Podprogram ten powinien obliczyć różnicę dwóch liczb całkowitych ze znakiem w kodzie U2.

 

 

 

8. Poniżej podano fragment programu w języku C.

 

int pomiary[7], * wsk;

- - - - - - - - - - - - - - -

wsk = szukaj_elem_min(pomiary, 7);

printf("\nElement minimalny = %d\n",

                                                        * wsk);

Napisać podprogram w asemblerze przystosowany do wywoływania z poziomu języka C, którego prototyp ma postać:

 

int * szukaj_elem_min (

                            int tablica[ ], int n);

 

Podprogram ten powinien wyznaczyć najmniejszy element  tablicy i zwrócić adres (wskaźnik) tego elementu. Liczbę elementów tablicy określa drugi parametr funkcji.

 

 

 

9. Napisać podprogram w asemblerze przystosowany do wywoływania z poziomu języka C. Prototyp funkcji implementowanej przez ten podprogram ma postać:

void nowy_strcat (char * wynik, char * zrodlo);

gdzie wynik i zrodlo są adresami (wskaźnikami) tablic zawierających ciągi znaków ASCII, przy czym koniec ciągu wskazuje bajt o wartości 0. Podprogram powinien dopisać znaki zawarte w tablicy zrodlo do znaków zawartych w tablicy wynik.

Napisać także krótki program w języku C ilustrujący sposób ilustrujący sposób wywoływania tego podprogramu. W programie tym należy wczytać z klawiatury dwa dowolne teksty (funkcja scanf), a następnie, korzystając z opracowanej funkcji, wyświetlić połączone teksty.

 

 


10.  Funkcja biblioteczna języka C o prototypie

void * malloc(unsigned int k);

przydziela k-bajtowy obszar pamięci i zwraca adres przydzielonego obszaru. Jeśli wymagany obszar nie może być przydzielony, to funkcja zwraca wartość 0.

Napisać podprogram w asemblerze, przystosowany do wywoływania z poziomu języka C — prototyp tego podprogramu ma postać:

 

int * kopia_tablicy(int tabl[],

                            unsigned int n);

 

Podprogram kopia_tablicy tworzy nową tablicę o rozmiarach identycznych z oryginalną i zwraca adres nowej tablicy (albo 0, jeśli tablicy nie można było utworzyć).

Do nowej tablicy należy skopiować wszystkie elementy tablicy oryginalnej o wartościach będących liczbami parzystymi. Pozostałe elementy nowej tablicy wypełnić zerami.

Wskazówki:

1.       Nową tablicę należy utworzyć poprzez przydzielenie odpo­wie­dniego obszaru pamięci za pomocą funkcji malloc.

2.       Sprawdzenie czy liczba jest parzysta najłatwiej wykonać poprzez odczytanie najmłodszego bitu liczby (bit nr 0).

 

 

 

11.  Napisać podprogram w asemblerze obliczający wartość funkcji kwadrat metodą rekurencyjną korzystając z zależności:

              a2 = (a – 2) 2 + 4*a – 4              dla a > 1

              a2 = 1                                          dla a = 1

              a2 = 0                                          dla a = 0

przy czym argument a jest liczbą całkowitą 32-bitową zawartą w przedziale <1, 65535>.

Podprogram powinien być przystosowany do wywoływania z poziomu języka C, a jego prototyp ma postać:

 

unsigned int kwadrat (

                                          unsigned int a);

 

W podprogramie nie można używać rozkazów mnożenia i rozkazów przesunięć.

 


12. Podać wartość zwracaną przez funkcję iteracja w poniższym fragmencie programu w języku C

w = iteracja(32);

Kod funkcji iteracja zapisany w asemblerze ma postać

 

_iteracja     PROC

           push    ebp

           mov     ebp, esp

           mov     al, [ebp+8]

           sal     al, 1

; SAL wykonuje przesuniecie logiczne

; w lewo

           jc      zakoncz

           inc     al

           push    eax

           call    _iteracja

           add     esp, 4

           pop     ebp

           ret

 

zakoncz:   rcr     al, 1

; rozkaz RCR wykonuje przesunięcie

; cykliczne w prawo przez CF

           pop     ebp

           ret

_iteracja     ENDP

 

 

 

13. W pamięci komputera, począwszy od adresu podanego w rejestrze ESI znajduje się 32-bitowa liczba zmiennoprzecinkowa w formacie float. Napisać fragment programu, który przekształci tę liczbę na 64-bitowy format double i uzyskany rezultat wpisze do pamięci począwszy od adresu podanego w rejestrze EDI. W omawianym fragmencie nie można używać rozkazów koprocesora arytmetycznego.

 

 

14. W rejestrze EAX znajduje się liczba zmiennoprzecinkowa w formacie float. Napisać fragment programu, który zwiększy tę liczbę o 2, przy czym w fragmencie nie mogą występować rozkazy koprocesora arytmetycznego. Dodatkowo zakładamy, że liczba zmiennoprzecinkowa jest dodatnia.

 

 

 

15. W rejestrze EAX znajduje się liczba zmiennoprzecinkowa w formacie float. Napisać fragment programu, który zwiększy tę liczbę o 0.25, przy czym w fragmencie nie mogą występować rozkazy koprocesora arytmetycznego. Dodatkowo zakładamy, że liczba zmiennoprzecinkowa jest dodatnia.

 

 


16. Poniżej podano kod (niepełny) podprogramu w asemblerze, który zwiększa o 1 liczbę zmiennoprzecinkową w formacie double. Podprogram przystosowany jest do wywoływania z poziomu języka C, a jego prototyp ma postać:

double  plus_jeden  (double  x);

Nie używając rozkazów koprocesora, uzupełnić brakujący fragment podprogramu, przy założeniu, że liczba x jest większa od 1, a zawartość pola wykładnika (w formacie double) należy do przedziału <1023, 1075>. Uwaga: po wykonaniu dodawania przeprowadzić normalizację liczby.

 

_plus_jeden        PROC

           push    ebp

           mov     ebp, esp

           push    ebx

           push    esi

           push    edi

; odczytanie liczby

; w formacie double

           mov     eax, [ebp+8] 

           mov     edx, [ebp+12]

; wpisanie 1 na pozycji o wadze 2^0

; mantysy do EDI:ESI

           mov     esi, 0

           mov     edi, 00100000H

; wyodrębnienie pola

; wykładnika (11-bitowy)

; bit znaku liczby z założenia = 0

           mov     ebx, edx

           shr     ebx, 20

; obliczenie pierwotnego wykładnika

; potęgi

           sub     ebx, 1023

; zerowanie wykładnika i bitu znaku

           and     edx, 000FFFFFH

; dopisanie niejawnej jedynki

           or      edx, 00100000H  

—  —  —  —  —  —  —  —  —  —  —  —  —  —  —  —

—  —  —  —  —  —  —  —  —  —  —  —  —  —  —  —

; załadowanie obliczonej wartości z

; EDX:EAX na wierzchołek stosu

; koprocesora

           push    edx

           push    eax

           fld     qword PTR [esp]

           add     esp, 8

           pop     edi

           pop     esi

    ...

Zgłoś jeśli naruszono regulamin