Reputation: 1953
I am trying to calculate 2^(-n). My approach is to calculate 2^n using a loop, then divide 1 by that number. I tried to make this as readable as possible I could be dumb and there's a much easier way...
(I'm doing calculations with both highs and lows of registers for vector processing later)
formatfloatinput db "%lf", 0
two dq 2.0 ;a variable to be used later
one dq 1.0 ;a variable to be used later
mov r15, 1 ;counter for the loop
;scanf has been called, asking user to input "n"
pop r12 ;r12 will contain "n"
;===== Copy some data to xmm registers=========================
push r12 ;push r12 onto stack
push r12 ;push r12 onto stack
movupd xmm5, [rsp] ;move both values into "high" and "low" of xmm5
pop rax ;reverse push
pop rax ;reverse push
push qword [two] ;push 2 onto stack
push qword [two] ;push 2 onto stack
movupd xmm6, [rsp] ;push 2 into "high" and "low" of xmm6 for the "2^n" calculation
pop rax ;reverse push
pop rax ;reverse push
push qword [one] ;push 1 onto stack
push qword [one] ;push 1 onto stack
movupd xmm7, [rsp] "push 1 into "high" and "low" of xmm7 for division later"
pop rax ;reverse push
pop rax ;reverse push
;================================================================
movupd xmm4,xmm6 ;places 2's into xmm4. this is to multiply xmm6 with later in the loop
beginExponent: ;begin loop for calculating exponent
mulpd xmm4,xmm6 ;multiply 2x2
inc r15 ;increment counter
cmp r12,r15 ;is the counter the same as the user specified "n"?
jne beginExponent ;if not, go up and loop again
divpd xmm7,xmm4 ;divide 1 by (2^n)
movsd xmm0,xmm7 ;mov "just high or low, can't remember" of xmm7 into xmm0
mov qword rdi, formatfloatinput
mov qword rax, 1
call printf
it just hangs and outputs nothing.
Upvotes: 1
Views: 2733
Reputation: 58772
See wikipedia for the details of standard floating point format.
The double precision has a leading sign bit (0 for positive), then 11 bits of exponent biased by 1023, finally 52 bits of mantissa with an implicit leading 1. The number 2^-n
will have 0 sign and 0 mantissa (because the mantissa value is 1 but the leading 1 is omitted) and the exponent will be 1023-n
. It's easy to create this pattern by negation, addition and shift:
section .data
formatfloatinput db "%lf", 0
section .text
global main
extern printf
main:
push rbp ; maintain stack alignment
mov r12, 3 ; fetch input into r12 here, use 3 as example
neg r12 ; get -n
add r12, 1023 ; add the double-precision exponent bias
shl r12, 52 ; shift into place
; sign and mantissa are zero, we are done
movq xmm0, r12
mov rdi, formatfloatinput
mov eax, 1
call printf
xor eax, eax
pop rbp
ret
By the way, even though your code isn't optimial, it did seem to work for me after I have added the missing pieces.
Upvotes: 1