# [Duda] sobre la instrucción subwf



## lgonzalez (Feb 22, 2010)

Hola a todos,
Soy nuevo en este foro y quisiera saber si me podéis aclarar una duda (básica) que tengo respecto de la instrucción subwf (en mi caso en el 16F84A).
Necesito un pequeño algoritmo para comparar 2 números de 8 bits sin signo (todos los bits indican magnitud, por ejemplo comparando:0x82 y 0x7F). 
Como el micro no tiene instrucciones de comparación, he usado la instrucción subwf para ello, pero no me funcionó como esperaba. 
Al consultar en el manual encontré que el rango de números que es capaz de utilizar esta instrucción es [0,127]. Lógicamente el 0x82 cae fuera de este rango.
Hay alguna manera sencilla de implementar la comparación de 2 números de 8 bits en el rango [0,255]? Estoy haciendo algo mal? Os agradecería si me pudierais ayudar.
Un saludo a todos


----------



## Chico3001 (Feb 22, 2010)

te andas confundiendo.... el 0 a 127 es el numero de registro... no el contenido del registro... subwf puede restar 2 numeros de 0 a 255 sin problemas

El modo para usarlo como comparador es como sigue:

movlw 0x82
movfw registro1
movlw 0x7F
subwf registro1,w

el resultado de la comparacion esta en 2 banderas.... si Z esta activo quiere decir que ambos numeros son iguales y por lo mismo el resultado fue cero

Si C esta activo es que el resultado es positivo y F>W, si C es cero entonces el resultado fue negativo y F<W


----------



## lgonzalez (Feb 23, 2010)

Muchas gracias! Tienes toda la razón: debo de haber hecho algo mal cuando lo probé.

De todas maneras me queda una duda.
El manual pone en la instrucción: "Status Affected: C, DC, Z"
El hecho de que Z se ponga a 1 si los números son iguales es evidente, pero (para mi) no lo del flag de carry C. Estos detalles ¿dónde los puedo ver/aprender si el manual no lo especifica?

Un saludo,


----------



## Meta (Feb 23, 2010)

Mira aquí.
http://unbarquero.blogspot.com/2008/07/subwf.html

Este es sumar, pero puedes bucar ejemplo de restar.
http://unbarquero.blogspot.com/2008/07/baseline-progbasico-8.html

Instrucciones.
http://unbarquero.blogspot.com/2008/07/set-de-instrucciones-mid-range-pic.html


----------



## lgonzalez (Feb 23, 2010)

Muchas gracias!


----------



## jjfonsecaz (Feb 24, 2010)

Compañero Igonzalez.

El carry se activa, por la razon de como se realiza la operacion de resta.
una ALU generalmente tiene implementado un sistema de suma de n- bits por lo que si quieres implementar la resta es exactamente lo mismo pero usando un complemento a 2 de el segundo registro. ejemplo:
restar 1010 con 1010 lo que en decimal ceria 10-10 con una alu de 4 bits.
en el primer registro de la ALU pones 1010 y en el segundo registro el complemento a 2 de 1010 el cual seria 0110.
si sumas ambos tienes el resultado.
1010+0110= 1,0000 donde el bit mas significativo corresponde al carry.
Hay que revisar las bases de la aritmetica binaria.
Saludos.


----------



## lgonzalez (Feb 25, 2010)

Compañero jjfonsecaz,

Esto me vino muy bien. Muchas gracias, hace tiempo que no toco nada de esto. 

Ahora en mi ejemplo original sería:
a) 0x82 - 0x7F:
0x82=1000 0010
0x7F=0111 1111 -> compl. a 2: 1000 0000 + 0000 0001 = 1000 0001

Al restar (sumando):
1000 0010
1000 0001
----------
0000 0011 (OK!) y C=1, tal como decía Chico3001, porque 0x82>0x7F, OK?

b) 0x7F-0x82:
0x7F=0111 1111
0x82=1000 0010 -> compl. a 2: 0111 1101 + 0000 0001 = 0111 1110

Al restar (sumando)
0111 1111
0111 1110
----------
1111 1101 (es -3 en complem. a 2. OK!) y C=0, tal como decía Chico3001, porque 0x7F<0x82

Parece que todo funciona perfectamente...Pero ahora me asalta de nuevo la duda por un detalle: En el ejemplo a) El resultado era +3 porque obviamente 0x82 es mayor que 0x7F. Pero esto es tan obvio? Al fin de cuentas el bit 7 de 0x82 es 1, indicando un número negativo, tal y como se refuerza en el resultado del ejemplo b): 0xFD.

Entonces, cómo es todo esto: el resultado de la operación aritmética se debe analizar siempre mirando el valor de C?

Espero no aburrir, pero tengo dudas.

Un saludo,


----------



## jjfonsecaz (Feb 25, 2010)

Pues realmente depende del rango que estes manejando
Si usas un rango de valores con signo El bit 7 te indicaria cuando un numero es negativo, pero cuando quieres usar el rango de 0 a 255 tienes entonces tienes que considerar el carry ejemplo:
si consideras puros numeros enteros la siguiente operacion seria:
240 - 1 = 239
11110000 - 00000001 = 11101111; y el carry es 1 con lo que el resultado es positivo.

Pero si estas considerando numeros con signo entonces eso no es igual ya que tendrias.
11110000 - 00000001 = 11101111;
que seria
-16-1 = -17
ya que el bit 7 te indica el signo, por lo cual no necesitas revisar el carry.
Saludos.


----------



## Meta (Feb 25, 2010)

En el MPLAB abajo te pone cuando el Carry está activo.

C=1
c=0

Es fácil de entender. Si l aC está en mayúscula es 1, si está en minúscula es 0.


----------



## lgonzalez (Feb 28, 2010)

Muchas gracias a todos por la ayuda. Todo va perfectamente ahora.
A propósito: 
1)
he visto que un par de instrucciones no funcionan bien con el registro W:

btfss W,7; no funciona 

Para que funcione hay que usar un registro auxiliar:

movwf AUX
btfss  AUX, 7

No es la primera vez que el registro W se comporta de modo raro. Esto es así? Hay algún documento de "undocumented 16F84A"?

2)
Otra cosa. Hasta ahora estaba usando el MPASM incorporado en el programador. Me bajé el IDE completo para usar el simulador, porque hasta ahora era todo prueba y error y estoy un poco cansado...
En fin, mi programa tiene un archivo .asm y 3 archivos .inc. El caso es que cuando le doy al "Build" el MPASM no reconoce ciertas variables declaradas en los .inc y no compila. 
En el MPASM del programador (que tiene pocas opciones) esto no ocurre. Tenéis idea de dónde puedo estar fallando??


----------



## Meta (Feb 28, 2010)

¿Puedes poner el código fuente?

http://unbarquero.blogspot.com/2008/07/baseline-progbasico-4.html


----------



## jjfonsecaz (Feb 28, 2010)

compañero Igonzalez.

Considero que deberias de leer con mas detenimiento los manuales. En este caso, el manual del PIC16F84A:
http://ww1.microchip.com/downloads/en/DeviceDoc/35007b.pdf
Ya que el mismo dice en la pagina 37, que la instruccion que comentas trabaja sobre los registros, no sobre el Acumulador (W) por lo tanto esta demas la razon del por que no funciona esta instruccion.
No recuerdo si algun PIC tenga mapeado el acumulador como un registro de trabajo, en cuyo caso si funcionaria. Pero no lo es en esta ocasion.
Si revisas la pagina 3 del manual de este pic, notaras la diferencia entre los registros de trabajo y el Acumulador y por ende por que no funciona esa instruccion.
En la pagina 6 del mismo notaras que no se encuentra mapeado el acumulador en los registros.
Con respecto a tu programa, si nos pudieras colocar el codigo seria mas facil ayudarte.

Saludos.


----------



## lgonzalez (Mar 1, 2010)

Hola a todos,
Efectivamente, tienes toda la razón (no cuento más que con los Domingos para probar unas pocas cosas). Di por hecho un mapeo que no existe; de todas formas la solución es super sencilla.

Cambiando al tema Ensamblador, como os comentaba, estaba intentando compilar el programa desde la suite IDE (para poder simular) y me salen los mensajes de este t¡po:

Error[113]   F:\LEONARDO\GB\WORK\PROJECT\MRI_4.ASM 348 : Symbol not previously defined (AARGB1)
Error[113]   F:\LEONARDO\GB\WORK\PROJECT\MRI_4.ASM 350 : Symbol not previously defined (AARGB0)
Error[113]   F:\LEONARDO\GB\WORK\PROJECT\MRI_4.ASM 352 : Symbol not previously defined (AEXP)
Veréis la estructura del proyecto en el fichero adjunto.

La cabecera del programa .asm es:
;----------------------------------------------------------------------------------
; Author: Leonardo González                                                                                     
; Date: 13/02/2010                                                                                                                     
; Version: 0.1                                                                                                                               
; Title: MRI4                                                                                       
;                                                                                                                                                   
; Description:                                                                                                                                                                                         
;----------------------------------------------------------------------------------

	#include p16f84A.inc
	#include DEV_FAM_lga.inc
	#include math16.inc

W_TEMP	equ	0x36		; Registro temporal del W durante la interrupción
S_TEMP	equ	0x37		; Registro temporal del STATUS durante la interrupción
CNT_NEG0	equ	0x38		; Cuenta de pulsos negativos
CNT_TOT0	equ	0x39		; Cuenta de pulsos totales. Se decrementa cada vez que el TMR0 interrumpe.
CNT_NEG1	equ	0x3A		; Cuenta de pulsos negativos 
CNT_TOT1	equ	0x3B		; Cuenta de pulsos totales. Se decrementa cada vez que el TMR0 interrumpe. 

N 		equ 0x21		; Indice del coeficiente kx
INDTBLX	equ	0x22		; Indice dentro de la tabla: INDTBLX=3x(N-1) + 1, 2, 3
INDTBLY	equ	0x23		; Indice dentro de la tabla: INDTBLY=3x(Nmax-1)- INDTBLX + 1, 2, 3

Kx1 		equ 0x24
Kx0 		equ 0x25
KxEXP 	equ 0x26 		; 8 bit biased exponent for argument A

Ky1 		equ 0x27
Ky0 		equ 0x28
KyEXP 	equ 0x29 		; 8 bit biased exponent for argument B

...

Y dentro de los .inc están las definiciones que el compilador reclama (como os digo con el MPASM del programador Velleman compilo perfectamente). Math16.inc tiene las definiciones de unas rutinas de punto flotante (que podéis ver en los mjes. de error: AARGB0, etc. En fin, todas estas variables están bien declaradas, pues de otro modo el MPASM del programador daría error, y sin embargo compila bien)

Bueno, no os aburro más, tengo que leerme un tutorial bueno, y la verdad es que no tengo tiempo.

Saludos!


----------

