1
Programación avanzada en Ensamblador
Cesáreo Fernández Martínez
Álvaro Sánchez Miralles
Título Presentación - 2
Tareas que realiza el programa ensamblador
• Traduce el fuente .a66 a código máquina .obj– mov Rx, Ry
– mov reg, #dato
• Resuelve los valores de las etiquetas– Lleva un contador direcciones en memoria de las
instrucciones. La etiqueta toma el valor de la dirección de memoria de la instrucción asociada
Escribirprograma en
el editor
Ensamblador
Fichero *.a66
Código máquinaFichero *.obj
Ejecutar
Enlazar
Librerías .obj
Código máquinaFichero *.
F0 x y
E6 reg dato
Código de instrucción
Número de GPR
Código de instrucción
Número de SFR
Número de 16 bits
2
Título Presentación - 3
Ejemplo de ensamblador
• Las etiquetas facilitan la programación en ASS
MOV R0,#0MOV 0xfa00,R0MOV R0,#1 ; r0 (i)MOV R1,#1 ; auxiliar
bucle: CMP R0,#5 ; if i>NJMPR cc_sgt,fin ; then goto ´fin’ADD 0xfa00,R1 ; j += 1ADD R0,#1 ; i += 1JMPS bucle ; = jmpr cc_uc,
fin:
Etiquetas (op)
Instrucción Operandos Comentarios (opcional)
Título Presentación - 4
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)
– Ejemplo en 8 bits: 0xFF + 0x01 = 0x00 (ya que el resultado no cabe en 8 bits)
0xFFFF (-1)0x0001 (1)
0xFFFE (-2)0x0002 (2)
0xFFFD (-3)0x0003 (3)
Número -Número +
3
Título Presentación - 5
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.
• 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)
positivonúmeronegativonúmero bitsdenúmero _2_ __ −=0002020 16 xxFFFE −=
Título Presentación - 6
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?
– 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.
positivonúmeronegativonúmero bitsdenúmero _2_ __ −=22254 8 −=
4
Título Presentación - 7
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 - 8
Mov con extensión de signo.
• Extensión de signo– MOVBZ
• Carga el byte en parte baja, extiende (a los 16 bits) con ceros
– MOVBS
• Carga el byte en parte baja, extiende (a los 16 bits) con bit designo
MOVBZ R0,#0xFF ; r0 <- 0x00FFMOVBZ R0,#-1 ; r0 <- 255 no respeta el signo
-128 (0xFF80)128 (0x0080)128-1280x80
-1 (0xFFFF)255 (0x00FF)255-10xFF
16 bits exten-diendo signo
16 sin extender signo
8 bits sin signo
8 bits con signo
MOVBS R0,#0xFF ; r0 <- 0xFFFFMOVBS R0,#-1 ; r0 <- -1 respeta el signo
5
Título Presentación - 9
Programando con etiquetas (para datos)
• La pseudoinstrucción EQU permite dar nombres a los distintos datos de programa– Variables (posiciones de memoria, ej 0fa00h)
– Constantes
var1 equ 0fa00hvar2 equ 0fa01h
MOVB RL0,var1MOVB RL1,var2MOVB var2,RL0MOVB var1,RL1
el_uno equ 1
MOVB RL0,#el_uno
¿Cómo se sabe si el 1 es una constante o una variable?
Título Presentación - 10
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.
6
Título Presentación - 11
Instrucciones aritméticas
• Instrucción ADD– Suma a nivel de word (16b)
– Ej: ADD Rx, op ; Rx <- Rx + op
• Instrucción ADDB– Suma a nivel de byte
MOV R0,#0x0001MOV 0xFA00,R0ADD R0,#0x0009ADD 0xFA00,R0
¿Qué vale R0?
MOV R0,#0x0001ADDB Rh0,#0x01
¿Qué vale R0?
Título Presentación - 12
Instrucciones aritméticas
• Instrucción SUB– Resta a nivel de word (16b)
– Ej: SUB Rx, op ; Rx <- Rx - op
• Instrucción SUBB– Resta a nivel de byte
MOV R0,#0x01FFMOV 0xFA00,R0SUB R0,#0x0009ADD 0xFA00,R0
¿Qué vale R0?
MOV R0,#0x01FFSUBB Rh0,#0x01
¿Qué vale R0?
7
Título Presentación - 13
Instrucciones aritméticas
• Instrucción NEG– Complemento a dos de un número
– Un cambio de signo
– NEG Rx ; Rx <- 0 - Rx
• Instrucción NEGB– Cambio de signo a nivel de byte
MOV R0,#0x01FFNEG R0 ¿Qué vale R0?
MOV R0,#0x01FFNEGB Rl0
¿Qué vale R0?
Título Presentación - 14
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,#0xFFFFMOV R1,#0xFFFFMUL R0,R1MOV R2,MDLMOV R3,MDHMULU R0,R1
¿Qué vale MDL, MDH, R2 y R3?
8
Título Presentación - 15
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,#0xFFFFMOV MDL,R3MOV R0,#0x0001DIV R0MOV R1,MDLMOV R2,MDHMOV R3,#0xFFFFMOV MDL,R3DIVU R0
¿Qué vale MDL, MDH, R1 y R2?
Título Presentación - 16
Instrucciones lógicas
• Instrucción AND– Realiza un AND bit a bit de dos números
– Ej: AND Rx, op ; Rx <- Rx and op
– Sirve como máscara: una especie de filtro para seleccionar únicamente ciertos bits de un registro
MOV R0,#0x0001AND R0,#0x0009
¿Qué vale R0?
AND R0,#0xFFFDSe quiere poner el bit1 del registro R0 a 0. O lo que es lo mismo, se seleccionanel resto de bits del registro R0
9
Título Presentación - 17
Instrucciones lógicas
• Instrucción OR– Realiza un OR bit a bit de dos números
– Ej: OR Rx, op ; Rx <- Rx or op
– Sirve como máscara: una especie de filtro para seleccionar únicamente ciertos bits de un registro
MOV R0,#0x0001OR R0,#0x0009
¿Qué vale R0?
OR R0,#0x0002
Se quiere poner el bit1 del registro R0 a 1. O lo que es lo mismo, se seleccionanel resto de bits del registro R0
AND R0,#0xFFFD ; se pone a 0 el bit 1 de R0MOV R2,R1 ; para no modificar R1AND R2,#0x0002 ; se selecciona el bit 1 de R2OR R0,R2 ; R0.1 = R2.1 = R1.1
Se quiere poner el bit1 del registro R0 igual
que el bit 1 del registro R1.
Título Presentación - 18
Instrucciones lógicas
• Instrucción XOR– Realiza un XOR bit a bit de dos números
– Ej: XOR Rx, op ; Rx <- Rx xor op
• Instrucción CPL– Realiza el complemento a 1 de un número
– CPL Rx ; Rx <- complemento a 1 de Rx
MOV R0,#0x0101 XOR R0,#0xFFFF ; R0 <- 0xFEFE
Si se usa con 0xFFFF se cambian todos los bits de un registro
MOV R0,#0x0101 CPL R0 ; R0 <- 0xFEFE
10
Título Presentación - 19
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,#0x0001SHL R0,#9
¿Qué vale R0?
AND R0,#0xFFFD ; se pone a 0 el bit 1 de R0MOV R2,R1 ; para no modificar R1AND R2,#0x0001 ; se selecciona el bit 0 de R2SHL R2,#1 ; el bit 0 pasa a ser el bit 1OR R0,R2 ; R0.1 = R2.1 = R1.1
Se quiere poner el bit1 del registro R0 igual
que el bit 0 del registro R1.
Rx 16 bits C0
Título Presentación - 20
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
MOV R0,#0x8001ROL R0,#9¿Qué vale R0?
Rx 16 bits C
11
Título Presentación - 21
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.
– 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)
• ...
CMP R0,R1JMPR cc_ugt,next ;si R0 > R1....
next:
Título Presentación - 22
Saltos “a nivel de bit”
• Salto si el bit está a 1– JB bit, dir
• Salto si el bit está a 0– JNB bit, dir
• Consideraciones– Sólo en zonas bit a bit
– No necesitan CMP antes
F600
FC00
FD00
FFFF
FF00
FE00
RAM
SFR’s
STACK
GPRs
Acceso bit a bit
SFRs
SFRs acceso bit a bit
JB C,next ;si C = 1 salta next....
next:
12
Título Presentación - 23
“move” a nivel de bit
• Poner un bit a 1– BSET bit ; bit = 1
• Poner un bit a 0– BCLR bit ; bit = 0
• 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
;activa bit 1 del P2 BSET P2.1 ; BCLR C ; Carry = 0BMOV V,C ; V=C
Título Presentación - 24
C y Ensamblador
• if ( )– Alto nivel
– Ensamblador
if (a == b)...;
else...;
MOV R0,aCMP R0,bJMPR cc_ne,else; condición if..JMPR cc_uc,endif
else: ; condición else..
endif:
13
Título Presentación - 25
Bucles
• for ( )– Alto nivel
– Ensamblador
for (i=START; i <= STOP; i++){a = STOP - i;
MOV R0,#START ; r0 (i)MOV R1,#STOPSUB R1,R0 ; r1 (STOP-START)JMPR cc_uc,test
for: MOV a,R1SUB R1,#1ADD R0,#1 ; i += 1
test: CMP R0,#STOPJMPR cc_slt,for ; i <= STOP
next:
Título Presentación - 26
Otro ejemplo
• while ( )– Alto nivel
– Ensamblador
i = 0;while (i<10) {
a[i] = i; i += 1;}
MOV R0,#0 ; R0 es iMOV R1,#1 ; es el incremento de iMOV R2,#0xfa00 ;R2 almacena la dirección de memoria d e a
otro: CMP R0,#10 JMPR cc_sge,nextMOV [R2],R0ADD R0,R1ADD R2,#2JMPR cc_uc,otro
next:
14
Título Presentación - 27
Directivas. “Pseudoinstrucciones”
• Las directivas a usar en el ”while” anterior :
$nonsegmentedmaxdata equ 0x10 ; constante
D100 section data at 200Hj dsw 10 ; array de datosD100 ends
ej section code at 300Hej1 proc NEAR
MOV R0,#0MOV R1,#1MOV R2,#j
otro: CMP R0,# maxdataJMPR cc_sge,nextMOV [R2],R0ADD R0,R1ADD R2,#2JMPR cc_uc,otro
next: NOPej1 endpej ends
end
Procedimiento ej1
Sección de código ejen dirección 0x300
Sección de datos D100en dirección 0x200
Final de programa
Título Presentación - 28
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)
15
Título Presentación - 29
Subrutinas (funciones)
• f(x), ejemplo pow2(x)– Alto nivel
– Ensamblador
pot = pow2(n);
MOV R1,#n ; maincall pow2 ; llamada (pow2)
.
.
Pow2: MOV R0,#1 ; 2^nSHL R0,R1RET ; Vuelta a main
Título Presentación - 30
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)
– (SP) <- IP ; almacena la dir de vuelta en el stack
– IP <- pow2 ; IP apunta a la dirección de pow2 (primera instrucción)
• RET– IP <- (SP)
– SP <- SP + 2 ;Todo queda como estaba antes de llamar a pow2
SPFC00FBFE
IP SPFC00FBFE
SP
IP SPFC00FBFE
SPFC00FBFE
SP
16
Título Presentación - 31
Push y Pop
• PUSH R0– SP <- SP - 2
– (SP) <- R0 ; guarda R0 en el stack
• POP R0– R0 <- (SP)
– SP <- SP + 2 ; recupera R0 (vacía stack)
• 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)
SPFC00FBFE
R0 SPFC00FBFE
SP
R0 SPFC00FBFE
SPFC00FBFE
SP