Está en la página 1de 80

Tema 2.

Arquitectura de Computadores

Sección 2.2: Programación en Ensamblador - ARM

Electrónica Digital 2 – 2024-1


Docente: Luis Germán García M.
Motivación para esta sección
Entender la estructura y funcionamiento del sistema de cómputo
¿Cómo se programa un sistema de cómputo?
CPU or Processor
Peripheral 1

Control Unit +
Datapath Peripheral 4

Peripheral 2 Peripheral 3
Cache Memory

System Bus (Sistema de Interconexión)

Main Memory or RAM (Memoria Principal)


Motivación para esta sección (2)
Primero, recordemos la abstracción por capas definida:
1. Programas: problemas, algoritmos y programación
2. Sistemas Operativos: gestión de recursos
3. Arquitectura: instrucciones, registros y modos de
direccionamiento (ISA).
4. Microarquitectura: unidades de control y manejo de datos
5. Lógica: bloques funcionales tales como ALUs, memorias, …
6. Circuitos Digitales: compuertas NAND, NOR, NOT, AND, …
7. Otros: circuitos analógicos → dispositivos → física.
Motivación para esta sección (3)

Lenguajes como C, C++, entre otros, emplean las siguientes


estructuras de programación:
1. Operaciones Aritméticas y Lógicas
2. Estructuras de Control de Flujo:
a) Declaraciones Condicionales if/else o case
b) Bucles for y while (do ... while)
3. Llamado a Funciones
4. Manejo de Memoria: arreglos, estructuras, punteros

Objetivo: comprender como estas construcciones de alto nivel se programan


en Lenguaje Ensamblador
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Lecturas Recomendadas

▪ Libro guía: Digital Design and Computer Architecture, ARM


Edition. Sarah L. Harris & David Money Harris
▪ Topic 6.3.1: Data-processing Instructions
▪ Topic 6.3.2: Condition Flags
▪ Topic 6.3.3: Branching
▪ Topic 6.3.4: Conditional Statements
▪ Topic 6.3.5: Getting Loopy
▪ Topic 6.3.6: Memory
▪ Topic 6.3.7: Function Calls
▪ Simulador ARM: https://cpulator.01xz.net/?sys=arm
CPUlator ARM v7
Simulador de Sistemas de Cómputo basados en ARM

▪ Permite en realidad la simulación de varias arquitecturas, no solo


ARM
▪ Se puede simular el funcionamiento de:
▪ La Unidad Central de Proceso
▪ La Memoria
▪ Periféricos de Entrada y Salida
▪ Simulador On-line: https://cpulator.01xz.net/?sys=arm
CPUlator ARM v7 (2)
Barra de control: controla la ejecución de la simulación
Registros y opciones

Visualizador de ASM, código máquina, memoria


CPUlator ARM v7 (3)
Estructura de un programa en lenguaje ensamblador
.equ N, 5 // Definición de Macro N = 5
.global _start // Define la etiqueta como global
.text // Sección de instrucciones en memoria
_start: // Etiqueta que referencia la primera instrucción
MOV R1, #1
MOV R0, #2
For1: // Etiqueta que referencia la instrucción CMP…
CMP R0, #N #define N 5
BHI EndFor1 unsigned int i;
MUL R1, R1, R0 unsigned int fact=1;
ADD R0, R0, #1 for (i=2; i<=N; i++) {
B For1 fact = fact*i;
EndFor1: }
.data // Sección de datos en memoria (si es requerida)
CPUlator ARM v7 (4)
Consideraciones con la escritura de código
.directive {Label}, {Value}
.equ N, 5 // Ejemplo: macro N de valor 5
.global _start // Define la etiqueta como global
.text // El código comienza desde acá
_start: // Etiqueta de inicio de programa
MNEMONIC{COND}{S} DestOper, SrcOper1, SrcOper2 // Comments
SUBS R0, R1, R2 // Ejemplo

Final:
B Final // Evitar finalización de programa
.data // Los datos comienzan desde acá
label: .dc.{l,w,b} VALUE1, VALUE2, VALUE3, … // Constantes
Label: .ds.{l,w,b} #_MEMORY_POSITIONS // Variables
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Consideraciones sobre las Instrucciones
Tenga en cuenta las siguientes consideraciones
▪ Lectura de la instrucción desde la
memoria (Program Counter: R15)
InstrAddr Instruction
▪ Este registro contiene la dirección de la Control Unit
Memory
instrucción a ser leída y ejecutada

ReadInstr
▪ Decodificación de la instrucción para … …

determinar la operación a realizar.


▪ Lectura de datos desde registros o Datapath Unit DataAddr
memoria para realizar la operación A Data
Register
ReadData
R Memory
▪ Ejecución de la operación R ← A op B File
B ALU WriteData

▪ Escritura de resultados en registros


internos o en memoria
Consideraciones sobre las Instrucciones (2)
Tenga en cuenta las siguientes consideraciones
▪ La mayoría de las instrucciones solo
operan sobre registros:
InstrAddr Instruction
▪ ADD R0, R1, R2 Control Unit
Memory
▪ SUB R5, R9, R10

ReadInstr
▪ EOR R7, R9, R10 … …

▪ MOV R0, R1
▪ Existen instrucciones especializadas Datapath Unit DataAddr
en realizar transferencias de memoria A Data
Register
ReadData
R Memory
a registro y viceversa File
B ALU WriteData
▪ LDR R0, [R1]
▪ STR R5, [R4]
Movimiento de datos
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
. . . .
R5 XX XX XX XX 0000_0014
R4 XX XX XX XX 0000_0010
R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 XX XX XX XX 0000_0008 9A AB BC CD
R1 XX XX XX XX 0000_0004 56 67 78 89
R0 XX XX XX XX 0000_0000 12 23 34 45
32-bits 32-bits
Movimiento de datos (2)
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
MOV R1, R0 . . . .
R5 XX XX XX XX 0000_0014
R4 XX XX XX XX 0000_0010
R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 XX XX XX XX 0000_0008 9A AB BC CD
R1 XX XX XX XX 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Movimiento de datos (3)
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
MOV R1, R0 . . . .
// Transf. Mem a Reg
R5 XX XX XX XX 0000_0014
// Dir: R0 + 4
R4 XX XX XX XX 0000_0010
LDR R2, [R0, #4] R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 XX XX XX XX 0000_0008 9A AB BC CD
R1 00 00 00 00 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Movimiento de datos (4)
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
MOV R1, R0 . . . .
// Transf. Mem a Reg
R5 XX XX XX XX 0000_0014
// Dir: R0 + 4
R4 XX XX XX XX 0000_0010
LDR R2, [R0, #4] R3 XX XX XX XX 0000_000C 7E FD FC FA
// Transf. Reg a Mem
R2 56 67 78 89 0000_0008 9A AB BC CD
// Dir: R0 + 0xC
R1 00 00 00 00 0000_0004 56 67 78 89
STR R2, [R0, #0xC]
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Movimiento de datos (5)
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
MOV R1, R0 . . . .
// Transf. Mem a Reg
R5 XX XX XX XX 0000_0014
// Dir: R0 + 4
R4 XX XX XX XX 0000_0010
LDR R2, [R0, #4] R3 XX XX XX XX 0000_000C 56 67 78 89
// Transf. Reg a Mem
R2 56 67 78 89 0000_0008 9A AB BC CD
// Dir: R0 + 0xC
R1 00 00 00 00 0000_0004 56 67 78 89
STR R2, [R0, #0xC]
R0 00 00 00 00 0000_0000 12 23 34 45
// Init. valores grandes
// Valor Inm (#) restringido 32-bits 32-bits
LDR R3, =0xAABBCCDD
Movimiento de datos (6)
Instrucciones que permiten transferir datos entre registros o
registros y memoria

// Inicialización Regs Registro Datos Dir. Words Datos


MOV R0, #0 . . . .
. . . .
MOV R1, R0 . . . .
// Transf. Mem a Reg
R5 XX XX XX XX 0000_0014
// Dir: R0 + 4
R4 XX XX XX XX 0000_0010
LDR R2, [R0, #4] R3 AA BB CC DD 0000_000C 56 67 78 89
// Transf. Reg a Mem
R2 56 67 78 89 0000_0008 9A AB BC CD
// Dir: R0 + 0xC
R1 00 00 00 00 0000_0004 56 67 78 89
STR R2, [R0, #0xC]
R0 00 00 00 00 0000_0000 12 23 34 45
// Init. valores grandes
// Valor Inm (#) restringido 32-bits 32-bits
LDR R3, =0xAABBCCDD
Operaciones Lógicas
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R4 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R3 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R2 10010000 11110011 01010101 00110011
R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (2)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R4 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R3 10010000 00000011 00000000 00110000
R2 10010000 11110011 01010101 00110011
R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (3)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XOR entre bits: EOR R5, R1, R2 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R4 11111111 11111111 11111111 11110011
R3 10010000 00000011 00000000 00110000
R2 10010000 11110011 01010101 00110011
R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (4)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XOR entre bits: EOR R5, R1, R2 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 01101111 11111100 11111111 11000011
BIC R  A & ~B: BIC R6, R1, R2
R4 11111111 11111111 11111111 11110011
R3 10010000 00000011 00000000 00110000
R2 10010000 11110011 01010101 00110011
R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (5)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
XOR entre bits: EOR R5, R1, R2 R6 01101111 00001100 10101010 11000000
R5 01101111 11111100 11111111 11000011
BIC R  A & ~B: BIC R6, R1, R2
R4 11111111 11111111 11111111 11110011

MOV R  B: MOV R7, R2 R3 10010000 00000011 00000000 00110000


R2 10010000 11110011 01010101 00110011
R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (6)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R7 10010000 11110011 01010101 00110011
XOR entre bits: EOR R5, R1, R2 R6 01101111 00001100 10101010 11000000
R5 01101111 11111100 11111111 11000011
BIC R  A & ~B: BIC R6, R1, R2
R4 11111111 11111111 11111111 11110011

MOV R  B: MOV R7, R2 R3 10010000 00000011 00000000 00110000


R2 10010000 11110011 01010101 00110011
MVN R  ~B: MVN R8, R2 R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones Lógicas (7)
Instrucciones de procesamiento de datos que realizan
operaciones lógicas a nivel de bits en registros
. .
AND entre bit: AND R3, R1, R2 . .
. .
OR entre bits: ORR R4, R1, R2 R8 01101111 00001100 10101010 11001100
R7 10010000 11110011 01010101 00110011
XOR entre bits: EOR R5, R1, R2 R6 01101111 00001100 10101010 11000000
R5 01101111 11111100 11111111 11000011
BIC R  A & ~B: BIC R6, R1, R2
R4 11111111 11111111 11111111 11110011

MOV R  B: MOV R7, R2 R3 10010000 00000011 00000000 00110000


R2 10010000 11110011 01010101 00110011
MVN R  ~B: MVN R8, R2 R1 11111111 00001111 10101010 11110000
R0 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
Operaciones de Desplazamiento
Instrucciones de procesamiento de datos que realizan
operaciones de desplazamiento de bits en registros
. .
LSL desp. lógico ←: LSL R2, R0, #12 . .
. .
R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R4 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R3 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R2 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R1 00000000 00000000 00000000 00001110
R0 11001100 11100000 00111100 00000111
Operaciones de Desplazamiento (2)
Instrucciones de procesamiento de datos que realizan
operaciones de desplazamiento de bits en registros
. .
LSL desp. lógico ←: LSL R2, R0, #12 . .
. .
LSR desp. lógico →: LSR R3, R0, R1 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R4 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R3 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R2 00000011 11000000 01110000 00000000
R1 00000000 00000000 00000000 00001110
R0 11001100 11100000 00111100 00000111
Operaciones de Desplazamiento (3)
Instrucciones de procesamiento de datos que realizan
operaciones de desplazamiento de bits en registros
. .
LSL desp. lógico ←: LSL R2, R0, #12 . .
. .
LSR desp. lógico →: LSR R3, R0, R1 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
ASR disp. arith →: ASR R4, R0, R1 R4 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R3 00000000 00000011 00110011 10000000
R2 00000011 11000000 01110000 00000000
R1 00000000 00000000 00000000 00001110
R0 11001100 11100000 00111100 00000111
Operaciones de Desplazamiento (4)
Instrucciones de procesamiento de datos que realizan
operaciones de desplazamiento de bits en registros
. .
LSL desp. lógico ←: LSL R2, R0, #12 . .
. .
LSR desp. lógico →: LSR R3, R0, R1 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
ASR disp. arith →: ASR R4, R0, R1 R4 11111111 11111111 00110011 10000000
R3 00000000 00000011 00110011 10000000
ROR rotación →: ROR R5, R0, R1
R2 00000011 11000000 01110000 00000000
R1 00000000 00000000 00000000 00001110
R0 11001100 11100000 00111100 00000111
Operaciones de Desplazamiento (4)
Instrucciones de procesamiento de datos que realizan
operaciones de desplazamiento de bits en registros
. .
LSL desp. lógico ←: LSL R2, R0, #12 . .
. .
LSR desp. lógico →: LSR R3, R0, R1 R6 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
R5 11110000 00011111 00110011 10000000
ASR disp. arith →: ASR R4, R0, R1 R4 11111111 11111111 00110011 10000000
R3 00000000 00000011 00110011 10000000
ROR rotación →: ROR R5, R0, R1
R2 00000011 11000000 01110000 00000000
R1 00000000 00000000 00000000 00001110
R0 11001100 11100000 00111100 00000111
Operaciones Aritméticas
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
. .
. .
R8 XX XX XX XX
R7 XX XX XX XX
R6 XX XX XX XX
R5 XX XX XX XX
R4 XX XX XX XX
R3 XX XX XX XX
R2 XX XX XX XX
R1 80 00 00 00
R0 00 00 00 01
32-bits
Operaciones Aritméticas (2)
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
Resta: SUB R3, R1, R0 . .
. .
R8 XX XX XX XX
R7 XX XX XX XX
R6 XX XX XX XX
R5 XX XX XX XX
R4 XX XX XX XX
R3 XX XX XX XX
R2 80 00 00 01
R1 80 00 00 00
R0 00 00 00 01
32-bits
Operaciones Aritméticas (3)
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
Resta: SUB R3, R1, R0 . .
. .
R8 XX XX XX XX
Mult 32bits: MUL R4, R0, R1
R7 XX XX XX XX
R6 XX XX XX XX
R5 XX XX XX XX
R4 XX XX XX XX
R3 7F FF FF FF
R2 80 00 00 01
R1 80 00 00 00
R0 00 00 00 01
32-bits
Operaciones Aritméticas (4)
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
Resta: SUB R3, R1, R0 . .
. .
R8 XX XX XX XX
Mult 32bits: MUL R4, R0, R1
R7 XX XX XX XX
Mult 64bits: UMULL R5, R6, R0, R1 R6 XX XX XX XX
LSB MSB R5 XX XX XX XX
R4 80 00 00 00
R3 7F FF FF FF
R2 80 00 00 01
R1 80 00 00 00
R0 00 00 00 01
32-bits
Operaciones Aritméticas (5)
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
Resta: SUB R3, R1, R0 . .
. .
R8 XX XX XX XX
Mult 32bits: MUL R4, R0, R1
R7 XX XX XX XX
Mult 64bits: UMULL R5, R6, R0, R1 R6 00 00 00 00
LSB MSB R5 80 00 00 00

Mult 64bits: SMULL R7, R8, R0, R1 R4 80 00 00 00


LSB MSB R3 7F FF FF FF
R2 80 00 00 01
R1 80 00 00 00
R0 00 00 00 01
32-bits
Operaciones Aritméticas (6)
Instrucciones de procesamiento de datos que realizan
operaciones aritméticas entre registros
Suma: ADD R2, R0, R1 Registro Datos
. .
Resta: SUB R3, R1, R0 . .
. .
R8 FF FF FF FF
Mult 32bits: MUL R4, R0, R1
R7 80 00 00 00
Mult 64bits: UMULL R5, R6, R0, R1 R6 00 00 00 00
LSB MSB R5 80 00 00 00

Mult 64bits: SMULL R7, R8, R0, R1 R4 80 00 00 00


LSB MSB R3 7F FF FF FF
División: no disponible en muchas CPUs R2 80 00 00 01

ARM (Hardware extenso y costoso) R1 80 00 00 00


R0 00 00 00 01
32-bits
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Toma de Decisiones en los Programas
Los programas requieren más que una simple ejecución
secuencial en orden
▪ Instrucciones ARM pueden, si es requerido, modificar el estado de
4 Flags:
▪ Resultado Negativo (N: Negative)
▪ Resultado Cero (Z: Zero)
▪ Resultado con Acarreo (C: Carry)
▪ Resultado con Desbordamiento (V: oVerflow)
▪ Para activar las banderas se puede emplear la instrucción CMP
▪ CMP Rx, Ry: ALU Flags [N, Z, C, V] ← Rx – Ry
▪ Siguientes instrucciones pueden ser condicionalmente ejecutadas
Toma de Decisiones en los Programas (2)
Los programas requieren más que una simple ejecución
secuencial en orden
▪ A las instrucciones que se deben ejecutar condicionalmente, se les
agrega un sufijo:
Mnemonic Condición Mnemonic Condición
EQ 𝐴 = 𝐵 HI 𝐴 > 𝐵 para valores sin signo
NE 𝐴!= 𝐵 LS 𝐴 ≤ 𝐵 para valores sin signo
CS/HS 𝐴 ≥ 𝐵 para valores sin signo GE 𝐴 ≥ 𝐵 para valores con signo
CC/LO 𝐴 < 𝐵 para valores sin signo LT 𝐴 < 𝐵 para valores con signo
MI Resultado negativo GT 𝐴 > 𝐵 para valores con signo
PL Resultado positivo o cero LE 𝐴 ≤ 𝐵 para valores con signo
VS Resultado con overflow Ninguno Ignorar condición
VC Resultado sin overflow AL Ignorar condición
Toma de Decisiones en los Programas (3)
Revisemos el siguiente código en lenguaje C (sentencia if/else):
signed int a = 10, b = 15, c = 5;
if (a >= b) // R0: a, R1: b
c = c + 1; // R2: c
else
c = c – 1;
Código en ensamblador
MOV R0, #10 // Inicializar R0 con 10
MOV R1, #15 // Inicializar R1 con 15
MOV R2, #5 // Inicializar R2 con 5
...
CMP R0, R1 // Flags ← R0 – R1
ADDGE R2, R2, #1 // Resultado es ignorado
SUBLT R2, R2, #1 // Resultado se guarda en R2
Toma de Decisiones en los Programas (4)
¿Y si las sentencias son demasiadas en los bloques if/else?
▪ Ejecución condicional ya no es conveniente:
▪ Gasto de energía innecesario
▪ Tiempo de ejecución más largo
▪ Instrucciones de salto condicional (Bxx) / incondicional (B)
▪ xx corresponde a los mnemonics indicados anteriormente
▪ En el código ensamblador se especifican etiquetas para indicarle a Bxx/B
donde se debe realizar el salto en caso que la condición se cumpla
Label1:
MNEMONIC DestOper, SrcOper1, SrcOper2 ; Comments
MNEMONIC DestOper, SrcOper1, SrcOper2 ; Comments

B Label1 // Salto incondicional (always)
Toma de Decisiones en los Programas (5)
Volvamos a revisar el siguiente código en lenguaje C:
signed int a = 10, b = 15, c = 5;
if (a >= b) // R0: a, R1: b
c = c + 1; // R2: c
else
c = c – 1;
Código en ensamblador: evaluar la condición contraria
CMP R0, R1 // Flags ← R0 – R1
BLT Else1 // Realizar el else si cumple cond.
If1:
ADD R2, R2,#1 // Resultado se guarda en R2
B End1
Else1:
SUB R2, R2, #1 // Resultado se guarda en R2
End1:
Toma de Decisiones en los Programas (6)
Para pocas sentencias, la ejecución condicional es conveniente
signed int counter;
...
counter++; // R0: counter
if (counter == 10)
counter = 0;
...
Ejecución con saltos Ejecución condicional
ADD R0, R0, #1 ADD R0, R0, #1
CMP R0, #10 CMP R0, #10
BNE End1 ANDEQ R0, R0, #0
If1: End2:
AND R0, R0, #0
End1:
Toma de Decisiones en los Programas (7)
Para pocas sentencias, la ejecución condicional es conveniente
unsigned int a = 10, b = 15, c = 5;
if (a < b) // R0: a, R1: b
c = c + 1; // R2: c
else
c = c – 1;
Ejecución con saltos Ejecución condicional
CMP R0, R1 CMP R0, R1
BHS Else1 If2:
If1: ADDLO R2, R2, #1
ADD R2, R2, #1 Else2:
B End1 SUBHS R2, R2, #1
Else1: End2:
SUB R2, R2, #1
End1:
Toma de Decisiones en los Programas (8)
Revisemos este código con sentencia switch/case/default
Ejecución condicional
switch (ch) { // R0: ch
case ‘a’: CMP R0, #’a’
option = 1; // R1: option MOVEQ R1, #1
break; BEQ Endcase1

case ‘b’: CMP R0, #’b’


option = 2; // Sin break MOVEQ R1, #2
// intencional/

default: MOV R1, #0


option = 0; // ‘b’ u otros Endcase1:
}
Toma de Decisiones en los Programas (9)
Revisemos este código con sentencia switch/case/default
Ejecución condicional
switch (ch) { // R0: ch
case ‘a’: CMP R0, #’a’
option = 1; // R1: option MOVEQ R1, #1
break; BEQ Endcase1

case ‘b’: CMP R0, #’b’


option = 2; // Con break MOVEQ R1, #2
break; // corregido BEQ Endcase1

default: MOV R1, #0


option = 0; // ‘b’ u otros Endcase1:
}
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Estructuras Repetitivas
Bloque de código que se repite mientras se cumpla determinada
condición
▪ While (Mientras)
▪ El bloque dentro del while se repite mientras se cumpla la condición dada
▪ Es posible que el bloque no se ejecute ni una sola vez
▪ Existe la estructura Do… While que permite la repetición del bloque al
menos una vez
▪ For (Para)
▪ Se repite mientras se cumpla la condición dada
▪ Permite la inicialización de variables y la modificación de las mismas para
controlar la condición
Estructuras Repetitivas (2)
Revisemos este código con sentencia while
Ejecución con saltos
unsigned int i=1;
unsigned int fact=1; MOV R0, #1
MOV R1, #1
while (i <= 5) { // R0: i
fact = fact*i; // R1: fact While1:
i++; CMP R0, #5
} BHI EndWhile1
MUL R1, R1, R0
ADD R0, R0, #1
B While1
EndWhile1:
Estructuras Repetitivas (3)
Revisemos este código con sentencia for
Ejecución con saltos
#define N 5 .equ N, 5
unsigned int i; // R0: i MOV R1, #1
unsigned int fact=1; // R1: fact
MOV R0, #2
for (i=2; i<=N; i++) { For1:
fact = fact*i; CMP R0, #N
} BHI EndFor1
MUL R1, R1, R0
ADD R0, R0, #1
B For1
EndFor1:
Estructuras Repetitivas (4)
Instrucciones como ADD, SUB, MOV, entre otras pueden
modificar también las ALU Flags
▪ Se añade S (Set Flags) al final del mnemonic
▪ De manera general se tiene:
MNEMONIC{COND}{S} DestOper, SrcOper1, SrcOper2 ; Comments

Example1:
ADD R0, R1, R2 // Siempre se ejecuta, no cambia Flags
ADDEQ R0, R1, R2 // Ejecución cond., no cambia Flags
ADDS R0, R1, R2 // Siempre se ejecuta, cambia Flags
ADDEQS R0, R1, R2 // Ejecución cond., cambia Flags
Estructuras Repetitivas (5)
Revisemos este código nuevamente con sentencia for

#define N 5 Ejecución con saltos


unsigned int i; // R0: i .equ N, 5
unsigned int fact=1; // R1: fact MOV R1, #1

for (i=N; i>0; i--) { MOVS R0, #N


fact = fact*i; BEQ EndFor1
Anterior
} ... For1:
For1:
CMP R0, #N
MUL R1, R1, R0
BHI EndFor1 SUBS R0, R0, #1
MUL R1, R1, R0 BNE For1
ADD R0, R0, #1
B For1
EndFor1:
EndFor1:
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Manejo de la Memoria
La memoria permite almacenar grandes volúmenes de
información
▪ Carga de datos de memoria a registro
▪ Instrucciones LDR / LDRB / LDRSB / LDRH / LDRSH:
LDR Rdest, [Raddrbase, Index (R/#)]
▪ Se cuenta con modos de acceso pre y post indexado, además de
escalamiento para el manejo de arreglos, excepto algunas instrucciones
▪ Almacenamiento de datos desde registro a memoria
▪ Instrucciones STR / STRB / STRH :
STR Rsrc, [Raddrbase, Index (R/#)]
▪ Se cuenta con modos de acceso pre y post indexado, además de
escalamiento para el manejo de arreglos, excepto algunas instrucciones
Manejo de la Memoria (2)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
. . . .
. . . .
R5 XX XX XX XX 0000_0014
R4 XX XX XX XX 0000_0010
R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 XX XX XX XX 0000_0008 9A AB BC CD
R1 XX XX XX XX 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Manejo de la Memoria (3)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
LDRB R2,[R0,#5] . . . .
. . . .
R5 XX XX XX XX 0000_0014
R4 XX XX XX XX 0000_0010
R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 XX XX XX XX 0000_0008 9A AB BC CD
R1 56 67 78 89 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Manejo de la Memoria (4)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
LDRB R2,[R0,#5] . . . .
. . . .
LDRH R3,[R0,#6]
R5 XX XX XX XX 0000_0014
R4 XX XX XX XX 0000_0010
R3 XX XX XX XX 0000_000C 7E FD FC FA
R2 00 00 00 78 0000_0008 9A AB BC CD
R1 56 67 78 89 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Manejo de la Memoria (5)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
LDRB R2,[R0,#5] . . . .
. . . .
LDRH R3,[R0,#6]
R5 XX XX XX XX 0000_0014
LDRSB R4,[R0,#0xD] R4 XX XX XX XX 0000_0010
R3 00 00 56 67 0000_000C 7E FD FC FA
R2 00 00 00 78 0000_0008 9A AB BC CD
R1 56 67 78 89 0000_0004 56 67 78 89
R0 00 00 00 00 0000_0000 12 23 34 45
32-bits 32-bits
Manejo de la Memoria (6)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
LDRB R2,[R0,#5] . . . .
. . . .
LDRH R3,[R0,#6]
R5 XX XX XX XX 0000_0014
LDRSB R4,[R0,#0xD] R4 FF FF FF FC 0000_0010

LDRSH R5,[R0,#0xE] R3 00 00 56 67 0000_000C 7E FD FC FA


R2 00 00 00 78 0000_0008 9A AB BC CD
Instrucciones LDRSB y R1 56 67 78 89 0000_0004 56 67 78 89
LDRSH realizan extensión R0 00 00 00 00 0000_0000 12 23 34 45

del bit de signo (más 32-bits 32-bits


significativo)
Manejo de la Memoria (7)
Acceso a la Memoria en ARM
Revisemos el siguiente código:
LDR R1,[R0,#4] Registro Datos Dir. Words Datos
. . . .
LDRB R2,[R0,#5] . . . .
. . . .
LDRH R3,[R0,#6]
R5 00 00 7E FD 0000_0014
LDRSB R4,[R0,#0xD] R4 FF FF FF FC 0000_0010

LDRSH R5,[R0,#0xE] R3 00 00 56 67 0000_000C 7E FD FC FA


R2 00 00 00 78 0000_0008 9A AB BC CD
Instrucciones LDRSB y R1 56 67 78 89 0000_0004 56 67 78 89
LDRSH realizan extensión R0 00 00 00 00 0000_0000 12 23 34 45

del bit de signo (más 32-bits 32-bits


significativo)
Manejo de la Memoria (8)
Revisemos este código con acceso a memoria
Primero veamos la utilidad de las directivas .DC.{L,W,B} y .DS.{L,W,B}
Instr/Label Dir. Words Datos
... . . .
Final: . . .
. . .
B Final
CteB 0000_002C FE FD FC FB
Vector[2] 0000_0028 XX XX XX XX
.data Vector[1] 0000_0024 XX XX XX XX
CteA: .DC.L 0x12233445 Vector[0] 0000_0020 XX XX XX XX
Vector: .DS.L 3 CteA 0000_001C 12 23 34 45
CteB: .DC.L 0xFEFDFCFB B Final 0000_0018 EA FF FF FE
32-bits
Manejo de la Memoria (9)
Revisemos este código con acceso a memoria

#define N 5
unsigned int i;
unsigned int vector[N]; Id Dir. Words Memoria
. . .
for (i=0; i<N; i++) { . . .
. . .
vector[i] = i; unknown 0000_0020 XX XX XX XX
} vector[4] 0000_001C XX XX XX XX
vector[3] 0000_0018 XX XX XX XX
Suponemos que vector está
vector[2] 0000_0014 XX XX XX XX
ubicado a partir de la vector[1] 0000_0010 XX XX XX XX
dirección 0x0000000C vector[0] 0000_000C XX XX XX XX
32-bits
Manejo de la Memoria (10)
Revisemos este código con acceso a memoria

#define N 5
unsigned int i;
unsigned int vector[N]; Id Dir. Words Memoria
. . .
for (i=0; i<N; i++) { . . .
. . .
vector[i] = i; unknown 0000_0020 XX XX XX XX
} vector[4] 0000_001C 00 00 00 04
vector[3] 0000_0018 00 00 00 03
Suponemos que vector está
vector[2] 0000_0014 00 00 00 02
ubicado a partir de la vector[1] 0000_0010 00 00 00 01
dirección 0x0000000C vector[0] 0000_000C 00 00 00 00
32-bits
Manejo de la Memoria (11)
Revisemos este código con acceso a memoria
.equ N, 5
#define N 5
LDR R1, =vector
unsigned int i;
MOV R0, #0
unsigned int vector[N];
For1:
CMP R0, #N
for (i=0; i<N; i++) {
BHS EndFor1
vector[i] = i;
LSL R2, R0, #2
}
STR R0, [R1, R2]
Llevar una dirección de ADD R0, R0, #1
memoria a un registro: B For1
LDR RegDest, =Label EndFor1:
vector: .ds.l N
Manejo de la Memoria (12)
Para el manejo de arreglos es posible realizar operaciones de:
▪ Modo pre-indexado: versión aumentada de *(++ptr) o *(--ptr)
▪ LDR/LDRB Rdest, [Raddrbase, Rindex/#Imm]!
▪ STR/STRB Rdest, [Raddrbase, Rindex/#Imm]!
LDR R0, [R1, R2]! // R1  R1 + R2
// R0  Mem[R1]
▪ Modo post-indexado versión aumentada de *ptr++ o *ptr--
▪ LDR/LDRB Rdest, [Raddrbase], Rindex/#Imm
▪ STR/STRB Rdest, [Raddrbase], Rindex/#Imm
STR R0, [R1], #4 // R0  Mem[R1]
// R1  R1 + 4
Manejo de la Memoria (13)
El loop anterior con modo post-indexado
.equ N, 5
#define N 5
LDR R1, =vector
unsigned int i;
MOV R0, #0
unsigned int vector[N];
For1:
unsigned int *ptr;
CMP R0, #N
ptr=vector;
BHS EndFor1
STR R0, [R1], #4
for (i=0; i<N; i++) {
ADD R0, R0, #1
*ptr++ = i;
B For1
}
EndFor1:
vector: .ds.l N
Agenda para la sección

1. Conociendo el Simulador CPUlator – ARMv7


2. Procesamiento de Datos
3. Toma de Decisiones en los Programas
4. Estructuras Repetitivas
5. Manejo de la Memoria
6. Llamados a Funciones
Llamado a Funciones
Las funciones permiten reutilizar código común, además de
hacer los programas más modulares
▪ Definición de las funciones en C
▪ Nombre
▪ Entradas (parámetros de la función que reciben los argumentos)
▪ Salida: valor de retorno
tipoRetorno Nombre_Func(tipoDato1 arg1, tipoDato2 arg2, …) {
declaración de variables;

Sentencias u otros bloques;


return (valor_segun_tipo_dato_retorno);
}
Llamado a Funciones (2)
Plantear un programa en C para resolver
𝑥
𝑓 𝑥 =
1 − 𝑥2
float F(float); // Prototipo de la función float F(float value) {
int main(void) { return ( value / (1 – value * value) );
float x, f; }
cout << “Ingrese un valor para x: ”;
cin >> x;
f = F(x);
cout << “El valor de F(“ << x << “) es ” << f;
return 0;
}
Llamado a Funciones (3)
En ARM, existe una convención para la declaración de
funciones y manejo de las mismas
▪ La función que llama a otra función se denomina caller
▪ La función que es llamada se denomina callee
▪ Tanto el caller como el callee deben establecer un pacto para:
▪ Pasar argumentos del caller al callee
▪ Retornar valor resultado desde callee al caller
▪ Hacer que el callee respete los registros y memoria empleada por caller
▪ Caller, por definición, pone sus argumentos en R0-R3
▪ Callee, por definición, pone su valor de retorno en R0
▪ El callee debe saber dónde retornar cuando termine
Llamado a Funciones (4)
En ARM, existe una convención para la declaración de
funciones y manejo de las mismas
▪ El caller llama al callee mediante la instrucción BL (Branch and
Link)
▪ BL almacena la dirección de retorno en el reg. LR (Link Register R14)
▪ BL altera el valor del reg. PC (Program Counter R15) para que la
siguiente instrucción en ejecutar sea la primera instrucción de callee.
▪ Cuando el Callee finaliza, ejecuta la instrucción MOV PC, LR
para causar que el programa continúe en la instrucción siguiente
al llamado
▪ En caso el Callee modifique los registros R4-R11, SP y LR, se
deberá realizar un manejo especial.
Llamado a Funciones (5)
En ARM, existe una convención para la declaración de
funciones y manejo de las mismas

▪ Recordemos los 16 registros de la arquitectura ARM: R0 – R15


Nombre del
Uso por parte del programador/sistema
Registro
R0 Argumentos de funciones, valor de retorno, variables temporales
R1-R3 Argumentos de funciones, variables temporales
R4-R11 Variables almacenadas para futuro uso
R12 Variable temporal
R13 (SP) Puntero de pila o Stack Pointer
R14 (LR) Registro de enlace o Link Register
R15 (PC) Contador de programa o Program Counter
Llamado a Funciones (6)
Llamando a una función que no hace nada práctico
.global _start
void doNothing(void); .text
_start:
void main(void) { BL doNothing // 0x00000000 PC
doNothing(); PC Final:
B Final // 0x00000004
while(1); doNothing:
} MOV PC, LR // 0x00000008
Registro Datos
void doNothing(void) { ... ...
return;
LR XX XX XX XX
}
PC 00 00 00 00
32-bits
Llamado a Funciones (7)
Llamando a una función que no hace nada práctico
.global _start
void doNothing(void); .text
_start:
void main(void) { BL doNothing // 0x00000000
doNothing(); Final:
B Final // 0x00000004
while(1); doNothing:
} MOV PC, LR // 0x00000008 PC
Registro Datos
void doNothing(void) { ... ...
return; PC
LR 00 00 00 04
}
PC 00 00 00 08
32-bits
Llamado a Funciones (8)
Llamando a una función que no hace nada práctico
.global _start
void doNothing(void); .text
_start:
void main(void) { BL doNothing // 0x00000000
doNothing(); Final:
B Final // 0x00000004 PC
while(1); PC doNothing:
} MOV PC, LR // 0x00000008
Registro Datos
void doNothing(void) { ... ...
return;
LR 00 00 00 04
}
PC 00 00 00 04
32-bits
Llamado a Funciones (9)
Llamando a una función que calcula el complemento a dos
int doTwoComp(int);
.global _start
void main(void) { .text
int num = 1; _start:
num = doTwoComp(num); MOV R0, #1
BL doTwoComp
while(1); Final:
} B Final
doTwoComp:
int doTwoComp(int x) { MVN R0, R0
return( ~x + 1 ); ADD R0, R0, #1
} MOV PC, LR
Llamado a Funciones (10)
Casos Especiales

▪ ¿Qué pasa si necesito enviar más de 4 argumentos?


▪ ¿Cómo restauro los registros R4-R11 en caso la función callee
los utilice?
▪ Y si llamo a una función dentro de otra función, ¿Qué le sucede
al valor del registro LR?
▪ ¿Podría tener funciones recursivas?
▪ Todo lo anterior se puede resolver si se emplea la pila del
sistema (Manejo de Stack).
▪ Dicho tema se verá en la siguiente sección.
Llamado a Funciones (11)
Haga una función que calcule la serie de Fibonacci
#define N 10
int vector[N]; .equ N, 10 Loop:
void fibo(int *, int); LDR R0, =vector LDR R2, [R0, #-8]
MOV R1, #N LDR R3, [R0, #-4]
void main(void) { BL Fibo ADD R3, R2, R3
fibo(vector, N); Final: STR R3, [R0], #4
while(1); B Final
} Fibo: SUBS R1, R1, #1
MOV R2, #1 BNE Loop
void fibo(int *ptr, int num) { STR R2, [R0], #4 EndLoop:
*ptr++ = 1; *ptr++ = 1; STR R2, [R0], #4 MOV PC, LR
for (int i=2; i<num; i++) SUB R1, R1, #2
*ptr++=*(ptr-1) + *(ptr-2); vector: .ds.l N
}
¿Problemas en el código?
Sección 2.2: Programación en Ensamblador - ARM

Muchas gracias por la atención prestada

Electrónica Digital 2 – 2024-1


Docente: Luis Germán García M.

También podría gustarte