Search code examples
assemblymasmx86-16fasmsquare-root

square root of a constant (masm, fasm)


Hy all, I need to declare some constants in an assembly source. In a certain part of the program I need the (integer) square root of one of those constants to limit a loop. My question is: is it even possible?

So far I tried something like:

nMax EQU 200
nLimit EQU sqrt(nMax) ; of course won't assemble... 
                      ; just like nMax^0.5

Of course I could compute it run-time, but it's a nonsense to me... And of course I could do a work-around like:

nLimit EQU 14
nMax EQU nLimit*nLimit

But in this way I can get only perfect squared value of nMax, and that is just not what I need...

Thanks for your help! :)


Solution

  • You could implement one of the many square root algorithms described in this Wikipedia article using macros.

    Here's what I've come up with:

    NEWTON MACRO S, A
      EXITM <(A + ((S) / (A))) / 2>
    ENDM
    
    SQRT MACRO N
      LOCAL V
    
      IF (N LT 0) OR (N GT 4294967295)
        .ERR ; negative or too large argument
        EXITM <0>
      ENDIF
    
      IF (N EQ 0) OR (N EQ 1)
        EXITM <N> ; 0 or 1
      ENDIF
    
      ; calculate approximations of the square root
      ; using Newton's method,
      ; initial approximation is N / 2
    
      V = NEWTON(N, N / 2)
    
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
    
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
    
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
    
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
      V = NEWTON(N, V)
    
      V = NEWTON(N, V)
    
      IF (V * V GT N) OR ((V * V) EQ 0)
        EXITM <V - 1> ; return 1 less
                      ; if the approximation is too big
                      ; or
                      ; if its square overflows to 0
      ENDIF
    
      EXITM <V>
    ENDM
    
    .386P
    
    CODE SEGMENT PUBLIC USE32
    ASSUME CS:CODE
    ORG 0
    
    start:
    ;mov eax, SQRT(-1)
    mov eax, SQRT(0)
    mov eax, SQRT(1)
    mov eax, SQRT(2)
    mov eax, SQRT(15)
    mov eax, SQRT(16)
    mov eax, SQRT(16+9)
    mov eax, SQRT(256)
    mov eax, SQRT(65535)
    mov eax, SQRT(65536)
    mov eax, SQRT(16769025)
    mov eax, SQRT(1073676289)
    mov eax, SQRT(2147483647)
    mov eax, SQRT(2147483648)
    mov eax, SQRT(4294705155)
    mov eax, SQRT(4294705156)
    mov eax, SQRT(4294705157)
    mov eax, SQRT(4294967295)
    ;mov eax, SQRT(4294967296)
    ret
    
    CODE ENDS
    
    END start
    

    Listing file:

    Microsoft (R) Macro Assembler Version 6.14.8444             03/21/13 01:51:53
    sqrt.asm                                                     Page 1 - 1
    ...
     00000000                       CODE SEGMENT PUBLIC USE32
                                    ASSUME CS:CODE
                                    ORG 0
    
     00000000                       start:
                                    ;mov eax, SQRT(-1)
     00000000  B8 00000000          mov eax, SQRT(0)
     00000005  B8 00000001          mov eax, SQRT(1)
     0000000A  B8 00000001          mov eax, SQRT(2)
     0000000F  B8 00000003          mov eax, SQRT(15)
     00000014  B8 00000004          mov eax, SQRT(16)
     00000019  B8 00000005          mov eax, SQRT(16+9)
     0000001E  B8 00000010          mov eax, SQRT(256)
     00000023  B8 000000FF          mov eax, SQRT(65535)
     00000028  B8 00000100          mov eax, SQRT(65536)
     0000002D  B8 00000FFF          mov eax, SQRT(16769025)
     00000032  B8 00007FFF          mov eax, SQRT(1073676289)
     00000037  B8 0000B504          mov eax, SQRT(2147483647)
     0000003C  B8 0000B504          mov eax, SQRT(2147483648)
     00000041  B8 0000FFFD          mov eax, SQRT(4294705155)
     00000046  B8 0000FFFE          mov eax, SQRT(4294705156)
     0000004B  B8 0000FFFE          mov eax, SQRT(4294705157)
     00000050  B8 0000FFFF          mov eax, SQRT(4294967295)
                                    ;mov eax, SQRT(4294967296)
     00000055  C3                   ret
    
     0056                           CODE ENDS
    
                                    END start
    ...