You are on page 1of 16

Programación avanzada en Ensamblador

Cesáreo Fernández Martínez


Álvaro Sánchez Miralles

Tareas que realiza el programa ensamblador


• Traduce el fuente .a66 a código máquina .obj
– mov Rx, Ry Escribir
F0 x y programa en
el editor

Código de Número de
instrucción GPR Fichero *.a66

– mov reg, #dato


E6 reg dato
Ensamblador

Código de Número de Número de


instrucción SFR 16 bits Código máquina Librerías
Fichero *.obj .obj

• Resuelve los valores de las etiquetas


– Lleva un contador direcciones en memoria de las Enlazar
instrucciones. La etiqueta toma el valor de la
Código máquina
dirección de memoria de la instrucción asociada Fichero *.

Ejecutar

Título Presentación - 2

1
Ejemplo de ensamblador
• Las etiquetas facilitan la programación en ASS

MOV R0,#0
Etiquetas (op) MOV 0xfa00,R0
MOV R0,#1 ; r0 (i)
MOV R1,#1 ; auxiliar
bucle: CMP R0,#5 ; if i>N
JMPR cc_sgt,fin ; then goto ´fin’
ADD 0xfa00,R1 ; j += 1
ADD R0,#1 ; i += 1
JMPS bucle ; = jmpr cc_uc,
fin:

Instrucción Operandos Comentarios (opcional)

Título Presentación - 3

Números con y sin signo


• Un número negativo es el que sumado a el mismo positivo da
como resultado 0. ¿Cómo hacerlo?
– Ejemplo en 16 bits: 0xFFFF + 0x0001 = 0x0000 (ya que el resultado
no cabe en 16 bits)

Número + Número -
0x0001 (1) 0xFFFF (-1)
0x0002 (2) 0xFFFE (-2)
0x0003 (3) 0xFFFD (-3)

– Ejemplo en 8 bits: 0xFF + 0x01 = 0x00 (ya que el resultado no cabe


en 8 bits)

Título Presentación - 4

2
Números con y sin signo
• Aritmética en “Coma fija complemento a 2”
– Números positivos: bit más significativo (bit 15) a 0.
– Números negativos: bit más significativo (bit 15) a 1.

número _ negativo = 2 número _ de _ bits − número _ positivo


0 xFFFE = 216 − 0 x0002
• Overflow (Flag V del registro PSW)
– Cuando operando dos números positivos se obtiene un número
negativo
0x7FFF + 0x0001 = 0x8000 (“Overflow”; V = 1)
0x7FFE + 0x0001 = 0x7FFF (V = 0)
• Carry (Flag C del registro PSW)
– Cuando operando dos números no cabe el resultado en 16 bits
0x8000 + 0x8000 = 0x0000 (“Carry”; C = 1)
0x8000 + 0x7FFF = 0xFFFF (C = 0)

Título Presentación - 5

Números con y sin signo


• ¿Cómo se calcula un número negativo?
– En decimal se aplica la formula ¿cual es el negativo de 2 en 8 bits?

número _ negativo = 2 número _ de _ bits − número _ positivo


254 = 28 − 2
– En binario o hexadecimal (0000 0010 B)
• Se hace el complemento a 1 del número (1111 1101 B)
• Se le suma uno (1111 1110 B)
– El número negativo de 2 en 8 bits es el 254 ó 0xFE ó 11111110B.
• Como el micro sólo entiende de 0's y 1's cuando hay un
número en la memoria (por ejemplo 1111 1110) ¿Qué
significa?
– Si se interpreta con signo es el número negativo de 2 ó -2
– Si se interpreta sin signo es el número 254
– Depende del programador y de las instrucciones que use el que le da
una interpretación u otra.

Título Presentación - 6

3
Instrucción MOV.
• Directo a registro
– MOV r0,r1 ; R0 <- R1
• Inmediato
– MOV r0,#3 ; R0 <- 3 (no olvidar # !)
• directo a memoria
– MOV r0,0fa00H ; R0 <- Mem[fa00 H]
• Indirecto (“normal”, post-incremento, pre-decremento)
– MOV r0,[r1] ; R0 <- Mem[R1] (R1 Puntero)
– MOV r0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 2
– MOV r0,[-r1] ; R1 <- R1 - 2, R0 <- Mem[R1]
– MOV r0,[r1+#4] ; R0 <- Mem[R1+#4]
• A nivel de byte
– MOVB rl0,#3 ; R0 <- 3
– MOVB rh0,[r1+] ; R0 <- Mem[R1], R1 <- R1 + 1

Título Presentación - 7

Mov con extensión de signo.


• Extensión de signo
– MOVBZ
• Carga el byte en parte baja, extiende (a los 16 bits) con ceros

MOVBZ R0,#0xFF ; r0 <- 0x00FF


MOVBZ R0,#-1 ; r0 <- 255 no respeta el signo

– MOVBS
• Carga el byte en parte baja, extiende (a los 16 bits) con bit de
signo
MOVBS R0,#0xFF ; r0 <- 0xFFFF
MOVBS R0,#-1 ; r0 <- -1 respeta el signo

8 bits con 8 bits sin 16 sin 16 bits exten-


signo signo extender signo diendo signo

0xFF -1 255 255 (0x00FF) -1 (0xFFFF)


0x80 -128 128 128 (0x0080) -128 (0xFF80)

Título Presentación - 8

4
Programando con etiquetas (para datos)
• La pseudoinstrucción EQU permite dar nombres a los
distintos datos de programa
– Variables (posiciones de memoria, ej 0fa00h)

var1 equ 0fa00h


var2 equ 0fa01h

MOVB RL0,var1
MOVB RL1,var2
MOVB var2,RL0
MOVB var1,RL1

– Constantes ¿Cómo se sabe si el 1 es una


constante o una variable?
el_uno equ 1

MOVB RL0,#el_uno

Título Presentación - 9

Little/Big Endian
• En la operación (16 bits)
– mov r0,0fa00H ; R0 <- Mem[fa00 H]

• Little-Endian: el byte (8 bits) almacenado en la posición


0fa00H
– Va a la PARTE BAJA del REGISTRO (a RL0)
– El byte almacenado en 0xfa01 va a la PARTE ALTA (RH0)

• El C167 es un Little-Endian

• En los procesadores MOTOROLA


– Al revés
– En ambos casos NO se permite extraer un word (16 bits) de una
dirección impar de memoria.

Título Presentación - 10

5
Instrucciones aritméticas
• Instrucción ADD
– Suma a nivel de word (16b)
– Ej: ADD Rx, op ; Rx <- Rx + op

MOV R0,#0x0001 ¿Qué vale R0?


MOV 0xFA00,R0
ADD R0,#0x0009
ADD 0xFA00,R0

• Instrucción ADDB
– Suma a nivel de byte

MOV R0,#0x0001
ADDB Rh0,#0x01

¿Qué vale R0?

Título Presentación - 11

Instrucciones aritméticas
• Instrucción SUB
– Resta a nivel de word (16b)
– Ej: SUB Rx, op ; Rx <- Rx - op

MOV R0,#0x01FF
MOV 0xFA00,R0
¿Qué vale R0?
SUB R0,#0x0009
ADD 0xFA00,R0

• Instrucción SUBB
– Resta a nivel de byte

MOV R0,#0x01FF
SUBB Rh0,#0x01

¿Qué vale R0?

Título Presentación - 12

6
Instrucciones aritméticas
• Instrucción NEG
– Complemento a dos de un número
– Un cambio de signo
– NEG Rx ; Rx <- 0 - Rx

MOV R0,#0x01FF
NEG R0 ¿Qué vale R0?

• Instrucción NEGB
– Cambio de signo a nivel de byte

MOV R0,#0x01FF
NEGB Rl0

¿Qué vale R0?

Título Presentación - 13

Instrucciones aritméticas
• Instrucción MUL
– Multiplica dos números con signo
– Resultado en 32 bits en el registro MD
• MDL: Parte baja de MD (16 bits).
• MDH: Parte alta de MD (16 bits).
– MUL Rx, Ry ; [MDH, MDL] <- Rx * Ry

• Instrucción MULU
– Multiplica dos números sin signo

MOV R0,#0xFFFF
MOV R1,#0xFFFF
MUL R0,R1
MOV R2,MDL
MOV R3,MDH ¿Qué vale MDL, MDH,
MULU R0,R1 R2 y R3?

Título Presentación - 14

7
Instrucciones aritméticas
• Instrucción DIV
– Divide dos números (MDL y un GPR) con signo
– Resultado en dos registros de 16 bits
• MDL: Almacena el cociente de la división (16 bits).
• MDH: Almacena el resto de la división (16 bits).
– DIV Rx ; MDL <- MDL / Rx MDH <- MDL mod Rx

• Instrucción DIVU
– Divide dos números sin signo

MOV R3,#0xFFFF
MOV MDL,R3
MOV R0,#0x0001
DIV R0
MOV R1,MDL
MOV R2,MDH ¿Qué vale MDL, MDH,
MOV R3,#0xFFFF
R1 y R2?
MOV MDL,R3
DIVU R0

Título Presentación - 15

Instrucciones lógicas
• Instrucción AND
– Realiza un AND bit a bit de dos números
– Ej: AND Rx, op ; Rx <- Rx and op

MOV R0,#0x0001
¿Qué vale R0?
AND R0,#0x0009

– Sirve como máscara: una especie de filtro para seleccionar únicamente


ciertos bits de un registro

Se quiere poner el bit


AND R0,#0xFFFD 1 del registro R0 a 0.
O lo que es lo mismo,
se seleccionan el resto
de bits del registro R0

Título Presentación - 16

8
Instrucciones lógicas
• Instrucción OR
– Realiza un OR bit a bit de dos números
– Ej: OR Rx, op ; Rx <- Rx or op

¿Qué vale R0?


MOV R0,#0x0001
OR R0,#0x0009

– Sirve como máscara: una especie de filtro para seleccionar únicamente


ciertos bits de un registro

Se quiere poner el bit


Se quiere poner el bit OR R0,#0x0002 1 del registro R0 a 1.
1 del registro R0 igual O lo que es lo mismo,
que el bit 1 del se seleccionan el resto
registro R1. de bits del registro R0

AND R0,#0xFFFD ; se pone a 0 el bit 1 de R0


MOV R2,R1 ; para no modificar R1
AND R2,#0x0002 ; se selecciona el bit 1 de R2
OR R0,R2 ; R0.1 = R2.1 = R1.1

Título Presentación - 17

Instrucciones lógicas
• Instrucción XOR
– Realiza un XOR bit a bit de dos números Si se usa con 0xFFFF
– Ej: XOR Rx, op ; Rx <- Rx xor op se cambian todos los
bits de un registro

MOV R0,#0x0101
XOR R0,#0xFFFF ; R0 <- 0xFEFE

• Instrucción CPL
– Realiza el complemento a 1 de un número
– CPL Rx ; Rx <- complemento a 1 de Rx

MOV R0,#0x0101
CPL R0 ; R0 <- 0xFEFE

Título Presentación - 18

9
Desplazamientos
• SHL (SHift Left) o SHR (SHift Right)
– SHL Rx, #num
• Desplaza num veces a la izquierda los bits de Rx
– SHL Rx, Ry
• Desplaza a la izquierda Rx, el número de posiciones indicadas en
Ry
– Introduce ceros por la derecha
MOV R0,#0x0001 ¿Qué vale R0?
SHL R0,#9
Se quiere poner el bit
1 del registro R0 igual
0 Rx 16 bits C que el bit 0 del
registro R1.

AND R0,#0xFFFD ; se pone a 0 el bit 1 de R0


MOV R2,R1 ; para no modificar R1
AND R2,#0x0001 ; se selecciona el bit 0 de R2
SHL R2,#1 ; el bit 0 pasa a ser el bit 1
OR R0,R2 ; R0.1 = R2.1 = R1.1

Título Presentación - 19

Rotaciones
• ROL (ROtate Left) o ROR (ROtate Right)
– ROL Rx, #num
• Desplaza num veces a la izquierda los bits de Rx
• Rota los bits usando el bit de carry C
– ROL Rx, Ry
• Desplaza a la izquierda Rx, el número de posiciones indicadas en
Ry
• Rota los bits usando el bit de carry C

Rx 16 bits C

MOV R0,#0x8001
¿Qué vale R0? ROL R0,#9

Título Presentación - 20

10
Control de flujo de programa. Saltos.
• Comparación
– Ej: CMP Rx, Ry ; Actualiza PSW como una resta Rx - Ry
• Saltos
– JMPR va precedido de CMP (compara), de forma que después de
comparar se realiza el salto según una condición.

CMP R0,R1
JMPR cc_ugt,next ;si R0 > R1
....
next:
– JMPR:
• Jmpr cc_eq, dir (equal, salta si igual)
• Jmpr cc_uc, dir (unconditional, salta siempre)
• Jmpr cc_ne, dir (not equal, salta si no igual)
• Jmpr cc_ugt, dir (unsigned greater than)
• Jmpr cc_sgt, dir (signed greater than)
• Jmpr cc_ule, dir (unsigned less or equal)
• ...

Título Presentación - 21

Saltos “a nivel de bit”


• Salto si el bit está a 1
FFFF
– JB bit, dir
SFRs acceso bit a bit
• Salto si el bit está a 0 SFR’s FF00

– JNB bit, dir SFRs


FE00
• Consideraciones
Acceso bit a bit
– Sólo en zonas bit a bit FD00
– No necesitan CMP antes GPRs
FC00
RAM

STACK

F600

JB C,next ;si C = 1 salta next


....
next:

Título Presentación - 22

11
“move” a nivel de bit
• Poner un bit a 1
– BSET bit ; bit = 1
;activa bit 1 del P2
• Poner un bit a 0 BSET P2.1 ;
– BCLR bit ; bit = 0 BCLR C ; Carry = 0
BMOV V,C ; V=C
• Mover un bit
– BMOV bit1, bit2 ; bit1 = bit2
• Lógicas (a nivel de bit)
– BAND bit1, bit2 ; bit1 <- bit1 and bit2
– BOR bit1, bit2 ; bit1 <- bit1 or bit2
– BXOR bit1, bit2 ; bit1 <- bit1 xor bit2
• Consideraciones
– Sólo en zonas bit a bit

Título Presentación - 23

C y Ensamblador
• if ( )
– Alto nivel

if (a == b)
...;
else
...;

– Ensamblador
MOV R0,a
CMP R0,b
JMPR cc_ne,else
; condición if
..
JMPR cc_uc,endif
else: ; condición else
..
endif:

Título Presentación - 24

12
Bucles
• for ( )
– Alto nivel

for (i=START; i <= STOP; i++){


a = STOP - i;

– Ensamblador

MOV R0,#START ; r0 (i)


MOV R1,#STOP
SUB R1,R0 ; r1 (STOP-START)
JMPR cc_uc,test
for: MOV a,R1
SUB R1,#1
ADD R0,#1 ; i += 1
test: CMP R0,#STOP
JMPR cc_slt,for ; i <= STOP
next:

Título Presentación - 25

Otro ejemplo
• while ( )
– Alto nivel

i = 0;
while (i<10) {
a[i] = i; i += 1;
}

– Ensamblador
MOV R0,#0 ; R0 es i
MOV R1,#1 ; es el incremento de i
MOV R2,#0xfa00 ;R2 almacena la dirección de memoria de a
otro: CMP R0,#10
JMPR cc_sge,next
MOV [R2],R0
ADD R0,R1
ADD R2,#2
JMPR cc_uc,otro
next:

Título Presentación - 26

13
Directivas. “Pseudoinstrucciones”
• Las directivas a usar en el ”while” anterior :

$nonsegmented
maxdata equ 0x10 ; constante
Sección de datos D100
en dirección 0x200 D100 section data at 200H
j dsw 10 ; array de datos
D100 ends

ej section code at 300H


ej1 proc NEAR
MOV R0,#0
MOV R1,#1
MOV R2,#j
Procedimiento ej1 otro: CMP R0,#maxdata
JMPR cc_sge,next
MOV [R2],R0
Sección de código ej ADD R0,R1
en dirección 0x300 ADD R2,#2
JMPR cc_uc,otro
next: NOP
ej1 endp
ej ends
end Final de programa

Título Presentación - 27

Directivas. “Pseudoinstrucciones”

• El ensamblador de Keil (Siemens) no tiene ORG !

• Section: Comienzo de una sección


– De código (programa) ó datos, a partir de una POS de memoria
– Ends: Cierra la sección

• Proc : Comienzo de un procedimiento (subrutina/función)


– Endp: Cierra el procedimiento

• dsw: Reserva espacio para un word (dsb: para un byte)

• equ: Fuera de las secciones


– Define una constante/variable (para esto último se prefiere dsw)

Título Presentación - 28

14
Subrutinas (funciones)
• f(x), ejemplo pow2(x)
– Alto nivel

pot = pow2(n);

– Ensamblador

MOV R1,#n ; main


call pow2 ; llamada (pow2)
.
.

Pow2: MOV R0,#1 ; 2^n


SHL R0,R1
RET ; Vuelta a main

Título Presentación - 29

Subrutinas: stack
• ¿Cómo se encuentra la dirección de vuelta de una subrutina?
– Está almacenada en el STACK
• CALL
– SP <- SP - 2 ; SP (Stack Pointer)
FC00 SP
FBFE SP
– (SP) <- IP ; almacena la dir de vuelta en el stack
FC00
FBFE IP SP
– IP <- pow2 ; IP apunta a la dirección de pow2 (primera instrucción)

• RET
– IP <- (SP) FC00
FBFE IP SP
– SP <- SP + 2 ;Todo queda como estaba antes de llamar a pow2
SP
FC00
FBFE SP
Título Presentación - 30

15
Push y Pop

• PUSH R0 SP
FC00
– SP <- SP - 2 FBFE SP
FC00
– (SP) <- R0 ; guarda R0 en el stack FBFE R0 SP

• POP R0
– R0 <- (SP) FC00
FBFE R0 SP
SP
FC00
– SP <- SP + 2 ; recupera R0 (vacía stack) FBFE SP

• Push y Pop sirven para poder “reutilizar” los GPR’s en las


funciones llamadas (dentro de la función se comportan como
las variables locales de C)

Título Presentación - 31

16

You might also like