Interfejsowanie do C/C++ w trybie 64 bitowym znacznie różni się od trybu 32 bitowego. Określa go AMD64 ABI.
Przede wszystkim argumenty są przekazywane nie przez stos ale w pierwszej kolejności przez rejestry w zależności od ich typu.
Skrócony opis można znaleźć w notatkach z wykładu.
Poniższe zadania powinny być rozwiązane w trybie 64 bitowym.
Napisz w assemblerze funkcję
extern "C" int suma (int n, int * tab);
która oblicza sumę n liczb całkowitych znajdujących się w tablicy tab np.
int tab[] ={1, 2, 3, 4};
suma(4, tab);
powinno zwrócić 10.
Napisz w assemblerze funkcję
extern "C" double wartosc (double a, double b, double x, int n);
która zwraca wartosc = (a*x+b)^n
Wywołanie wartosc(4, 3, 2, 2); powinno zwrócić 121.
Obliczenia należy wykonać na jednostce "SSE".
Zaimplementuj w assemblerze funkcję
extern "C" int iloczyn (int n, ...);
która oblicza iloczyn n liczb całkowitych podanych jako kolejne argumenty np.
iloczyn(4, 1, 2, 3, 4);
powinno zwrócić 24.
Wskazówka: Po zdjęciu adresu powrotu można na stosie odłożyć w kolejności R9, R8, RCX, RDX, RSI i wtedy otrzymamy tablicę argumentów (elementy znajdują się co 8 bajtów!).
#include <cstdio>
using namespace std;
class Faktura{
private:
int id;
float obrot;
float podatekNaliczony;
float stawkaPodatku;
static int nextID;
public:
Faktura(double obrot, double stawkaPodatku = 0.23, double podatekNaliczony = 0.0):
id(nextID++), obrot(obrot),
podatekNaliczony(podatekNaliczony), stawkaPodatku(stawkaPodatku){}
};
int Faktura::nextID = 0;
extern "C" float podatek(Faktura f);
extern "C" void wypisz(const Faktura & f);
int main(){
Faktura buraki(1000, 0.23, 100);
printf("Podatek : %f\n", podatek( buraki));
wypisz(buraki);
return 0;
}
Dla powyższego kodu w C++ napisz moduł assemblerowy implementujący funkcje:
float podatek(Faktura f) - zwracającą należny podatek według wzoru:
podatek= (obrót - podatekNaliczony) * stawkaPodatku
void wypisz(const Faktura & f) - wypisującą na ekran napis przy pomocy standardowej funkcji printf
printf("Faktura %d : obrot %f podatek %f\n", f.id, f.obrot, podatek(f));
Wskazówki:
Obiekt klasy Faktura przekazywany do funkcji podatek przez wartość zostanie pocięty na kawałki 8 bajtowe: pierwszy trafi do RDI, drugi do XMM0.
Funkcja printf wymaga aby
standard ABI64 był przestrzegany, w szczególności: stos był wyrównany, w rejestrze RAX umieszczona była liczba argumentów w rejestrach XMM
liczby typu float były przekazane jako double (konwersja np. cvtss2sd).