Vistas de página en total

martes, 4 de junio de 2013

RAIZ CUADRADA

Rutina que nos permite sacar la raíz cuadrada.

 No hay mucho que explicar pues la estructura se basa en lo mismo.
  Sabemos que existen coprocesadores con coma flotante en un PC. Pero cuando se enseña ensamblador, hay que tener en cuenta que no todos los procesadores lo tienen. Aprender ensamblador, significa aprende también microprocesadores. En la actualidad, muchos microcontroladores se programan en "C" o "basic", pero quizás por testarudez, a mi me gustan los microprocesadores directos.
   Este es un ejemplo de calculo de la raíz cuadrada por el método recurente, (Algoritmo Babilónico). En este caso solo obtenemos la parte entera, pero en muchos casos de pequeños programas de control nos servirá.
  Si queremos obtener decimales, bastará con multiplicar el número previamente por 100 o 10000 y luego aplicar el algoritmo. Después simplemente descomponemos la parte entera que nos haya resultado. Por ejemplo (Raiz de 3) = (Raiz de 300) /10.
   por ello si queremos un decimal, multiplicamos 3*100=300, aplicamos el algoritmo y nos da 17, y dividiendo por 10, la parte entera es la palrte entera y el resto son los decimales =1.7.

  Es un buen ejemplo de como obtener de forma matemática una función complicada, como la raíz cuadrada, mediante funciones simples.
  El método es el de Newton-Raphson, el cuál se basa en una serie de Taylor, para obtener el valor de una función dada. Si quieres saber más acerca de este método, mira en Wikipedia.
      El valor de una raíz cuadrada lo vamos a ir a aproximando de está forma:
 Para una raiz N, y teniendo una aproximación APROX, mi siguiente aproximación va a ser igual a:

APROX = APROX - (APROX * APROX - N) / (2 * APROX)

Este proceso lo repetimos hasta que la aproximación no cambie, o cuando los cambios de ésta sean mínimos (depende de que tan precisa quieres la raíz). Ej:

N=3
APROX = 1 (El valor inicial no importa)

APROX = 1 - ( 1 * 1 - 3) / (2 * 1) = 2
APROX = 2 - ( 2 * 2 - 3) / (2 * 2 ) = 1.75
APROX = 1.75 - (1.75 * 1.75 - 3) / (2 * 1.75) = 1.73215
YA APROXIMAMOS LA RAÍZ DE 3!!


SQR.ASM
; Copyright (C) 2013  José Ángel Moneo Fernández

;    This program is free software: you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.

;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.

;    You should have received a copy of the GNU General Public License
;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
; codigo
; raiz cuadrada. devuelve en ax el resultado

include main.mac
include math.mac
_modelo exe
_code
rutina _sqr p1

        push bx
        push si
        mov bx,[bp].p1
        mov si,offset n
        mov ax,[bx]       ;COPIAMOS EL DATO PASADO 
        mov [si],ax        ;N=P1
        mov ax,[bx+2]
        mov [si+2],ax
        MOV CX,2          ;MULTIPLICADOR 2
        ;COMIENZA LA ITARACIËN
        mov AX,1       ;APROX=1
    sig:        
        MOV APROX,AX
        MUL CX       ;2*APROX
        MOV AAPROX,AX
        MOV AAPROX+2,DX
        POT APROX,2,APROX2         ;APROX^2
        RESTA APROX2,N,APROX3
        DIVI  APROX3,AAPROX,APROX4
        MOV AX, APROX
        SUB AX, APROX4
        CMP AX, APROX
        jne sig
  
        pop si
        pop bx
        pop bp
        ret
_sqr endp
_data 
APROX DW 0,0
AAPROX DW 0,0
APROX2 DW 0,0
APROX3 DW 0,0
APROX4 DW 0,0
N DW 0,0
_end

16 comentarios:

  1. disculpa podrias orientarme como sacarlo para windows

    ResponderEliminar
    Respuestas
    1. En realidad este algoritmo es muy antiuo, lo hice cuando solo existía MS-DOS y los microprocesadores estaban en 8086. Por lo que no existían coprocesadores. En la actualidad es simplemente una muestra de como realizar un calculo complejo mediante un método muy simple. Pero si lo que se desea es realizar la raíz cuadrada ahora dispones del coprocesador.
      Es una función matemática, por lo que da igual si es windows que si no lo es. Lo impotante es si la necesitas en formato entero o flotante.
      Esta redondea a un entero de 16 bits, y puedes implementarla dentro de tu programa como una subrutina.
      Si usas MASM32, tienes la función IntSqrt para hacer lo mismo pero con una varialbe de 32 bits retornado en EAX.
      Si usas windows puedes usa WINASM como IDE con MASM32.
      Si esto no tw paece suficiene y quieres coma flotante, siempre te queda la opción más socorrida para mi. Tirar de las librerías de C. Si dispones del C de borland, puedes incorporar la librería MATH a tu proyecto y llamar a su función. Yo lo hacía mucho, y por eso siempre compilaba en ensamblador en formato compatible con C.
      Claro que con MS-dos era facil desensamblar el código. Pero como en este caso se trata de una función matemática, independiente del código del sistema, podemos seguir haciéndolo.
      Espero que te haya servido.

      Eliminar
    2. Una cosa más. Si a lo que te referías es a como implementarla en el formato de MASM32, es simple. esta función, tal y como la ves es compatible con el formato "C" y por lo tanto pasa los parámetros a través de pila. Deahí las 3 primeras instrucciones y las dos últimas en las que se recoge el puntero al dato y se salvan y recuperan los registros. Esto está en formato ASM. En TASM 2.0 y superior basta con usar en la definición del procedimiento la directiva "uses". El formato que he puesto aquí es el real y próximo a ensamblador. Pero ahora las directiva de los ensambladores permiten un formato moderno, más estructurado y de más alto nivel, alejandonos del código real. En la entrada http://myassembler.blogspot.com.es/2014/02/emulador-8051-914-ejecuta.html explico la diferencia y la adaptación a los nuevos formatos, aunque en este caso hago una mezcla ya que uso formato Pascal aunque coloco el "_" al comienzo del nombre de la rutina, por lo que realmente la hago compatible "C". Esto es para mantener la compatibilidad con mis rutinas antiguas,
      Un saludo

      Eliminar
  2. Oye amigo una pregunta como uno hace el juego del ahorcado pero con la 8086

    ResponderEliminar
    Respuestas
    1. Buenos días:
      No termino de entenderte. ¿Te refiers como programar un juego de Ahorcado en un micro 8086 o en una PC con 8086, es decir un AT?
      En el blog tinees el programa del ahorcado hecho. http://myassembler.blogspot.com.es/2013/07/ahorcado-55.html
      Está hecho en ensamblador básico del 8086, por lo que simplemente en un AT funciona. No necesita grárficos porque funciona en modo texto.
      Un saludo

      Eliminar
  3. Hola buen dia .Donde podria encontrar un codigo en ensamblador 8086 de un juego de buscaminas?

    ResponderEliminar
    Respuestas
    1. Este comentario ha sido eliminado por el autor.

      Eliminar
    2. Aquí tienes un algoritmo en "C"... pasarlo a ensamblador ya es cosa facil. https://www.youtube.com/watch?v=b5bOLNYyDxg
      Aqui tienes un ejemplo del juego en pantalla de texto.
      https://www.youtube.com/watch?v=pa1kNLQG6jg
      Aquí tienes el algoritmo en Java
      http://www.codigojavaoracle.com/java/codigo-busca-minas-en-java/

      Ahora para pasarlo a ensamblador, es facil, en mis últimas entradas en el blog, y apoyandome en mis propias funciones, explique como ir traduciendo de "C" a ensamblador código. Por lo tanto puedes traducir literalmente el programa de Java a ensamblador.
      Un saludo

      Eliminar
  4. Hola muy buenas tardes disculpe la molestia como puedo implementar este mismo algoritmo pero que tambien nos arroje numeros complejos
    espero no molestarlo mucho y ojala me de un tip o una idea... muy buena tarde

    ResponderEliminar
    Respuestas
    1. Buenos días:
      Esto es algo que no tengo implementado. Pero resulta facil de hacer si miras como se calcula la raíz enesima de un número complejo. El calculo se basa en transforma el número complejo a forma polar.
      En este enlace tienes como hacerlo. http://www.ditutor.com/numeros_complejos/complejos_polar.html

      Si desarrollas el procedimiento, necesitarás crear una función raiz_compleja a que pases dos arguementos, a y b, parte real y parte imaginaria. Esta función necesita llamar a la función potencia y a la raiz_cuadrada. Funciones que si puedes encontrar en el blog, y con ellas calcular el módulo.
      Primero deberás convertir el número a forma polar. Por lo que deberás caluclar el módulo y el argumento.
      Para calcular el módulo solo tendras que hacer la raíz de a2+b2. Por lo que te basta la función raiz y la potencia.
      Para calcular el argumento (alfa) necesitarás el "arctag" de b/a. Esta función no la tengo implementada, por lo que deberás de hacerla. Si tengo tiempo puede que la añada proximamenta junto con la función completa de raiz_compleja, ya que has hecho la pregunta.

      Una vez que tengas z y alfa, solo tienes que calcular la raiz_cuadrada del número complejo mediante le procedimiento de raiz de unmero complejo en forma polar.
      La raiz será un numero complejo cuyo módulo es la raiz del módulo en forma polar. Esto es facil, pues ya tienes el procedimiento de la raíz en ensamblador aquí. El argumento de la raíz serán 2, (argumeto)/2 y (argumeto+2*pi)/2, dado que es la raiz n=2.
      Y ya está. el resultado lo tendrás en forma polar con un módulo y dos argumentos.
      Para calcular el arctang deberás implementar una función con aproximación poligonal. Aquí tienes la del arctang. http://132.248.17.238/calculo2/Aproximacion/a_aproximacion05_d.html.

      Eliminar
    2. Hola soy nuevo en esto del emsamblador, mi ingeniero me dijo que consiga un codigo que resuelva raices cuadradas pero me dijo q ese tipo de codigo solo valdria para windows 95, vi en los comentarios que este codigo fue diseñado precisamente para ser utilizado en ese windows, la cuestion es que ya tengo instalado en una maquina virtual el windows 95 y el turbo assembles 5.0 que para esa version de windows, si escribo tu codigo deberia corres o necesito algo mas, por cierto ya corri algunos progrmas en el turbo assembler usando tasm y todo eso....gracias por su tiempo

      Eliminar
    3. Buenso días:
      Por supuesto que este programa corre en cualquier ordenador. El ensamblador, no depende del sistema operativo, sino del microprocesador, por lo que correrá en cualquier x86.
      Solo la interface con el sistema es lo que cambiará, y para eso es para lo que deberás utilizar un ensamblador u otro. Esto está hecho en TASM 1.0, el cual solo funcionaba para DOS. No tenía soporte para llamar a funciones de Windows. Solo podíamo llamar directamente a kernel de Dos. No porque realmente no pudieramos, sino porque no tenía las librerías y por lo tanto si queríamos hacerlo deberíamos hacerlo con nuestras propias funciones.
      Ahora ya tienes ensambladores que implementan en sus librerías y macros funciones de llamada a funciones de Windows mediante el comando "invoke". Por l otanto ahora si podemos funcionar facilmente en entornos Windows con el ensamblador.
      pero tengamos en cuenta que realmente seguimos trabajando sobre el micro, y por lo tanto la diferencia entre el TASM1.0 y el WnASM o MSAM32, es que estos últimos implementan liberías para las llamadas, que nos ahorran el trabajo de hacerlas nosostos mismos.
      Igualmente si ves este código ves u monton de instrucciones previas al código principal, que ahora no son necesarias en TASM 5.0, de hecho alguna no son necesarias ni en TASM1.0. Pero este código podría ejecutarse en ASM. Es decir en el primer ensamblador. Pues no usa directivas de compilación complejas. Más adenate en el blog implemento las directivas de compilación de TASM 5.0 en macros. Para demostrar que realmente no son más que trucos para facilitar la programación, pero que realmente siempre estamos generando lo mismo.
      Si desensamblases el código del programa que compiles... verías en codigo máquina el código como se muestra en este programa.
      Resumiendo. Si que te sirve. Si vas a utilizar un ensamblador en sindows como WinASM o MASM32, cambiará la forma de plantear el programa debido a los invoques y librerías de windows, pero a la hora de realizar la raíz será igual.
      Una cosa más, es que este código está hecho para 8086. Es decir para un micro de 16 bits. Por eso, para realizar las sumas, restas, divisiones y potencias en 32 bits, debo de apoyarme en funciones propias. Si tu en cambio utilizas, un micro de 16 o 32, puedes substituri las funcones SUB,DIV por sus equivalentes en ensamblador, las cuales ya operarán con las variables directamente. O implementarlas según lo he hecho yo para utilizar variables más grandes.
      Así. yo en 16 bits las hago para manejar variables de 32. Tu en 32 las puedes hacer para manejar variables de 64. El núcleo de la función empieza en "MOV CX,2" y termina en "jne sig". El resto pertenece a la comunicación de parámetros y a la salvaguarda de estos en la variable N para operar. La función devuelve en AX el resultado. Un saludo

      Eliminar
  5. que tal amigos, estoy intentando hacer una raiz cuadrada en Masm32 pero no se como hacerlo, ya intente con la funcion intsqrt pero me tira error, no se si necesite llamar una libreria o algo asi, les agradeciera su ayuda

    ResponderEliminar
    Respuestas
    1. Hola que tal Alex: Yo no he compilado en masm32. Así que, no me conozco todas sus librerías. solo algunas. Además muchas veces tiro de código propio. El algoritmo de esta función es igualmente válido para masm32. En su caso además el mismo algorimo hecho con registro de 32 bits, realizará una operación ya en 64 bits.
      En esa función uso funciones matemáticas propias como POT. pero en el blog, ADD, etc para operar con 32 bits en un micro de 16. Convirtiendolas, en masm32 el mimo algoritmo permite operar con variables de 64 bits mediante las operaciones de 32 bits del micro.

      Eliminar
  6. Hola, mi duda es en este programa, saca solamente la raíz cuadrada de un número? Tenia entendido que el método de Newton raphson saca la raíz de una función derivada. Y la otra es, será muy complicado llevar este código del tasm al nasm de linux? Saludos

    ResponderEliminar
    Respuestas
    1. Hola Genaro:
      No saca la raíz cuadrada completa. solo obtienes la parte entera. Es realmente una aproximación a la raíz cuadrada. Es un ejemplo de programación de una función matemática, y se puede usar en operaciones o funciones simples. Yo nunca me he molestado en hacer un programa de una operación matemática muy compleja... no tiene sentido, para ello ya las tienes hechas. Ahora los ensambladores ya tienen librerías de funciones completas matemáticas, y antes, siempre podías recurrir al "C".
      En los tiempos en que no existían las librerías que ahora puedes conseguir en el ensamblador que uses, cuando se trabajaba en MS-Dos, con en ASM o el TASM, mi solución era muy simple. Dado que había "C" desde la versión 1.0 en el año 90, yo lo que hacía era sacar la función matemática que deseaba de la librería .LIB del C y me la pasaba a mi librería de ensamblador. A partir de ahí ya disponía de esa función. Así que nunca necesité molestarme en hacer una raíz cuadrada completa. Este programa era un ejemplo sencillo para mostrar como funcionaba una función matemática.
      En cuanto a la segunda pregunta. No es complicado pasar de un lenguaje a otro, Aunque si puede ser laborioso, ya que cambian las nomenclaturas y las formas de declarar segmentos.
      Este problema es el que siempre he tenido con los lenguajes, cada vez que sacan uno, o una versión, el código que tienes ya no vale. Por eso, en este blog verás que yo no usaba nunca las funciones que iba añadiendo el compilador TASM según iba subiendo de versión. En realidad, lo que yo hacía, de antemano, era crearme macros para simplificar el trabajo. Esto luego lo implementaban las nuevas versiones, pero ya no me valía la pena hacer el esfuerzo de adaptarme, ya había encontrado la solución para hacerlo con la versión 1.0.
      Para traducir del TASM, puedes crearte macros en NASM que sigan la nomenclatura del código TASM. Así cuando montes el código TASM para compliar con NASM, el compilador interpretará el antiguo código como si fueran las macros, y lo decodificará. Pero eso es algo laborioso. Y siempre habrá algunas cosas que deberás cambiar a mano.
      Ahora yo programo más microcontroladores que PC, así que ya no me vale la pena el esfuerzo de conversión a NASM.
      Un saludo

      Eliminar

Si tienes algún comentario, duda o sugerencia, o si quieres aportar algún código creado a partir de las librerías expuestas aquí, por favor, indícamelo.