Do rozwiązania zadań przydatna jest znajomość wykładów
Zaimplementuj w osobnym module assemblerowym funkcje, które rotują w lewo bity w liczbie x o n pozycji o następujących nagłówkach
unsigned int rotate(unsigned int x, int n = 1);
unsigned char rotate(unsigned char x, int n = 1);
#include <cstdio>
template <typename T>
void test(){
T a = 1, b = 127;
printf("%u %u\n", (unsigned)rotate(a, 1), (unsigned)rotate(b,1));
printf("%u %u\n", (unsigned)rotate(a, 8), (unsigned)rotate(b,8));
printf("%u %u\n", (unsigned)rotate(a, 31), (unsigned)rotate(b,31));
printf("--------\n");
}
int main(){
test<unsigned char>();
test<unsigned int>();
return 0;
}
/** Spodziewane wyjście
2 254
1 127
128 191
--------
2 254
256 32512
2147483648 2147483711
--------
*/
Wskazówki: aby zobaczyć nazwy jakie funkcjom nadał kompilator użyj funkcję w funkcji main a następnie przetłumacz plik do asemblera
g++ -S plik.cpp -o plik.s
Do rotacji użyj instrukcji
ROL rejestr, przesunięcie
(przesunięcie powinno być podane w rejestrze CL)
Wykorzystując operacje łańcuchowe i przedrostek REP zaimplementuj w asemblerze funkcje
// kopiuje n liczb typu int z zrodla do celu
void kopiuj(unsigned int * cel, unsigned int * zrodlo, unsigned int n);
// zeruje tablice liczb typu int o rozmiarze n
void zeruj(unsigned int * tablica, unsigned int n);
Poniższa klasa BigInt reprezentuje bardzo duże liczby całkowite bez znaku. Liczbę taka przechowujemy następująco:
zapisujemy ją binarnie, a następnie tniemy na kawałki po 32 bity i każdy taki kawałek jest przechowywany jako liczba unsigned int w tablicy dane.
Dla klasy BigInt
#include <iostream>
// Funkcje z zadania 2 // kopiuje n liczb typu int z zrodla do celu void kopiuj(unsigned int * cel, unsigned int * zrodlo, unsigned int n); // zeruje tablice liczb typu int o rozmiarze n void zeruj(unsigned int * tablica, unsigned int n);class BigInt{ unsigned int rozmiar; unsigned int * dane; public: explicit BigInt(unsigned int rozmiar) : rozmiar(rozmiar), dane( new unsigned[rozmiar] ){ zeruj(dane, rozmiar); } BigInt(const BigInt & x) : rozmiar(x.rozmiar), dane(new unsigned[x.rozmiar]){ kopiuj(dane, x.dane, x.rozmiar); } BigInt & operator=(const BigInt & x) { if(rozmiar != x.rozmiar){ unsigned * tmp = new unsigned[x.rozmiar]; delete[] dane; rozmiar = x.rozmiar; dane = tmp; } kopiuj(dane, x.dane, x.rozmiar); return *this; } ~BigInt(){ delete[] dane; }// do zaimplementowania w zadaniu 3 int dodaj(unsigned int n); int pomnoz(unsigned int n); int podzielZReszta(unsigned int n); BigInt & operator=(const char * liczba); friend std::ostream & operator << (std::ostream & str, const BigInt & x);// do zaimplementowania w zadaniu 4 friend BigInt operator+ (const BigInt & a, const BigInt & b); friend BigInt operator- (const BigInt & a, const BigInt & b);};
zaimplementuj w asemblerze metody
int BigInt::dodaj(unsigned int n);
dodaje do obiektu BigInt (modyfikując go) liczbę całkowitą n,
funkcja zwraca 1 jeżeli nastąpiło przepełnienie liczby BigInt, 0 w przeciwnym wypadku,
(w praktyce dodajemy n do dane[0] a potem tylko propagujemy przeniesienie)
int BigInt::pomnoz(unsigned int n);
mnoży obiekt BigInt przez n (modyfikując obiekt),
funkcja zwraca 1 jeżeli nastąpiło przepełnienie liczby BigInt, 0 w przeciwnym wypadku,
unsigned int BigInt::podzielZReszta(unsigned int n);
dzieli obiekt BigInt przez n (modyfikując go) i zwraca resztę z dzielenia.
Z ich pomocą (można już w języku C++) zdefiniuj operatory:
wypisania liczby BigInt do strumienia
przypisania łańcucha tekstowego, zawierającego liczbę np. a="1234214243543543543243543534";
Dla klasy BigInt dopisz operatory dodawania i odejmowania
BigInt operator+ (const BigInt & a, const BigInt & b);
BigInt operator- (const BigInt & a, const BigInt & b);
Proszę te operatory całkowicie napisać w assemblerze,
W prostszej wersji można założyć, że a i b są tej samej długości.
Należy z asemblera wywołać konstruktor BigInt dla adresu pamięci przekazanego jako pierwszy argument.
W dodawaniu dobrze jest skorzystać z instrukcji ADC, która dodaje dwie liczby dodając dodatkowo 1 jeżeli w poprzednim dodawaniu została ustawiona flaga CF.
Dla odejmowania można analogicznie użyć instrukcji SBB.