Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top