top of page

3.4.1 SUMA, RESTA Y COMPARACIÓN

SUMA SIN ACARREO:

Consiste en sumar al contenido del registro "A" un número y obtener el resultado en el registro "A". El indicador de acarreo no se tiene en cuenta para esta operación. Su esquema sería:

 

                                                              A ← A+n

 

SUMA CON ACARREO:

Exactamente igual que la anterior, pero se suma también el indicador de acarreo del registro "F". De esta forma, sepuede incluir en la suma el acarreo procedente de una suma anterior. Su esquema sería:

 

                                                              A ← A+n+CF

 

RESTA SIN ACARREO:

Consiste en restar un número del contenido del registro "A", y obtener el resultado en este mismo registro. El indicador de acarreo no interviene en la operación. Se consideran números negativos los superiores a 127 (7Fh) de la forma que se explicó en el capítulo relativo a los sistemas de numeración; es decir, el número 255 (FFh) se considera "-1", el 254 (FEh) se considera "-2" y así sucesivamente, hasta 128 (80h) que se considera "-128". El paso de 127 a 128 o viceversa se indica poniendo a "1" el flag de "overflow" (P/V) del registro "F". Su esquema sería:

 

 

                                                           A ← A-n

 

RESTA CON ACARREO:

Igual que el anterior, salvo que también se resta el indicador de acarreo (CF) del registro "F". Su esquema sería:

 

                                                         A ← A-n-CF

 

INCREMENTO:

Consiste en sumar uno al contenido de un registro que se especifica en la instrucción. Su esquema es:

 

                                                            R ← R+1

Donde "R" representa un registro cualquiera de 8 a 16 bits. Si se trata de un registro doble (de 16 bits) se incrementa el registro de orden bajo (por ejemplo, en el "BC" se incrementa "C"), y si ello hace que este pase a valer "0", se incrementa también el de orden alto.

 

DECREMENTO:

Es la inversa de la anterior, consiste en restar uno al contenido de un registro. Su esquema es:

 

                                                                R ← R-1

Si se trata de un registro doble, se decrementa el de orden bajo y, si esto hace que pase a valer 255 (FFh), se decrementa también el de orden alto.

Si el registro incrementado o decrementado es de 8 bits, resultan afectados los indicadores del registro "F".

 

 

           GRUPO ARITMETICO DE 8 BITS (SUMA Y RESTA

                          Código  Fuente

                    Hexadecimal

                           Decimal

ADD A,A

87

135

ADD A,B

80

128

ADD A,C

81

129

ADD A,D

82

130

ADD A,E

83

131

ADD A,H

84

132

ADD A,L

85

133

ADD A,n

C6,n

198,n

ADD A,(HL)

86

134

ADD A,(IX+d)

DD,86,d

221,134,d

ADD A,(IY+d)

FD,86,d

253,134,d

ADC A,A

8F

143

ADC A,B

88

136

ADC A,C

89

137

ADC A,D

8A

138

ADC A,E

8B

139

ADC A,H

8C

140

ADC A,L

8D

141

ADC A,n

CE,n

206,n

ADC A,(HL)

8E

142

ADC A,(IX+d)

DD,8E,d

221,142,d

ADC A,(IY+d)

FD,8E,d

253,142,d

SUB A

97

151

SUB B

90

144

SUB C

91

145

SUB D

92

146

SUB E

93

147

SUB H

94

148

SUB L

95

149

SUB n

D6,n

214,n

SUB (HL)

96

150

SUB (IX+d)

DD,96,d

221,150,d

SUB (IY+d)

FD,96,d

253,150,d

SBC A,A

9F

159

SBC A,B

98

152

SBC A,C

99

153

SBC A,D

9A

154

SBC A,E

9B

155

SBC A,H

9C

156

SBC A,L

9D

157

SBC A,n

DE,n

222,n

SBC A,(HL)

9E

158

SBC A,(IX+d)

DD,9E,d

221,158,d

SBC A,(IY+d)

FD,9E,d

253,158,d

 

Tabla de codificación para suma y resta.

 

 

EJEMPLOS:

Al igual que en el capítulo anterior, vamos a hacer algunos programas en código máquina que nos demuestren el funcionamiento de las instrucciones de suma y resta. Al mismo tiempo, iremos cogiendo práctica en la realización y ensamblado de programas en Assembler.

Recomendamos al lector que no se limite a «leer por encima» este curso. Si desea, de verdad, aprender a programar en código máquina, debe seguir el curso encima de una mesa con lápiz y papel en la mano. Intente ensamblar cada programa usted mismo y no se limite a ver cómo lo hacemos nosotros; e incluso, atrévase a escribir sis propias rutinas. No se preocupe si el ordenador se le «cuelga» cincuenta veces, es totalmente normal, una rutina en código máquina rara vez funciona a la primera.

Vamos con el primero de nuestros programas. Se trata de sumar dos números sin acarreo. Utilizaremos un programa en Basic que se encargará de gestionar la entrada de datos, llamar a la rutina en C/M e imprimir los resultados, pero la suma la realizaremos en código máquina.

En principio, necesitamos POKEar los dos números que vamos a sumar en dos direcciones de memoria, desde donde serán leidos por la rutina C/M. Estas dos direcciones serán la 5CB0h (23728) para el primer operando, y la 5CB1h (23729) para el segundo; estas direcciones corresponden a una variable del sistema que no se usa.

Primero escribiremos el programa en C/M y luego el Basic. En Assembler, nuestra rutina podría ser algo así:

 

10

 

LD

 

A,(#5CB1)

20

 

LD

 

B,A

30

 

LD

 

A,(#5CB0)

40

 

ADD

 

A,B

50

 

PUSH

 

AF

60

 

POP

 

BC

70

 

RET

 

 

 

Las líneas 10, 20 y 30 leen los dos operandos desde las posiciones de memoria donde los almacenó el Basic. La línea 40 realizará la suma equivalente a:

 

"LET A=A+B"

Las líneas 50 y 60 transfieren el resultado al registro "B" y los indicadores de estado del registro "F", al registro "C". Recuerde que el registro "BC" es lo que nos devuelve USR cuando retornamos a Basic. Mirando las tablas de codificación, podemos ensamblar el programa:

 

Assembler

Hexadecimal

Decimal

LD A,(#5CB1)

3A,B1,5C

58,177,92

LD B,A

47

71

LD A,(#5CB0)

3A,B0,5C

58,176,92

ADD A,B

80

128

PUSH AF

F5

245

POP BC

C1

193

RET

C9

201

 

Habría sido interesante que el propio lector hubiera ensamblado el programa antes de mirar la tabla anterior. Prométase a sí mismo que la próxima vez lo intentará.

Ya tenemos preparada la rutina en código máquina para sumar dos números. Seamos buenos con los que aún tienen solo 16K, y carguemos la rutina a partir de la dirección 31000.

Ha llegado el momento de pasar al olvidado Basic. El PROGRAMA 1 se encarga de todo. La línea 10 baja RAMTOP, las líneas 20 y 30 introducen en memoria nuestra rutina que se encuentra en los DATA de la línea 40. Las líneas 50 a 100 nos piden los dos operandos y los POKEan en memoria tras comprobar si están dentro de rango.

 

 

PROGRAMA 1.

[Fichero TAP]

La línea 110 llama a nuestra rutina en C/M de forma que, al retornar, el contenido del registro "BC" se almacena en la variable "a". En 120 llamamos a la rutina 3100 que nos pasa el número a binario, esta subrutina es la mism que usábamos en el programa para cambiar de base, del capítulo 3. Las líneas 130 y 140 completan el número con ceros a la izquierda para obtener, de nuevo, 16 bits. Finalmente, las líneas 200 a 220 imprimen en pantalla el valor que contenía el acumulador después de efectuar la suma y el estado de los indicadores en el registro "F". El significado de los indicadores es el siguiente:

 

S

:

Signo

Z

:

Cero

H

:

Semi-acarreo

V

:

Desbordamiento

N

:

Suma/Resta

C

:

Acarreo

Los indicadores marcados "x" presentan un estado indeterminado y no habrá que tomarlos en cuenta.

Una vez que tenga el programa en memoria, pruebe a introducir distintos operandos comprendidos entre 0 y 255. Le sugerimos unos cuantos:

 

17

+

17

=

34

 

15

+

240

=

255

(S)

128

+

128

=

0

(Z,V,C)

127

+

1

=

128

(S,H,V)

3

+

127

=

130

(S,H,V)

 

 

Puede utilizar este mismo programa para la resta cambiando "ADD A,B" por "SUB A,B", es decir, el "128" de la línea 40 por un "144". Haga el cambio y ejecute el programa de nuevo, esta vez restará el segundo operando del primero. Si el segundo operando es mayor que el primero (resultado negativo) el indicador "C" se pondrá a "1" y el resultado aparecerá en complemento a 2.

Ahora vamos a complicar un poco más la cosa, se trata de hacer una rutina qeu permita sumar números superiores a 255. En este caso, usaremos la instrucción "ADC" (sumar con acarreo) para poder tener en cuenta, cuando sumemos un octeto, el acarreo procedente del anterior.

Introduciremos el primer operando en las posiciones 5CB0h (23728) y 5CB1h (23729) (primero el octeto menos significativo y luego el más significativo), y el segundo operando en 5C76h (23670) y 5C77h (23677).

El programa en Assembler puede ser algo como:

 

10

 

AND

 

A

20

 

LD

 

A,(#5C76)

30

 

LD

 

D,A

40

 

LD

 

A,(#5CB0)

50

 

ADC

 

A,D

60

 

LD

 

C,A

70

 

LD

 

A,(#5C77)

80

 

LD

 

D,A

90

 

LD

 

A,(#5CB1)

100

 

ADC

 

A,D

110

 

LD

 

B,A

120

 

PUSH

 

AF

130

 

POP

 

DE

140

 

LD

 

(#5CB0),DE

150

 

RET

 

 

La línea 10 pone a «cero» el indicador de acarreo; se trata de un pequeño "truco" que consiste en realizar un "AND" lógico del acumulador consigo mismo, con lo que el contenido no varía, pero se pone a cero el indicador de acarreo. Más adelante, y dentro de este mismo capítulo, veremos las operaciones lógicas.

Las líneas 20, 30 y 40 cargan los octetos de orden bajo de los dos operandos. La línea 50 los opera (suma) y, si hay acarreo, lo guarda para la suma siguiente. La línea 60 guarda el resultado en "C" (octeto bajo de "BC").

La operación se vuelve a repetir para los octetos altos; las líneas 70, 80 y 90 cargan los operandos. La línea 100 los suma tomando en cuenta el acarreo procedente de la operación anterior. Finalmente, la línea 110 transfiere el resultado al registro "B" (octeto alto de "BC").

La operación ya se ha realizado, tenemos el resultado en "BC" y, por tanto, será lo que obtengamos al retornar a Basic. Ahora sólo nos falta sacar, de alguna forma, el contenido del registro "F" (indicadores) de forma que lo podamos leer desde Basic. Para ello, las líneas 120 y 130 pasan los contenidos de "A" y "F" a "DE" y la línea 140 almacena el contenido de "E" en la posición de memoria 5CB0h (23728), desde donde será leido por el Basic. En esta operación, también se guarda en 23729 el contenido del registro "D" pero, en este caso, no nos interesa.

Sería interesante que el lector intentara, ahora ensamblar por su cuenta este programa, para ello, deberá proceder como hicimos nosotros en el caso anterior. Primero, copie el programa en un papel, ahora, vaya buscando cada instrucción en las tablas ("AND A" se ensambla como A7h ó 167d). A continuación, escriba los operandos numéricos sin olvidar invertir el orden de los octetos y finalmente, acuérdese de ensamblar "RET" como C9h o 201d.

¿Ya lo tiene? Correcto, ahora compruebe si lo que ustes ha ensamblado coincide con lo nuestro.

 

Assembler

Hexadecimal

Decimal

AND A

A7

167

LD A,(#5C76)

3A,76,5C

58,118,92

LD D,A

57

87

LD A,(#5CB0)

3A,B0,5C

58,176,92

ADC A,D

8A

138

LD C,A

4F

79

LD A,(#5C77)

3A,77,5C

58,119,92

LD D,A

57

87

LD A,(#5CB1)

3A,B1,5C

58,177,92

ADC A,D

8A

138

LD B,A

47

71

PUSH AF

F5

245

POP DE

D1

209

LD (#5CB0),DE

ED,53,B0,5C

237,83,176,92

RET

C9

201

No se preocupe si se ha equivocado en algo, sería mucho pedir que el primer programa que ensambla le saliera sin errores. Ahora, con los datos de la tercera columna (donde dice: "Decimal") podemos construir el programa en Basic que introduzca esta rutina en memoria, y la utilice para sumar dos números. Este programa es el listado que aparece con el nombre de PROGRAMA 2. No hace falta que lo copie entero, si lo desea, puede cargar el PROGRAMA 1 y reescribir las líneas 20, 40, 60, 70, 90, 100, 110, 120, 130, 210 y 220 ya que son las únicas que varían.

bottom of page