Für die Aufgabe 3 vom 8. Übungsblatt sollen IEEE-Gleitkommazahlen addiert beziehungsweise subtrahiert werden. Anfangs gab es dazu x87-Coprozessoren (x87 bezeichnet den Teil des x86-Befehlssatzes, mit dem Gleitkommaberechnungen durchgeführt werden), die mit einer Art Stack-Architektur arbeiteten. Heute ist jedoch x87 eher unwichtig geworden, da heutige Prozessoren die Gleitkommaberechnungen über SSE2 durchführen – SSE2 ist bei allen x86-64bit-Prozessoren vorhanden.
Anders als bei Ganzzahlen können für IEEE-Gleitkommazahlen nicht die Standard-Register rax
, rbx
, etc. verwendet werden. Dafür gibt es spezielle Register, die mit xmm0
, xmm1
, …, xmm15
bezeichnet werden.
In der Calling Convention kann man lesen, dass Gleitkommazahlen über die Register xmm0
, xmm1
, etc. in dieser Reihenfolge übergeben werden. Wichtig ist, dass bei gemischten Ganz- und Gleitkommazahlen die Register pro Typ in der Reihenfolge verwendet werden. Der Aufruf test(1, 1.2, 4, 5, 6.3, 2.3)
übergibt die Zahlen in den folgenden Registern:
rdi = 1, rsi = 4, rdx = 5,
xmm0 = 1.2, xmm1 = 6.3, xmm2 = 2.3
Genauso passiert die Rückgabe einer Gleitkommazahl über das ersten SSE-Register xmm0
.
Um beispielsweise zwei Zahlen zu multiplizieren gibt es (unter anderem) die folgenden zwei Befehle:
mulss xmm2, xmm4 // xmm2 = xmm2 * xmm4 // (32bit)
mulsd xmm5, xmm1 // xmm5 = xmm5 * xmm1 // (64bit)
Der Unterschied besteht darin, dass die ss
-Befehle für single precision, also 32bit-IEEE-Gleitkommazahlen funktionieren, während die sd
-Befehle für double precision, also 64bit-IEEE-Gleitkommazahlen funktionieren. Hier muss also aufgepasst werden, ob die Funktion float
(32bit) oder double
(64bit) Parameter erwartet.
Analog dazu gibt es noch weitere Funktionen wie addss
, addsd
, subss
, subsd
, etc.