main.cpp
#include <stdio.h>
extern "C" bool SseSfpCalcSphereAreaVolume(double r, double* sa, double* v);
int main(int argc, char* argv[])
{
const double r[] = {-1.0, 0.0, 1.0, 2.0, 3.0, 5.0, 10.0, 20.0};
int num_r = sizeof(r) / sizeof(double);
for (int i = 0; i < num_r; i++)
{
double sa, v;
bool rc = SseSfpCalcSphereAreaVolume(r[i], &sa, &v);
printf("rc: %d r: %8.2lf sa: %10.4lf vol: %10.4lf\n", rc, r[i], sa, v);
}
return 0;
}
ssescalarfloatingpointspheres.asm
; Name: ssescalarfloatingpointspheres.asm
;
; Build: g++ -c -m32 main.cpp -o main.o -std=c++11
; nasm -f elf32 -o ssescalarfloatingpointspheres.o ssescalarfloatingpointspheres.asm
; g++ -m32 -o ssescalarfloatingpointspheres ssescalarfloatingpointspheres.o main.o
;
; Source: Modern x86 Assembly Language Programming p. 225
global SseSfpCalcSphereAreaVolume
; Constants required to calculate sphere surface area and volume.
section .data
r8_pi dq 3.14159265358979323846
r8_four dq 4.0
r8_three dq 3.0
r8_neg_one dq -1.0
section .text
; extern "C" bool SseSfpCalcSphereAreaVolume_(double r, double* sa, double* v);
;
; Description: The following function calculates the surface area and
; volume of a sphere.
;
; Returns: 0 = invalid radius
; 1 = success
;
; Requires: SSE2
%define r qword [ebp+8] ; value
%define sa [ebp+16] ; pointer
%define v [ebp+20] ; pointer
SseSfpCalcSphereAreaVolume:
push ebp
mov ebp,esp
; Load arguments and make sure radius is valid
movsd xmm0,r ;xmm0 = r
mov ecx,sa ;ecx = sa
mov edx,v ;edx = v
xorpd xmm7,xmm7 ;xmm7 = 0.0
comisd xmm0,xmm7 ;compare r against 0.0
jp .badRadius ;jump if r is NAN
jb .badRadius ;jump if r < 0.0
; Compute the surface area
movsd xmm1,xmm0 ;xmm1 = r
mulsd xmm1,xmm1 ;xmm1 = r * r
mulsd xmm1,[r8_four] ;xmm1 = 4 * r * r
mulsd xmm1,[r8_pi] ;xmm1 = 4 * pi r * r
movsd qword[ecx],xmm1 ;save surface area
; Compute the volume
mulsd xmm1,xmm0 ;xmm1 = 4 * pi * r * r * r
divsd xmm1,[r8_three] ;xmm1 = 4 * pi * r * r * r / 3
movsd qword [edx],xmm1 ;save volume
mov eax,1 ;set success return code
pop ebp
ret
; Invalid radius - set surface area and volume to -1.0
.badRadius:
movsd xmm0,[r8_neg_one] ;xmm0 = -1.0
movsd qword [ecx],xmm0 ;*sa = -1.0
movsd qword [edx],xmm0 ;*v = -1.0;
xor eax,eax ;set error return code
pop ebp
ret
build
g++ -c -m32 main.cpp -o main.o -std=c++11
nasm -f elf32 -o ssescalarfloatingpointspheres.o ssescalarfloatingpointspheres.asm
g++ -m32 -o ssescalarfloatingpointspheres ssescalarfloatingpointspheres.o main.o