Documente Academic
Documente Profesional
Documente Cultură
PowerPC con
Mac OS X
Ensamblador del PowerPC con Mac OS X MacProgramadores
Para poder conseguir este objetivo, este tutorial está diseñado para personas
con ciertos conocimientos de programación y de arquitectura de
computadores, en concreto el documento exige que el lector tenga
conocimientos de programación en C, así como de arquitectura de
computadores al nivel que se da en una primera asignatura de arquitectura
Pág 2
Ensamblador del PowerPC con Mac OS X MacProgramadores
Otros requisitos, que sin ser indispensables, si que ayudarían mucho al lector
serían que el lector hubiese programado ya alguna vez en ensamblador, o
bien del PowerPC, o bien de cualquier otro microprocesador, ya que los
conceptos entre distintos procesadores varían más bien poco. Por último, y
especialmente dirigido a los últimos temas, sería recomendable conocer el
diseño de un sistema operativo tal como se explica en un primer curso de
sistemas operativos en una carrera universitaria de informática. Este requisito
es el menos importante ya que estos conceptos sí que se explican bastante
bien a lo largo del tutorial.
Pág 3
Ensamblador del PowerPC con Mac OS X MacProgramadores
Notaciones utilizadas
En general, cuando describamos una instrucción ensamblador vamos a utilizar
las minúsculas para indicar valores que tengamos que escribir literalmente,
mientras que vamos a utilizar mayúsculas para indicar valores que deban ser
sustituidos por su valor, es decir, si escribimos el formato de una instrucción,
escribiremos:
cmp CRF,L,rA,rB
cmp 2,0,r5,r6
Nota legal
Este tutorial ha sido escrito por Fernando López Hernández para
MacProgramadores, y de acuerdo a los derechos que le concede la legislación
española e internacional el autor prohíbe la publicación de este documento en
cualquier otro servidor web, así como su venta, o difusión en cualquier otro
medio sin autorización previa.
Sin embargo el autor anima a todos los servidores web a colocar enlaces a
este documento. El autor también anima a cualquier persona interesada en
aprender a programar el PowerPC a bajarse o imprimirse este tutorial.
Pág 4
Ensamblador del PowerPC con Mac OS X MacProgramadores
Tabla de contenido
TEMA 1: Introducción al PowerPC
1 La arquitectura del PowerPC ..............................................................10
2 Los entornos del PowerPC..................................................................12
3 Los registros del PowerPC..................................................................13
4 Byte ordering....................................................................................14
5 Alineación.........................................................................................16
Pág. 5
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág. 6
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág. 7
Ensamblador del PowerPC con Mac OS X MacProgramadores
APÉNDICE B: La segmentación
1 ¿Que es la segmentación? ...............................................................209
2 Etapas multiciclo .............................................................................212
3 Los riesgos .....................................................................................213
3.1 Riesgos estructurales ................................................................213
3.2 Riesgos por dependencia de datos .............................................214
3.3 Riesgos de control ....................................................................217
3.4 Saltos sin resolver ....................................................................218
3.5 Solución software a los saltos sin resolver ..................................219
3.5.1 Estructura if.......................................................................220
3.5.2 Estructura while.................................................................220
3.5.3 Estructura do-while ............................................................221
3.5.4 Estructura for ....................................................................222
3.6 Solución hardware a los saltos sin resolver .................................222
3.7 La serialización .........................................................................226
4 Más allá de la segmentación ............................................................227
Pág. 8
Tema 1
Introducción al PowerPC
Sinopsis:
Este primer tema sirve para orientar al lector sobre el contenido del tutorial, y
ayuda a concretar una serie de conceptos básicos que serán necesario tener
claro para leer el resto del tutorial.
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 10
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por un lado Motorola está fabricando chips que siguen esta arquitectura de
uso doméstico, y que aunque ha hecho algún micro de 64 bits, la mayoría de
los micros de que disponen son de 32 bits.
Apple por su parte compra los micros a Motorola (en concreto los G4
disponen de micros de la serie MPC74xx de Motorola y a IBM (los G5 son
microprocesadores que IBM ha hecho a Apple). Podemos consultar los micros
de que dispone Motorola aquí en [MICROMOTOROLA], y los micros de IBM
en [MICROIBM].
Nosotros nos vamos a centrar en estudiar los micros de 32 bits, que son los
que utiliza el sistema operativo Mac OS X. Téngase en cuenta que aunque
dispongamos de una máquina G5 con un microprocesador de 64 bits,
actualmente no se utilizan sus características adicionales con el fin de
mantener compatibilidad. En cualquier caso pasar de un ensamblador de 32
bits a uno de 64 bits resulta muy fácil ya que los juegos de instrucciones
fueron pensados con el fin de que fueran similares.
Pág 11
Ensamblador del PowerPC con Mac OS X MacProgramadores
Todos los micros deben de implementar el UISA, mientras que el VEA y OEA
son opcionales, aunque si un micro implementa el OEA también debe de
implementar el VEA.
Pág 12
Ensamblador del PowerPC con Mac OS X MacProgramadores
El entorno VEA añade dos nuevos registros llamados TBU (Time Base Upper)
y TBL (Time Base Lower), que sólo están disponibles en los micros que
implementan VEA.
Por último OEA define otros muchos registros especiales llamados SPR
(Special Purpose Registers), que no veremos hasta más adelante, y a los que
sólo se puede acceder en modo supervisor. Estos registros nos permiten
controlar cosas como las tablas de paginación y segmentación, la traducción
de direcciones lógicas a direcciones virtuales y reales, el manejo de
excepciones, el acceso a dispositivos, etc. Normalmente estos registros no
son accedidos más que por el sistema operativo.
Una característica importante de los sistemas RISC, y por tanto del PowerPC
es que, a diferencia de los sistemas CISC, las únicas instrucciones que
transfieren datos entre memoria y los registros son instrucciones diseñadas
con el fin de leer o escribir en memoria, y todas las demás instrucciones
siempre trabajan con datos previamente cargados en registros. El hecho de
que las instrucciones de los sistemas RISC sólo puedan tener como operandos
registros disminuye mucho los modos de direccionamiento de las
instrucciones del micro, y en consecuencia la complejidad del juego de
instrucciones. Compárese esta organización con los sistemas CISC, donde las
instrucciones pueden tener como uno de sus operadores una dirección de
memoria, o bien un registro.
Esto también hace que en los sistemas RISC sea muy típico que una
instrucción tenga hasta 3 operandos. Por ejemplo la instrucción de suma
recibe dos registros como origen y un tercero como destino. Esto también es
una diferencia respecto a los sistemas CISC donde las instrucciones suelen
recibir sólo dos operadores, con lo que operaciones como la de suma tienen
Pág 13
Ensamblador del PowerPC con Mac OS X MacProgramadores
Modo supervisor. Usado sólo por el sistema operativo para acceder a los
recursos definidos por el OEA.
Modo usuario. Usado por las aplicaciones y el sistema operativo para
realizar operaciones consideradas “no peligrosas”. Es el modo que usamos
para acceder a los recursos definidos por UISA y VEA.
4 Byte ordering
Los bytes de la memoria se numeran empezando a contar por 0. Cada
número es la dirección de memoria de un byte. En este sentido los bytes son
unidades indivisibles y no existe problema respecto a la forma de ordenar los
bits de un byte en memoria. El problema surge con las variables cuyo tamaño
es mayor a un byte.
En este caso existen dos formas de colocar los bytes que forman una variable
en memoria llamadas:
Por ejemplo, el número 617163 en binario se escribe como 1001 0110 1010
1100 1011. Si lo queremos guardar en memoria necesitaremos una variable
de tamaño suficiente para almacenarlo.
Pág 14
Ensamblador del PowerPC con Mac OS X MacProgramadores
4.1.1.1 Big-Endian
4.1.1.2 Little-Endian
Pág 15
Ensamblador del PowerPC con Mac OS X MacProgramadores
5 Alineación
PowerPC dispone de instrucciones que permiten transferir entre memoria y
los registros tanto bytes, como halfwords (16 bits), words (32 bits), o
doublewords (64 bits). En las máquinas de 32 bits, estos últimos sólo se usan
para los datos en representación de punto flotante con precisión doble que
queramos guardar en los FPR, mientras que en los procesadores de 64 bits,
los GPRs tienen 64 bits con lo que es su tamaño por defecto.
Como regla general, debemos colocar las variables en zonas de memoria cuya
dirección sea múltiplo del tamaño de la variable que estamos guardando.
Pág 16
Tema 2
EMPEZANDO A PROGRAMAR
Sinopsis:
1 Herramientas necesarias
Vamos a empezar viendo qué herramientas de programación en ensamblador
existen para Mac OS X y como se pueden usar.
Los primero que vamos a necesitar es obtener las Development Tools que
podemos conseguir gratuitamente de la Apple Developer Connection (ADC) en
[DEVTOOLS]:
#include <stdio.h>
int main ()
{
printf(MENSAJE);
return 0;
}
Listado 1.1: Programa ensamblador mínimo
1. Preprocesado
2. Generación del código ensamblado (compilación)
3. Generación del código objeto (ensamblado)
4. Enlazado
Pág 18
Ensamblador del PowerPC con Mac OS X MacProgramadores
Podemos pedir a gcc que realice todas o sólo alguna de estas fases.
$ gcc -E saluda.c
$ gcc -S saluda.c
$ gcc -c saluda.c
Esto genera el fichero saluda.o que después podemos enlazar junto con
otros ficheros de código objeto.
$ gcc -c saluda.s
$ as saluda.s -oD.o
De hecho esta es la principal herramienta que vamos a usar para compilar los
programas en ensamblador que hagamos a lo largo de este tutorial.
Pág 19
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por último, la Tabla 2.1 muestra las extensiones de fichero que reconoce el
compilador de GNU, y para que se utiliza cada una.
Pág 20
Ensamblador del PowerPC con Mac OS X MacProgramadores
2 El programa mínimo
Ya que sabemos cómo se usa el compilador, vamos a escribir un programa
mínimo para ver cómo se compila y enlaza un programa ensamblador en Mac
OS X.
Comentario Descripción
/*··· */ Comentario multilínea de C
// Comentario de una sola línea de C
; Comentario de una sola línea propio del ensamblador as
Tabla 2.2: Tipos de comentarios en lenguaje ensamblador
Pág 21
Ensamblador del PowerPC con Mac OS X MacProgramadores
.globl sirve para declarar como global el siguiente símbolo que aparece. La
función main() debe de ser un símbolo global para que Mac OS X pueda
acceder a ella. Obsérvese que la función se llama _main y no main, esto es
así porque todos los símbolos sufren un name-mangling al estilo C (poner un
_ delante) antes de meterlos en la tabla de símbolos.
Pág 22
Ensamblador del PowerPC con Mac OS X MacProgramadores
3 El lenguaje ensamblador
Ahora que ya sabemos cómo se hace un programa en ensamblador, vamos a
comentar brevemente cuales son los principales elementos del lenguaje
ensamblador, así como la sintaxis de las sentencias que soporta.
Las distintas partes de la sentencia se pueden separar tanto por espacio como
por tabulador, pero normalmente existe la costumbre de separar por espacio,
excepto en el caso de la etiqueta donde se suele poder un tabulador al
Pág 23
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por ejemplo:
mflr r0
inicio: stwu r1,-80(r1)
mr r30,r1
bcl 20,31,inicio
En esta sección vamos a comentar cuáles son los principales elementos que
componen el lenguaje ensamblador.
Pág 24
Ensamblador del PowerPC con Mac OS X MacProgramadores
3.2.1 Literales
li r3,'A'
Estas se utilizan sobre todo para reservar trozos de memoria con la directiva
.ascii así:
0flt_char[{+-}[dec...][.[dec...]]e[{+-}][dec...]]
Pág 25
Ensamblador del PowerPC con Mac OS X MacProgramadores
Cuando usamos uno de estos literales con las directivas .single y .double
que sirven para reservar memoria para un número en punto flotante de
precisión simple o doble, respectivamente, la directiva ignora el tipo del
literal, y sólo se tiene en cuenta el tipo de la directiva, aun así es
recomendable indicar el tipo por claridad.
Por ejemplo:
3.2.2 Identificadores
"maximo relativo"
"diferencia en pixeles"
Aunque por homogeneidad con los demás lenguajes es mejor no usar esta
forma, que da lugar a confusión con las cadenas de caracteres, y en vez de
ello usar guiones bajos o mayúsculas y minúsculas para separar palabras.
MaximoRelativo
diferencia_en_pixeles
Pág 26
Ensamblador del PowerPC con Mac OS X MacProgramadores
········
inicio: stwu r1,-80(r1) ; Declaración
········
bcl 20,31,inicio ; Uso
Respecto al ámbito de las etiquetas, estas sólo son visibles dentro del fichero
que las declara, pero podemos hacer las etiquetas de ámbito global (para
poder acceder a ellas desde otros ficheros) con la directiva .globl:
.global A
A: lwi r4,5
Por ejemplo:
1: instruccionA
·················
1: instruccionB
·················
b 1 ; Salta a instruccionB
b 1b ; Salta a instruccionB
b 1f ; Salta a instruccionC
·················
1: instruccionC
Pág 27
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 28
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 29
Ensamblador del PowerPC con Mac OS X MacProgramadores
Este resulta a veces útil como operando de una instrucción, directiva, macro o
expresión.
Existen dos directivas que nos permiten avanzar el valor del location counter:
Por ejemplo:
.align 2
Esta directiva avanza el location counter tantos bytes como diga avance,
rellenando con bytes con el valor de relleno, o ceros si no se indica.
Por ejemplo:
Pág 30
Ensamblador del PowerPC con Mac OS X MacProgramadores
Sólo existe una excepción que son las sentencias de asignación directa, las
cuales tienen la forma:
identificador = expresion
La cuales sirven para declarar constantes que se puedan usar más adelante
en el programa.
Por ejemplo, el programa del Listado 2.1 lo podríamos haber hecho como
muestra el Listado 2.2:
.text
.align 2
.globl _main
_main:
li r3,operando1
li r4,operando2
add r5,r3,r4
blr
Listado 2.2: Programa que usa sentencias de asignación directa
Pág 31
Ensamblador del PowerPC con Mac OS X MacProgramadores
// Directivas .set
.set operando1,3
.set operando2,5
.text
.align 2
.globl _main
_main:
li r3,operando1
li r4,operando2
add r5,r3,r4
blr
Listado 2.3: Programa que usa .set en lugar de identificadores
Las sentencias de asignación directa y las directivas .set sólo nos permiten
almacenar valores literales:
var1 = 3 ; Correcto
var1 = r3 ; Error ensamblado
.set var1 3; correcto
.set var1 r3 ; Error ensamblado
#define dividendo r3
#define divisor r4
#define cociente r5
divw cociente,dividiendo,divisor
Pág 32
Ensamblador del PowerPC con Mac OS X MacProgramadores
4 Acceso a memoria
En esta sección vamos a explicar una serie de conceptos fundamentales para
poder acceder a memoria.
1
Como veremos más adelante existen más segmentos, pero por simplicidad vamos a
empezar suponiendo que sólo existen estos dos
Pág 33
Ensamblador del PowerPC con Mac OS X MacProgramadores
.data
············
············
.text
············
············
············
Cuando el enlazador recibe los ficheros de código objeto, éste fusiona todos
los segmentos de un mismo tipo bajo un único segmento.
Cada segmento a su vez está dividido en una o más secciones que nos dan
un mayor nivel de precisión a la hora de indicar como tratar los datos de esa
sección.
Vamos a comentar qué puede tener cada sección (del segmento de código y
del de datos), para que sirve cada una, así como que directivas se usan para
delimitar cada sección.
La Tabla 2.4 resume las directivas usadas para cada tipo de sección que
puede contener el segmento de código:
Pág 34
Ensamblador del PowerPC con Mac OS X MacProgramadores
.const Esta directiva se usa para crear una sección de datos constantes. Si
los datos no van a cambiar durante la ejecución del programa se pueden
guardar en el segmento de código (en vez de en el segmento de datos), con
las consiguientes ventajas que aporta. Por ejemplo respecto a la paginación.
.literal8 Igual que antes, pero usada para guardar datos constantes de 8
bytes. Principalmente números double. Durante el ensamblado el compilador
reúne todas las variables declaradas en esta sección que tengan el mismo
valor.
Pág 35
Ensamblador del PowerPC con Mac OS X MacProgramadores
Directiva Descripción
.byte [valor] Reserva espacio para un byte, y le asigna el valor
dado en valor, ó 0 si no se especifica.
.short [valor] Reserva espacio para una variable entera de 2
bytes, y le asigna el valor dado en valor, ó 0 si
no se especifica.
.long [valor] Reserva espacio para una variable entera de 4
bytes, y le asigna el valor dado en valor, ó 0 si
no se especifica.
.single [valor] Reserva espacio para una variable de punto
flotante con precisión simple (4 bytes), y le asigna
el valor dado en valor, ó 0 si no se especifica.
.double [valor] Reserva espacio para una variable de punto
flotante con precisión doble (8 bytes), y le asigna
el valor dado en valor, ó 0 si no se especifica.
.ascii cadena Reserva espacio para la cadena dada en cadena.
No pone el 0 de final de cadena
.asciz cadena Reserva espacio para la cadena dada en cadena.
Y pone un 0 al final de la cadena.
.fill Pone el valor dado en valor tantas veces como
repeticiones, diga repeticiones. El tamaño de la variable
tamaño, valor
puede ser 1,2 ó 4 según diga tamaño
.space n_bytes, Pone el valor dado en valor tantas veces como
[valor] diga n_bytes, o ceros si no damos valor
Tabla 2.5: Directivas para indicar la cantidad de memoria a reservar y valor inicial
.text
.const
c1: .byte 'A'
c2: .byte 'B'
.literal4
i: .long 12
Pág 36
Ensamblador del PowerPC con Mac OS X MacProgramadores
f: .float 0r1.34e0
.literal8
d: .double 0d56.e7
.cstring
msg: .ascii "Hola mundo\013\000"
.text ; Ahora van las instrucciones en ensamblador
; en una seccion de codigo regular
lwz r4,0(r9)
lwz r5,0(r11)
.literal4
A1: .long 0
A2: .long 0
A3: .long 0
A4: .long 0
.const
A1: .long 0
A2: .long 0
A3: .long 0
A4: .long 0
Pág 37
Ensamblador del PowerPC con Mac OS X MacProgramadores
La Tabla 2.6 resume las directivas usadas para cada tipo de sección que
puede contener el segmento de datos:
Estas dos directivas reservan siempre memoria dentro del segmento de datos,
con lo que aunque aparezcan en el segmento de código la reserva se produce
en el segmento de datos regular.
Pág 38
Ensamblador del PowerPC con Mac OS X MacProgramadores
Directiva Descripción
.comm etiqueta, tamaño Reserva tamaño bytes y crea la etiqueta
global etiqueta que apunta a esta zona
de memoria sin inicializar.
.lcomm etiqueta, tamaño Igual a .comm, sólo que la etiqueta es de
ámbito local, con lo que no es accesible
desde fuera del módulo
Tabla 2.7: Directivas para reservar memoria en las secciones del segmento de datos
.data
A: .long 60 ; Crea una variable de 4 bytes con
; un valor de 60 en la sección
; (__DATA,__data)
.static_data
B: .long 3 ; Crea una variable de 4 bytes con
; un valor de 3 en la sección
; (__DATA,__static_data)
.comm C, 4 ; Reserva 4 bytes sin inicializar
; en la sección (__DATA,__static_data)
.text
; Ahora van las instrucciones en ensamblador
; en la sección regular del segmento de código
; (__TEXT,__text)
lwz r4,0(r9)
lwz r5,0(r11)
.comm D, 20 ; Reserva 20 bytes sin inicializar
; en la sección (__DATA,__data)
; Mas instrucciones en la sección regular
; del segmento de código (__TEXT,__text)
mtlr r0
lmw r30,-8(r1)
Listado 2.4: Ejemplo de reserva de memoria
Pág 39
Ensamblador del PowerPC con Mac OS X MacProgramadores
.const
A: .long 20
.section __TEXT,__const
A: .long 20
Cuando el compilador genera el código objeto, reúne todas las secciones del
mismo tipo que aparezcan a lo largo del fichero fuente, de forma que el
segmento del fichero objeto tiene como mucho una sección de cada tipo.
.data
··········
··········
.const
··········
··········
.text
··········
··········
.const
··········
··········
Pág 40
Ensamblador del PowerPC con Mac OS X MacProgramadores
Cuando el enlazador enlaza los ficheros objeto, vuelve a reunir las secciones
del mismo tipo de los distintos ficheros objeto, para que sólo haya una
sección de cada tipo en el segmento del ejecutable.
Hace años, las memoria que tenían que direccionar las máquinas era
relativamente pequeña (p.e 28B ó 216B), con lo que las instrucciones
ensamblador podían incluir la dirección de memoria a la que acceder como
parte de la instrucción, llamado indireccionamiento inmediato o bien
usaban un registro para almacenar la dirección a la que acceder, llamado
indireccionamiento de registro.
movb %al,dir
Pág 41
Ensamblador del PowerPC con Mac OS X MacProgramadores
La solución que se usa pasa por usar 2 instrucciones, una de ella carga los 16
bits altos del registro, y la otra los 16 bits bajos.
Para obtener la parte alta y la parte baja de una dirección de 32 bits (que
posiblemente saquemos de una etiqueta) se usan los operadores lo16()
hi16() y ha16() tal como se explica a continuación.
Vamos a ver cómo se cargan los 32 bits de una dirección de memoria en dos
partes, cada una de las cuales carga 16 bits.
En primer lugar comentar que sí hay instrucciones que pueden recibir como
operando un valor de 16 bits, que es el que luego cargan en el registro.
(rA|0) es una notación muy usada en las instrucciones del PowerPC que
significa que aquí podemos dar uno de los 32 registros de GPR excepto r0, o
bien un 0, en cuyo caso significa que este operando vale 0, con lo que en rD
se almacena el valor de sumar 0 a SIMM, es decir el valor de rD=0+SIMM.
Pág 42
Ensamblador del PowerPC con Mac OS X MacProgramadores
La razón por la que podemos indicar cualquiera de los registros menos el r0,
es que en la codificación binaria de la instrucción, el código 0 se utiliza para
indicar un 0 binario, y no el contenido del registro r0.
addis r2,0,hi16(expr)
rA es el destino de la operación
rS es uno de los operandos.
UIMM (Unsigned IMMediate) es el otro operando.
Luego ahora ya podemos escribir las dos instrucciones que cargan una
dirección de memoria de 32 bits en un registro.
addis r2,0,hi16(expr)
ori r2,r2,lo16(expr)
Aún queda por ver cuándo y cómo se usa ha16(), que lo vamos a ver en el
siguiente punto.
Como sabemos, una instrucción consta de un campo opcode, que indica que
hace la instrucción, y de unos operandos. Los operandos pueden estar
codificados directamente dentro de la instrucción, llamado operando
inmediato, o situado en memoria en cuyo caso tememos que hacer un
indireccionamiento del operando.
Pág 43
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 44
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 56 10 11 15 16 31
Opcode rD/rS rA d
Codificación de la instrucción
0 15 16 31
Extensión de signo d
Sí
¿rA=0? 0
No +
Store
GPR(rD/rS) Load Memoria principal
Instrucción Descripción
lbz rD,d(rA) (Load Byte and Zero) El byte en la dirección efectiva
d(rA) se carga en el byte bajo de rD, los demás
bytes de rD quedan a 0
lbzu rD,d(rA) (Load Byte and Zero with Update) Igual a lbz sólo
que la dirección efectiva se guarda en rA una vez
realizada la operación de carga
lhz rD,d(rA) (Load Half-word and Zero) El half-word en la dirección
efectiva d(rA)se carga en los dos bytes bajos de rD,
los demás bytes de rD quedan a 0
Pág 45
Ensamblador del PowerPC con Mac OS X MacProgramadores
lhzu rD,d(rA) (Load Half-word and Zero with Update) Igual a lhz
sólo que la dirección efectiva se guarda en rA una
vez realizada la operación de carga
lha rD,d(rA) (Load Half-word Algebraic) El half-word en la dirección
efectiva d(rA)se carga en los dos bytes bajos de rD,
los demás bytes de rD se rellenan con el bit más
significativo del half-word cargado, es decir, expande
el signo
lhau rD,d(rA) (Load Half-word Algebraic with Update) Igual a lha
sólo que la dirección efectiva se guarda en rA una
vez realizada la operación de carga
lwz rD,d(rA) (Load Word and Zero) El word en la dirección efectiva
d(rA) se carga en rD. Obsérvese que al medir un
GPR 32 bits no carga 0 en el resto del registro si el
GPR es de 32 bits, pero si lo haría si la instrucción se
ejecuta en una máquina 64 bits
lwzu rD,d(rA) (Load Word and Zero with Update) Igual a lwz sólo
que la dirección efectiva se guarda en rA una vez
realizada la operación de carga
Tabla 2.8: Instrucciones de carga de enteros con indireccionamiento de registro base e
índice inmediato
Instrucción Descripción
stb rS,d(rA) (STore Byte) El byte menos significativo de rS se
guarda en la posición de memoria dada por d(rA)
stbu rS,d(rA) (STore Byte with Update) Igual a stb, sólo que
después de guardar el dato en memoria, en rA se
guarda la dirección efectiva calculada como d(rA)
sth rS,d(rA) (STore Half-word) El half-word menos significativo de
rS se guarda en la posición de memoria dada por
d(rA)
sthu rS,d(rA) (STore Half-word with Update) Igual a sth, sólo que
después de guardar el dato en memoria, en rA se
guarda la dirección efectiva calculada como d(rA)
stw rS,d(rA) (STore Word) El valor de rS se guarda en la posición
de memoria dada por d(rA)
stwu rS,d(rA) (STore Byte with Update) Igual a stw, sólo que
después de guardar el dato en memoria, en rA se
guarda la dirección efectiva calculada como d(rA)
Tabla 2.9: Instrucciones de almacenamiento de enteros con indireccionamiento de registro
base e índice inmediato
Pág 46
Ensamblador del PowerPC con Mac OS X MacProgramadores
4.4.2 Ejemplo
Pág 47
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 48
Ensamblador del PowerPC con Mac OS X MacProgramadores
.data
.lcomm A,20 ; 10 elementos de 2 bytes
.text
···········
addis r3,0,hi16(A)
ori r3,r3,lo16(A)-2
DESDE 1 HASTA 10
lhzu r2,2(r3)
; Procesamos r2
FIN_DESDE
Hasta ahora hemos visto que para acceder a memoria primero tenemos que
cargar en un registro una dirección de memoria, para lo cual usábamos dos
instrucciones:
addis r3,0,hi16(var)
ori r3,r3,lo16(var)
Vamos a ver ahora que usando un pequeño truco vamos a poder cargar en
un registro sólo la parte alta de la dirección, y después aprovechamos el
indireccionamiento de registro base e índice inmediato para indicar la parte
baja de la dirección, más o menos así:
addis r3,0,ha16(var)
lwz r2,lo16(var)(r3)
Pág 49
Ensamblador del PowerPC con Mac OS X MacProgramadores
Ahora cuando la instrucción calcula d(rA) como la suma de la parte alta más
la parte baja, si intentamos calcular la dirección efectiva dir como
hi16(dir)+lo16(dir) tenemos:
Podemos modificar el ejemplo del Listado 2.5 para que use ha16() en vez de
hi16() como muestra el Listado 2.6.
Pág 50
Ensamblador del PowerPC con Mac OS X MacProgramadores
addis r5,0,ha16(dir)
stw r4,lo16(dir)(r5)
Pág 51
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 56 10 11 15 16 20 21 31
0 15 16 31
GPR(rB)
Sí
¿rA=0? 0
No +
Store
GPR(rS/rS) Load Memoria principal
Las instrucciones que usan este modo de indireccionamiento usan dos GPR
(llamados rA y rB) para calcular la dirección efectiva como la suma de estos.
A rA se le llama registro base, y a rB registro índice. En concreto se
calcula como (rA|0)+rB, es decir, rA puede ser uno de los registros de r1
a r31 (pero no r0), o bien 0, en cuyo caso para calcular la dirección efectiva
se usa sólo el valor de rB.
Las Tabla 2.10 y Tabla 2.11 muestran las principales instrucciones que usan
este modo.
Instrucción Descripción
lbzx rD,rA,rB (Load Byte and Zero indeXed) El byte en la dirección
efectiva (rA|0)+rB se carga en el byte bajo de rD,
los demás bytes de rD quedan a 0
lbzux rD,rA,rB (Load Byte and Zero with Update indeXed) Igual a
lbzx sólo que la dirección efectiva se guarda en rA
una vez realizada la operación de carga
lhzx rD,rA,rB (Load Half-word and Zero indeXed) El half-word en la
dirección efectiva (rA|0)+rB se carga en los dos
bytes bajos de rD, los demás bytes de rD quedan a 0
Pág 52
Ensamblador del PowerPC con Mac OS X MacProgramadores
lhzux rD,rA,rB (Load Half-word and Zero with Update indeXed) Igual
a lhzx sólo que la dirección efectiva se guarda en rA
una vez realizada la operación de carga
lhax rD,rA,rB (Load Half-word Algebraic indeXed) El half-word en la
dirección efectiva (rA|0)+rB se carga en los dos
bytes bajos de rD, los demás bytes de rD se rellenan
con el bit más significativo del half-word cargado, es
decir, expande el signo
lhaux rD,rA,rB (Load Half-word Algebraic with Update indeXed) Igual
a lhax sólo que la dirección efectiva se guarda en rA
una vez realizada la operación de carga
lwzx rD,rA,rB (Load Word and Zero indeXed) El word en la dirección
efectiva (rA|0)+rB se carga en rD. Obsérvese que al
medir un GPR 32 bits no carga 0 en el resto del
registro si el GPR es de 32 bits, pero si lo haría si es la
instrucción se ejecuta en una máquina 64 bits
lwzux rD,rA,rB (Load Word and Zero with Update indeXed) Igual a
lwzx sólo que la dirección efectiva se guarda en rA
una vez realizada la operación de carga
Tabla 2.10: Instrucciones de carga de enteros con indireccionamiento de registro base y
registro índice
Instrucción Descripción
stbx rS,rA,rB (STore Byte indeXed) El byte menos significativo de
rS se guarda en la posición de memoria dada por
(rA|0)+rB
stbux rS,rA,rB (STore Byte with Update indeXed) Igual a stbx, sólo
que después de guardar el dato en memoria, en rA se
guarda la dirección efectiva calculada como
(rA|0)+rB
sthx rS,rA,rB (STore Half-word indeXed) El half-word menos
significativo de rS se guarda en la posición de
memoria dada por (rA|0)+rB
sthux rS,rA,rB (STore Half-word with Update indeXed) Igual a sthx,
sólo que después de guardar el dato en memoria, en
rA se guarda la dirección efectiva calculada como
(rA|0)+rB
stwx rS,rA,rB (STore Word indeXed) El valor de rS se guarda en la
posición de memoria dada por (rA|0)+rB
stwux rS,rA,rB (STore Byte with Update indeXed) Igual a stwx, sólo
que después de guardar el dato en memoria, en rA se
guarda la dirección efectiva calculada como
(rA|0)+rB
Tabla 2.11: Instrucciones de almacenamiento de enteros con indireccionamiento de registro
base y registro índice
Pág 53
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
lmw rD,d(rA) (Load Multiple Word) Carga los word almacenados a
partir de d(rA) en los registros que van desde r(D)
a r(D+n) siendo n=(31-D)
stmw rS,d(rA) (STore Multiple Word) Guarda a partir de la dirección
de memoria d(rA) los valores de los registros que
van desde r(S) a r(S+n) siendo n=(31-S)
Tabla 2.12: Instrucciones de carga y almacenamiento de multiples words
La instrucción lmw carga n words en los registros que van desde rD hasta
r31.
Pág 54
Ensamblador del PowerPC con Mac OS X MacProgramadores
.const
A: .long 3456 ; 20 enteros
.long -565
··········
.long 1767
.text
addis r2,0,ha16(A)
lmw r11,A(r2)
La instrucción carga los registros que van de r11 a r31 con los 20 números
del array A.
Instrucción Descripción
lswi rD,rA,n (Load String Word Indirect) Carga los n primeros
bytes a partir de la dirección de memoria dada por
(rA|0) en los registros que van desde rD en
adelante
stswi rS,rA,n (Store String Word Indirect) Guarda a partir de la
dirección de memoria (rA|0) los n primeros bytes
empezando a contar por el byte más significativo de
rD en adelante
lswx rD,rA,rB (Load String Word indeXed) Carga los n=XER[25-31]
primeros bytes a partir de la dirección de memoria
dada por (rA|0)+rB en los registros que van desde
rD en adelante
stswi rS,rA,rB (STore String Word indeXed) Guarda a partir de la
dirección de memoria (rA|0)+rB los n=XER[25-31]
primeros bytes empezando a contar por el byte más
significativo de rS en adelante
Tabla 2.13: Instrucciones de carga y almacenamiento de múltiples bytes (caracteres)
Pág 55
Ensamblador del PowerPC con Mac OS X MacProgramadores
.cstring
saludo: .ascii "Hola mundo!\000"
mensaje: .org 255
.text
addis r2,0,hi16(saludo)
ori r2,r2,lo16(saludo)
lswi r10,r2,12 ; Rellena los registros
; r10,r11,r12,r13
addis r2,0,hi16(mensaje)
ori r2,r2,lo16(mensaje)
addi r3,0,12
mtxer r3 ; En XER cargamos el número
; de bytes a leer
andi r3,r3,0
stswi r10,r2,r3 ; Pasa r10,r11,r12,r13 a memoria
4.6 Mnemonics
2
Aunque en castellano se pueden traducir por mnemónicos, hemos preferido mantener el
término inglés para facilitar la comprensión de la documentación
Pág 56
Ensamblador del PowerPC con Mac OS X MacProgramadores
numero = 1768937;
addis r2,0,ha16(numero)
addi r2,r2,lo16(numero)
numero = 1768937;
lis r2,ha16(numero)
li r2,lo16(numero)
numero = 1768937;
addis r2,0,ha16(numero)
addi r2,0,lo16(numero)
Pág 57
Ensamblador del PowerPC con Mac OS X MacProgramadores
numero = 1768937;
lis r2,ha16(numero)
addi r2,r2,lo16(numero)
numero = 1768937;
lis r2,hi16(numero)
ori r2,r2,lo16(numero)
SD:
.data
A: .long 45
B: .long 0
C: .long 37
·············
.text
; En r2 obtenemos la dirección base del segmento
lis r2,ha16(A)
; Hacemos que r3 apunte a A, r4 apunte a B
; y r5 apunte a C
la r3,A(r2)
la r4,B(r2)
la r5,C(r2)
Pág 58
Ensamblador del PowerPC con Mac OS X MacProgramadores
Para el estudio de las instrucciones de trabajo con enteros las hemos dividido
en los siguientes grupos:
0 34 78 11 12 15 16 19 20 23 24 27 28 31
Figura 2.3: Organización del registro CR en campos
Pág 59
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por ejemplo, si queremos copiar todos los bits del registro r2 al registro CR
haremos:
cmp CRF,L,rA,rB
cmp 2,0,r5,r6
Pág 60
Ensamblador del PowerPC con Mac OS X MacProgramadores
Bit Descripción
0 El primer operando es menor al segundo
1 El primer operando es mayor al segundo
2 Los operandos son iguales
3 Summary Overflow (SO). Hubo un overflow. Este bit es una copia del
estado final del bit XER[SO]
Tabla 2.14: Significado de los bits de los campos de CR en las instrucciones de comparación
cmp 0,r5,r6
mfcrf 128,r2 ; Copiamos el campo CR0 a r2
andi r2,4 ; Quitamos todos los bits menos el bit
; que indica que que son iguales
El valor que se guarda en CR0 viene dado por la tabla Tabla 2.15.
Pág 61
Ensamblador del PowerPC con Mac OS X MacProgramadores
Bit Descripción
0 El registro destino ha recibido un valor negativo
1 El registro destino ha recibido un valor positivo
2 El registro destino ha recibido un cero
3 Summary Overflow (SO). Hubo un overflow. Este bit es una copia del
estado final del bit XER[SO]
Tabla 2.15: Significado de los bits del campo de CR0 en las instrucciones con enteros
acabadas en punto (.)
addi. r7,r5,r6
mfcrf 128,r2 ; Copiamos el campo CR0 a r2
andi r2,4 ; Quitamos todos los bits menos el bit
; que es el que indica que r7 tiene un 0
Por último queda por comentar que el campo CR1 se suele utilizar para
reflejar el resultado de ejecutar una operación con números en punto flotante
con instrucciones de punto flotante acabadas en punto (.), como por ejemplo
fadd. o fabs., tal como muestra la tabla Tabla 2.16.
Bit Descripción
4 Floating-point eXception (FX)
5 Floating-point Enabled eXception (FEX)
6 Floating-point inValid eXception (VX)
7 Floating-point Overflow eXception (OX)
Tabla 2.16: Significado de los bits del campo de CR1 en las instrucciones en punto flotante
acabadas en punto (.)
Pág 62
Ensamblador del PowerPC con Mac OS X MacProgramadores
El registro XER es un registro que, al igual que CR, sirve para mostrar el
resultado de ejecutar una operación con enteros, nos da información sobre
posibles problemas durante la ejecución de la instrucción aritmética, así como
otras informaciones asociadas a operaciones aritméticas.
0 1 2 24 25 31
Figura 2.4: Partes del registro XER
Para cada operación aritmética que pueda producir un acarreo suelen existir
dos instrucciones, una con indicación de acarreo y otra sin ella. Por ejemplo
Pág 63
Ensamblador del PowerPC con Mac OS X MacProgramadores
Lo mismo pasa con los overflow, hay una instrucción que no lo detecta (add)
y otra que sí (addo), incluso hay una que detecta el acarreo y el overflow
(addco).
Pág 64
Ensamblador del PowerPC con Mac OS X MacProgramadores
La cual copia los bits CA, OV y SO de XER a CR para que los bits de CR se
sincronicen con los de XER, es decir, tengan el mismo valor que los bits de
XER.
Instrucción Descripción
addi rD,rA,SIMM (ADD Immediate) Calcula la suma de
(rA|0)+SIMM y la pone en rD.
addis rD,rA,SIMM (ADD Immediate Shift) Calcula la suma de
(rA|0)+(SIMM||0x0000) y la pone en rD
add rD,rA,rB (ADD) La suma rA+rB se deposita en rD
add. rD,rA,rB (ADD) Igual que add, sólo que CR0 se actualiza tal
como explicamos en el apartado 5.1
addo rD,rA,rB (ADD Overflow) Igual que add, sólo que XER[OV]
se pone a 1 si hay overflow
addo. rD,rA,rB (ADD Overflow) Igual que addo, sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
addic rD,rA,SIMM (ADD Immediate Carrying) Igual que addi sólo
que XER[CA] a se pone a 1 si hay acarreo
addic. rD,rA,SIMM (ADD Immediate Carrying) Igual que addic sólo
que CR0 se actualiza tal como explicamos en el
apartado 5.1
addc rD,rA,rB (ADD Carrying) Igual que add sólo que XER[CA]
se pone a 1 si hay acarreo
addc. rD,rA,rB (ADD Carrying) Igual que addc sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
addco rD,rA,rB (ADD Carrying with Overflow) Igual que add sólo
que si hay acarreo XER[CA] se pone a 1 y
XER[OV] se pone a 1
addco. rD,rA,rB (ADD Carrying with Overflow) Igual que addco
sólo CR0 se actualiza tal como explicamos en el
apartado 5.1
adde rD,rA,rB (ADD Extended) La suma rA+rB+XER[CA] se
pone en rD
adde. rD,rA,rB (Add Extended) Igual que adde, sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
Pág 65
Ensamblador del PowerPC con Mac OS X MacProgramadores
A todos los registros que reciben como operandos estas instrucciones se les
considera números con signo.
3
En C de GNU para PowerPC el tipo long ocupa 32 bits, debiendo usarse long long para
su correspondiente tipo de 64 bits
Pág 66
Ensamblador del PowerPC con Mac OS X MacProgramadores
En este caso primero tendremos que sumar con acarreo r3+r5 y si hay
acarreo, pasarlo a la suma r2+r4. La suma r2+r4 no la hacemos con
acarreo, ya que si hubiera acarreo este se perdería, luego en este caso vamos
a considerar al acarreo un overflow, el cual podríamos detectar para dar un
mensaje de error.
addc r7,r3,r5
Que pone la suma r3+r5 en r7, y activa el bit XER[CA] si hay acarreo.
addeo r6,r2,r4
Pág 67
Ensamblador del PowerPC con Mac OS X MacProgramadores
lwz r4,lo16(B)(r10)
lwz r5,lo16(B+4)(r10)
// Calculamos la suma en r6||r7
addc r7,r3,r5
addeo r6,r2,r4
// Guardamos el resultado que tenemos en r6||r7 en C
lis r10,ha16(C)
stw r6,lo16(C)(r10)
stw r7,lo16(C+4)(r10)
blr
Listado 2.7: Programa que suma dos números de 64 bits
r3 r4 r5 r6
r7 r8 r9 r10
Figura 2.5: Uso de instrucciones que suman dos números de 128 bits
Pág 68
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 69
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
subf rD,rA,rB (SUBtract From) Calcula rB-rA y lo deposita en
rD.
subf. rD,rA,rB (SUBtract From) Igual que subf, sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
subfo rD,rA,rB (SUBtract From with Overflow) Igual que subf,
sólo que XER[OV] se pone a 1 si hay overflow
subfo. rD,rA,rB (SUBtract From with Overflow) Igual que subfo,
sólo que CR0 se actualiza tal como explicamos en
el apartado 5.1
subfc rD,rA,rB (SUBtract From Carring with Overflow) Calcula rB-
rA y lo deposita en rD, y si hay acarreo pone
XER[CA] a 1
subfc. rD,rA,rB (SUBtract From Carring with Overflow) Igual que
subfc, sólo que CR0 se actualiza tal como
explicamos en el apartado 5.1
subfco rD,rA,rB (SUBtract From Carrying with Overflow) Igual que
subfc, sólo que XER[OV] se pone a 1 si hay
overflow
subfco. rD,rA,rB (SUBtract From Carrying with Overflow) Igual que
subfco, sólo que CR0 se actualiza tal como
explicamos en el apartado 5.1
Pág 70
Ensamblador del PowerPC con Mac OS X MacProgramadores
Al igual que en la suma, a todos los registros que reciben como operandos
estas instrucciones se les considera números con signo.
Pág 71
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
neg rD,rA (NEGate) Calcula el complemento a 2 de rA y lo
deposita en rD, es decir, calcula ~rA+1
neg. rD,rA (NEGate) Igual que neg, sólo que CR0 se actualiza
tal como explicamos en el apartado 5.1
nego rD,rA (NEGate with Overflow) Igual que neg, sólo que
XER[OV] se pone a 1 si hay overflow
nego. rD,rA (NEGate) Igual que nego, sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
Tabla 2.20: Instrucciones de negación aritmética con enteros
La instrucción mulli sólo debe usarse cuando estemos seguros de que los 16
bits altos del registro rA estén a 0, sino se producirá una perdida de datos
por desbordamiento.
Pág 72
Ensamblador del PowerPC con Mac OS X MacProgramadores
Figura 2.6: Cálculo del producto de dos números de 32 bits usando instrucciones PowerPC
Instrucción Descripción
mulli rD,rA,SIMM (MULtiply Low Immediate) Los 32 bits bajos del
producto rA*SIMM se depositan en rD.
mullw rD,rA,rB (MULtiply Low Word) Calcula los 32 bits bajos de
rA*rB. Esta instrucción se puede combinar con
mulhw para calcular un producto completo, de 64
bits
mullw. rD,rA,rB (MULtiply Low Word) Igual que mullw, sólo que
CR0 se actualiza tal como explicamos en el
apartado 5.1
mullwo rD,rA,rB (MULtiply Low Word with Overflow) Igual que
mullw, sólo que XER[OV] se pone a 1 si hay
overflow
Pág 73
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
divw rD,rA,rB (DIVide Word) El dividendo es rA, el divisor es rB,
y el cociente se deposita en rD. La instrucción no
nos da el resto de la operación.
divw. rD,rA,rB (DIVide Word) Igual que divw, sólo que CR0 se
actualiza tal como explicamos en el apartado 5.1
divwo rD,rA,rB (DIVide Word with Overflow) Igual que divw, sólo
que XER[OV] se pone a 1 si hay overflow
divwo. rD,rA,rB (DIVide Word with Overflow) Igual que divwo,
sólo que CR0 se actualiza tal como explicamos en
el apartado 5.1
divwu rD,rA,rB (DIVide Word Unsigned) Calcula la división con
números sin signo. El dividendo es rA, el divisor
es rB, y el cociente se deposita en rD. La
Pág 74
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
cmpi CRFD,L,rA,SIMM (CoMPare Immediate) Compara como números
con signo al número depositado en el registro
rA con el número SIMM con extensión de signo.
El resultado de la comparación se deposita en
CRFD
cmp CRFD,L,rA,rB (CoMPare) Compara rA y rB tratándolos como
números con signo y el resultado lo deposita en
CRFD
cmpli CRFD,L,rA,UIMM (Compare Logical Immediate) El número
depositado en el registro rA se compara con el
número 0x0000||UIMM, tratando a los
operandos como números sin signo. El resultado
de la comparación se deposita en CRFD
cmpl CRFD,L,rA,rB (CoMPare Logical) Compara a los números
depositados en rA y rB como números sin
signo. El resultado se deposita en CRFD
Tabla 2.23: Instrucciones de comparación de enteros
Pág 75
Ensamblador del PowerPC con Mac OS X MacProgramadores
Las instrucción cmpi recibe como operando un número con signo (SIMM) de
16 bits sobre el que realiza una extensión del signo a 32 bits, mientras que la
instrucción cmpli recibe como operando un número sin signo (UIMM) de 16
bits, sobre el que extiende los 16 bits altos rellenándolos con ceros.
Esto permite usar las instrucciones que reciben números con signo (cmpi y
cmp) para comparaciones aritméticas, y las instrucciones que reciben
números sin signo (cmpli y cmpl) para comparaciones lógicas.
Por ejemplo si queremos comparar como números sin signo los registros r3 y
r4 y depositar el resultado de la comparación en el campo 3 de CR haríamos:
cmp 3,0,r3,r4
cmp 0,r3,r4
La Tabla 2.24, Tabla 2.25 y Tabla 2.26 muestran las instrucciones lógicas con
enteros que existen en PowerPC.
Instrucción Descripción
andi. rD,rA,UIMM (AND Immediate) Realiza un and lógico entre rA y
0x0000||UIMM y lo deposita en rD
andis. rD,rA,UIMM (AND Immediate Shifted) Realiza un and lógico
entre rA y UIMM||0x0000 y el resultado lo
deposita en rD
Pág 76
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
ori rD,rA,UIMM (OR Immediate) Realiza un or lógico entre rA y
0x0000||UIMM y lo deposita en rD
oris rD,rA,UIMM (OR Immediate Shifted) Realiza or lógico entre rA
y UIMM||0x0000 y el resultado lo deposita en rD
or rD,rA,rB (OR) Realiza un or lógico entre rA y rB y el
resultado se deposita en rD
or. rD,rA,rB (OR) Igual que or, sólo que CR0 se actualiza tal
como explicamos en el apartado 5.1
orc rD,rA,rB (OR with complement) Realiza un or lógico entre
rA y ~rB (complemento a 1 de rB) y el resultado
lo deposita en rD
orc. rD,rA,rB (OR with Complement) Igual que orc, sólo que
CR0 se actualiza tal como explicamos en el
apartado 5.1
nor rD,rA,rB (No OR) Al resultado del or lógico entre rA y rB
se le hace el complemento a 1 y se deposita en
rD, es decir, en rD se guarda ~(rA|rB)
Tabla 2.25: Instrucciones que realizan un or lógico con enteros
Instrucción Descripción
xori rD,rA,UIMM (eXclusive OR Immediate) Realiza un xor lógico
entre rA y 0x0000||UIMM y lo deposita en rD
xoris rD,rA,UIMM (eXclusive OR Immediate Shifted) Realiza xor
lógico entre rA y UIMM||0x0000 y el resultado lo
deposita en rD
Pág 77
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 78
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
slw rD,rS,rC (Shift Left Word) Desplaza a la izquierda los bits
de rS tantas veces como diga rC (que debe ser
un número comprendido entre 0 y 31), el
resultado se copia en rD
srw rD,rS,rC (Shift Right Word) Desplaza a la derecha los bits
de rS tantas veces como diga rC (que debe ser
un número comprendido entre 0 y 31), el
resultado se copia en rD
srawi rD,rS,C (Shift Right Algebraic Word Inmediate) Desplaza a
la derecha los bits de rS tantas veces como diga C
(que debe ser un número comprendido entre 0 y
31), al resultado se le extiende el bit de signo y se
copia en rD
srawi. rD,rS,C (Shift Right Algebraic Word Inmediate) Igual que
srawi, sólo que CR0 se actualiza tal como
explicamos en el apartado 5.1
sraw rD,rS,rC (Shift Right Algebraic Word) Desplaza a la derecha
los bits de rS tantas veces como diga rC (que
debe ser un número comprendido entre 0 y 31), al
resultado se le extiende el bit de signo y se copia
en rD
sraw. rD,rS,rC (Shift Right Algebraic Word) Igual que sraw, sólo
que CR0 se actualiza tal como explicamos en el
apartado 5.1
Tabla 2.27: Instrucciones de desplazamiento con enteros
Pág 79
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 80
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
rlwinm rD,rS,N,MB,ME (Rotate Left Word Immediate theN and with
Mask) El contenido de rS se rota a la
izquierda el número de veces especificado en
N. Se genera una máscara con unos desde el
bit MB hasta el bit ME, y lo demás con ceros.
Al resultado de la rotación se le hace un and
binario con la máscara, y el resultado se
deposita en rD
rlwinm. rD,rS,N,MB,ME (Rotate Left Word Immediate theN and with
Mask) Igual que rlwinm, sólo que CR0 se
actualiza tal como explicamos en el apartado
5.1
rlwnm rD,rS,rN,MB,ME (Rotate Left Word theN and with Mask) El
contenido de rS se rota a la izquierda el
número de veces especificado en los 5 bits
bajos de rN. Se genera una máscara con
unos desde el bit MB hasta el bit ME, y lo
demás con ceros. Al resultado de la rotación
se le hace un and binario con la máscara, y el
resultado se deposita en rD
rlwnm. rD,rS,rN,MB,ME (Rotate Left Word theN and with Mask) Igual
que rlwnm, sólo que CR0 se actualiza tal
como explicamos en el apartado 5.1
rlwimi rD,rD,N,MB,ME (Rotate Left Word Immediate then Mask
Insert) El contenido de rS se rota a la
izquierda tantas veces como diga N, del
resultado se insertan los bits indicados por los
unos de la máscara en sus respectivas
posiciones del registro rD, dejando los
anteriores bits con el valor anterior que
tuvieran en rD
rlwimi. rD,rD,N,MB,ME (Rotate Left Word Immediate then Mask
Insert) Igual que rlwimi, sólo que CR0 se
actualiza tal como explicamos en el apartado
5.1
Tabla 2.28: Instrucciones de rotación con enteros
Pág 81
Ensamblador del PowerPC con Mac OS X MacProgramadores
rlwinm rD,rS,2,0,10
rlwinm rD,rS,2,0,31
Ahora la máscara va desde MB=0 hasta ME=31, es decir, abarca todos los bits
del registro y en rD obtenemos:
Y hacemos:
rlwimi rD,rS,2,0,10
Y si hacemos:
rlwimi rD,rS,2,0,31
Pág 82
Ensamblador del PowerPC con Mac OS X MacProgramadores
5.7 Mnemonics
5.7.1 Mnemonics para la resta
Mnemonic Equivalente a
subi rD,rA,SIMM addi rD,rA,-SIMM
subi. rD,rA,SIMM addi. rD,rA,-SIMM
subis rD,rA,SIMM addis rD,rA,-SIMM
subis. rD,rA,SIMM addis. rD,rA,-SIMM
subic rD,rA,SIMM addic rD,rA,-SIMM
subic. rD,rA,SIMM addic. rD,rA,-SIMM
Tabla 2.29: Mnemonic para la resta con un operando inmediato
Por otro lado las operaciones de resta reciben los operandos de una forma
poco natural, ya que reciben primero el sustraendo y luego el minuendo,
cuando lo normal es recibirlos al revés. Para facilitar la comprensión del
programa se han creado mnemonics que reciben los operandos en el orden
inverso como muestra la Tabla 2.30.
Pág 83
Ensamblador del PowerPC con Mac OS X MacProgramadores
subco rD,rA,rB subfco rD,rB,rA Igual que subc sólo que activa
el bit XER[OV] si hay overflow
subco. rD,rA,rB subfco. Igual que subco pero dejando
rD,rB,rA el CR0 el resultado de la
comparación tal como se
explicó en el apartado 5.1
Tabla 2.30: Mnemonic para resta de dos registros operandos
cmp CRF,L,rA,rB
Tal que en arquitecturas de 32 bits L siempre debe valer 0. Para evitar tener
que pasar siempre un 0 en este operando se han diseñado los mnemonics de
la Tabla 2.31:
Pág 84
Ensamblador del PowerPC con Mac OS X MacProgramadores
cmpw 2,rA,rB
Podemos poner:
cmpw cr2,rA,rB
Pág 85
Ensamblador del PowerPC con Mac OS X MacProgramadores
Existe un mnemonic que nos permite emular la operación nop (No OPeration)
mediante una llamada a la instrucción or con operandos que hacen que la
instrucción no modifique nada:
Pág 86
Ensamblador del PowerPC con Mac OS X MacProgramadores
Si (a≥0) => a
Si (a<0) => complemento2(a)
2. Hacer un xor a a con b. De esta forma si a≥0 entonces c=a pero si a<0
entonces c=complemento1(a)
De esta forma:
Pág 87
Ensamblador del PowerPC con Mac OS X MacProgramadores
; r3 contiene el valor de a
srawi r4,r3,31 ; r4 = (r3<0) ? -1 : 0
xor r5,r4,r3 ; r5 = (r3<0) ? -a : a
sub r6,r5,r4 ; r6 = (a<0) ? (-a+1) : a
Por ejemplo, supongamos que a=-6 veamos como opera el programa con los
bits:
Obsérvese que si a hubiera valido 6, r4 hubiera tenido todos sus bits a cero,
con lo que las operaciones xor y subf no hubieran afectado el valor de a
min(a,b) = (a<=b)?a:b
max(a,b) = (a>=b)?a:b
; r3 = a
; r4 = b
subc r5,r4,r3 ; r5 = r4-r3
subfe r6,r4,r4 ; r6 = (r4>r3)?0:-1
and r5,r5,r6 ; r5 = (r4>r3)?0:(r4-r3)
add r7,r3,r5 ; r7 = (r4>r3)?r3:r4
; r7 = min(r3,r4)
Pág 88
Ensamblador del PowerPC con Mac OS X MacProgramadores
; r3 = a
; r4 = b
subc r5,r4,r3 ; r5 = r4-r3
subfe r6,r4,r4 ; r6 = (r4>r3)?0:-1
andc r5,r5,r6 ; r5 = (r4>r3)?(r4-r3):0
add r7,r3,r5 ; r7 = (r4>r3)?r4:r3
; r7 = max(r3,r4)
Pág 89
Ensamblador del PowerPC con Mac OS X MacProgramadores
; r3 = a
; r4 = b
xoris r5,r3,0x8000 ; c = a+128
xoris r6,r5,0x8000 ; d = b+128
; Ahora el problema es análogo al del mínimo sin signo
subc r5,r6,r5 ; e = d-c = b-a+256 = b-a
subfe r6,r6,r6 ; f = (d>c)?0:-1
and r5,r5,r6 ; g = (d>c)?0:(d-c)
add r5,r3,r5 ; r5 = a+g
; r5 contendrá la solución
Igual que antes, remplazando and por andc (AND with Complement to 1) el
código anterior nos permite calcular max(a,b)
; r3 = a
; r4 = b
xoris r5,r3,0x8000 ; c = cambio signo a
xoris r6 ,r5,0x8000 ; d = cambio signo b
; Ahora el problema es análogo al del máximo sin signo
subc r5,r6,r5 ; e = d-c
subfe r6,r6,r6 ; f = (d>c)?0:-1
andc r5,r5,r6 ; g = (d>c)?0:(d-c)
add r5,r3,r5 ; r5 = a+g
; r5 contendrá la solución
Pág 90
Ensamblador del PowerPC con Mac OS X MacProgramadores
n = d*c+r
Donde:
n d c r
7 3 2 1
-7 3 -2 -1
7 -3 -2 1
-7 -3 2 -1
Obsérvese que según esta regla para el valor del resto que hemos dado
siempre se cumple la fórmula n=d*c+r.
El algoritmo del cálculo del resto en una división con signo se limita a aplicar
la fórmula: n=d*c+r => r=n-d*c, y es el siguiente:
; rN Dividendo
; rD Divisor
divw rT,rN,rD ; c = n/d
mullw rT,rT,rD ; c*d
sub rT,rN,rT ; r = n-c*d
Pág 91
Ensamblador del PowerPC con Mac OS X MacProgramadores
En las divisiones de número sin signo el algoritmo es similar, sólo que ahora
se usa divwu en vez de divw:
; rN Dividendo
; rD Divisor
divwu rT,rN,rD ; c = n/d
mullw rT,rT,rD ; c*d
sub rT,rN,rT ; r = n-c*d
srawi rC,rN,rK
addze rC,rC
Pág 92
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los detalles son complicados, especialmente para algunos divisores, como por
ejemplo el 7.
Pág 93
Ensamblador del PowerPC con Mac OS X MacProgramadores
Para la mayoría de los divisores, existe más de un multiplicador que nos dan
el resultado correcto con este método. En este caso, en general lo mejor es
usar el multiplicador más bajo ya que este puede implicar un desplazamiento
de cero bits a la izquierda, ahorrándonos la instrucción srawi.
Pág 94
Ensamblador del PowerPC con Mac OS X MacProgramadores
Este programa es el mismo que el de la división entre +7, excepto que usa el
multiplicador de signo opuesto, resta en vez de añadir, y desplaza c en vez
de n a la derecha 31 posiciones. (En el caso de d=+7 también podríamos
desplazar c en vez de n 31 veces a la derecha, pero habría menos
paralelismo en el código).
La Tabla 2.34 muestra los magic number y desplazamientos para los números
más comunes.
Pág 95
Ensamblador del PowerPC con Mac OS X MacProgramadores
25 51EB 851F 3
125 1062 4DD3 3
Tabla 2.34: Magic number y desplazamientos para los números más comunes
Pág 96
Ensamblador del PowerPC con Mac OS X MacProgramadores
.data
n: .long 2,1 ; Dividendo
d: .long 1,0 ; Divisor
.comm c,8 ; Cociente
.comm r,8 ; Resto
.text
.globl _main
Pág 97
Ensamblador del PowerPC con Mac OS X MacProgramadores
_main:
// Cargamos el dividendo y divisor en los registros
// Para ello usamos lswi (Load String Word
// Immediate) que carga 32 bytes consecutivos en
// dvdl-dvsh
lis r2,ha16(n)
addi r2,r2,lo16(n)
lswi dvdh,r2,16
Pág 98
Ensamblador del PowerPC con Mac OS X MacProgramadores
beq eti5
mtctr ceros_dvd ; Fijamos el contador del
; bucle
eti4:add dvdh,dvdh,dvdh ; Desplazamos uno a
; izquierda sumando
addc dvdl,dvdl,dvdl ; Si acarrea lo pasamos
; a dvdh
addze dvdh,dvdh
bdnz eti4
eti5:// Empezamos el bucle de desplazamiento
lis coch,0
lis cocl,0
lis resh,0
lis resl,0
mtctr rep ; Fijamos contador del bucle
eti6:// 1. Desplazar la combinación res:dvd 1 bit
// a la izquierda
addc dvdl,dvdl,dvdl
adde dvdh,dvdh,dvdh
adde resl,resl,resl
adde resh,resh,resh
// 2. Restar a res el divisor dvs. Esto calcula
// la resta parcial de la división.
lis tmp3,0
subc tmp1,resl,dvsl
subfe tmp2,dvsh,resh
subfe tmp3,tmp3,tmp3
cmpwi tmp3,0
beq eti7 ; Si(tmp3==0) => res>=dvs
// (res<dvs) 3. Si el resultado es negativo,
// no modificamos res
// y insertamos un cero en el bit bajo de coc
addc cocl,cocl,cocl
adde coch,coch,coch
b eti8
eti7:// (res>=dvs)
//4. Si el resultado es positivo ponemos el
// resultado en res y insertamos un uno en
// el bit bajo de coc
mr resl,tmp1
mr resh,tmp2
addc cocl,cocl,cocl
adde coch,coch,coch
ori cocl,cocl,1
eti8:// 5. Si el número de iteraciones es menor al
// ancho de dvd, volvemos al paso 1
bdnz eti6
b eti10
Pág 99
Ensamblador del PowerPC con Mac OS X MacProgramadores
lis cocl,0
mr resh,dvdh
mr resl,dvdl
// Retornamos
blr
Listado 2.12: División de 64 bits en máquinas de 32 bits
Pág 100
Ensamblador del PowerPC con Mac OS X MacProgramadores
6 Instrucciones de bifurcación
En esta sección vamos a comentar con qué instrucciones de bifurcación
cuenta PowerPC.
Por otro lado las instrucciones de bifurcación pueden ser de salto relativo o
absoluto. Las instrucciones de bifurcación de salto absoluto especifican la
dirección completa (32 bits) de la dirección de salto, obsérvese que como
todas las instrucciones de PowerPC ocupan 32 bits, la dirección absoluta de
salto no se puede codificar dentro de la instrucción, sino que debe de estar en
un registro.
Pág 101
Ensamblador del PowerPC con Mac OS X MacProgramadores
o Salto relativo
o Salto absoluto
o Salto condicional relativo
o Salto condicional absoluto
o Salto condicional al Link Register
o Salto condicional al Count Register
Instrucción Descripción
b D (Branch) Salta a la dirección calculada como la
suma de D más el valor actual del IP. Esta
instrucción tiene AA=0 y LK=0
bl D (Branch then Link) Igual que b, sólo que en el
registro LR se almacena la dirección de la
siguiente instrucción a la instrucción de salto. Esta
instrucción tiene AA=0 y LK=1
Tabla 2.36: Instrucciones de salto relativo
Pág 102
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 5 6 29 30 31
18 LI AA LK
(Codificación de la instrucción)
0 5 6 29 30 31
Exten signo LI 0 0
0 31
IP (Instruction Pointer) +
0 31
Dirección de salto
Las instrucciones de salto absoluto que vamos a ver en esta sección reciben
como operando una dirección que indica la posición absoluta a la que realizar
el salto.
0 5 6 29 30 31
18 LI AA LK
(Codificación de la instrucción)
0 5 6 29 30 31
Exten signo LI 0 0
0 31
Dirección de salto
Pág 103
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
ba D (Branch Absolute) Salta a la dirección dada en D.
Esta instrucción tiene AA=1 y LK=0
bla D (Branch then Link Absolute) Igual que ba, sólo
que en el registro LR se almacena la dirección de
la siguiente instrucción a la instrucción de salto.
Esta instrucción tiene AA=1 y LK=1
Tabla 2.37: Instrucciones de salto absoluto
ba fin
········
fin: blr
0 5 6 10 11 15 16 29 30 31
OpCode BO BI AA LK
Pág 104
Ensamblador del PowerPC con Mac OS X MacProgramadores
BI Bit CRn
Dec Bin a evaluar Descripción
0 00000 CR0[0] Negative (LT). El resultado de una instrucción con
punto (.) es negativo
1 00001 CR0[1] Positive (GT). El resultado de una instrucción con
punto (.) es positivo
2 00010 CR0[2] Zero (EQ). El resultado de una instrucción con
punto (.) es cero
3 00011 CR0[3] Summary Overflow (SO). Copia del bit XER[SO]
de la anterior instrucción ejecutada
4 00100 CR1[0] Copia de FPSCR[FX]
5 00101 CR1[1] Copia de FPSCR[FEX]
6 00110 CR1[2] Copia de FPSCR[VX]
7 00111 CR1[3] Copia de FPSCR[OX]
8 01000 CRn[0] Menor que:
12 01100 Para enteros rA<SIMM o rA<UIMM o rA<rB
16 10000 Para punto flotante fA<fB
20 10100
24 11000
28 11100
9 01001 CRn[1] Mayor que:
13 01101 Para enteros rA>SIMM o rA>UIMM o rA>rB
17 10001 Para punto flotante fA>fB
21 10101
25 11001
29 11101
10 01010 CRn[2] Igual:
14 01110 Para enteros rA=SIMM o rA=UIMM o rA=rB
18 10010 Para punto flotante fA=fB
22 10110
26 11010
30 11110
11 01011 CRn[3] Summary Overflow o floating Point Unordered
15 01111
19 10011
23 10111
27 11011
31 11111
Tabla 2.38: Configuración del operando BI
Pág 105
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los demás campos (CR2 hasta CR7) se dejaban para las operaciones de
comparación, aunque los resultados de las comparaciones también se pueden
depositar en CR0 y CR1, sin embargo en la tabla hemos supuesto que se usan
para instrucciones con punto.
En la Tabla 2.38 n se refiere a los campos de CR que van desde CR2 hasta
CR7, donde los cuatro bits de cada campo se interpretan como menor que,
mayor que, igual y overflow, respectivamente.
Cada uno de los 32 valores de la tabla indica que bit de los 32 bits del registro
CR queremos comprobar.
BO Descripción
0000y Decrementa el registro CTR y después salta si CTR≠0 y la condición
es FALSE
0001y Decrementa el registro CTR y después salta si CTR=0 y la condición
es FALSE
001zy Salta si la condición es FALSE
0100y Decrementa el registro CTR y después salta si CTR≠0 y la condición
es TRUE
0101y Decrementa el registro CTR y después salta si CTR=0 y la condición
es TRUE
011zy Salta si la condición es TRUE
1z00y Decrementa el registro CTR y después salta si CTR≠0
1z01y Decrementa el registro CTR y después salta si CTR=0
1z1zz Salta siempre
z Es un bit que se reserva para el futuro, y de momento debe ser siempre 0
y Indica si es más probable que el salto se realice o que no se realice, su uso se explica en el
Apéndice B, en principio se puede dejar siempre a 0
Tabla 2.39: Configuración del operando BO
Pág 106
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 5 6 10 11 15 16 29 30 31
16 B0 BI BD AA LK
(Codificación de la instrucción)
0 15 16 29 30 31
Sí
¿Cumple Extensión del signo BD AA LK
condición?
0 31
No + Instruction Pointer (IP)
0 31
Siguiente instrucción
0 31
Dirección de salto
Pág 107
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
bc BO,BI,D (Branch Conditional) Si se cumplen las condiciones dadas
por BI y BO salta a la dirección calculada como la suma de
D más el valor actual del IP. Esta instrucción tiene AA=0 y
LK=0
bcl BO,BI,D (Branch Conditional then Link) Igual que bc, sólo que en
el registro LR se almacena la dirección de la siguiente
instrucción a la instrucción de salto. Esta instrucción tiene
AA=0 y LK=1
Tabla 2.40: Instrucciones condicionales de salto relativo
Por ejemplo, imaginemos que queremos hacer una operación sólo si el valor
del registro r2 es menor a 5, entonces haríamos:
cmpwi r2,5
bc 12,0,fin
; Hacemos la operación que sea
······························
fin: ; Otras operaciones
······························
Instrucción Descripción
bca BO,BI,D (Branch Conditional Absolute) Si se cumplen las
condiciones dadas por BI y BO salta a la dirección dada en
D. Esta instrucción tiene AA=0 y LK=0
bcla BO,BI,D (Branch Conditional then Link Absolute) Igual que bca,
sólo que en el registro LR se almacena la dirección de la
siguiente instrucción a la instrucción de salto. Esta
instrucción tiene AA=0 y LK=1
Tabla 2.41: Instrucciones condicionales de salto absoluto
Pág 108
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 5 6 10 11 15 16 29 30 31
16 B0 BI BD AA LK
(Codificación de la instrucción)
0 15 16 29 30 31
Sí
¿Cumple 0000 0000 0000 0000 BD AA LK
condición?
No
0 31
Siguiente instrucción
0 31
Dirección de salto
Pág 109
Ensamblador del PowerPC con Mac OS X MacProgramadores
0 5 6 10 11 15 16 20 21 29 30 31
19 B0 BI 0000 528 LK
(Codificación de la instrucción)
0 29
Sí
¿Cumple CTR (CounT Register)
condición?
No 30 31
0 31 00
||
Siguiente instrucción
0 31
Dirección de salto
Instrucción Descripción
bcctr BO,BI (Branch Conditional to CounT Register) Salta a la
dirección de memoria almacenada en el CTR. Esta
instrucción tiene LK=0
bcctrl BO,BI (Branch Conditional to CounT Register then Link)
Igual que bcctr sólo que almacena en el LR la
dirección de la siguiente instrucción a la
instrucción de salto. Esta instrucción tiene LK=1
Tabla 2.42: Instrucciones condicionales de salto absoluto
Pág 110
Ensamblador del PowerPC con Mac OS X MacProgramadores
Queda por ver cómo se trata otro problema, que es el problema de que una
llamada a una subrutina llame a su vez a otra subrutina guardando esta
también en LR la dirección de retorno, y borrando la anterior dirección. Como
explicaremos en el apartado 8, la solución está en guardar el valor de LR en
la pila antes de llamar a otra función. Las instrucciones que vamos a ver
ahora son las que nos permiten retornar de la llamada.
0 5 6 10 11 15 16 20 21 29 30 31
19 B0 BI 0000 16 LK
(Codificación de la instrucción)
0 29
Sí
¿Cumple LR (Link Register)
condición?
No 30 31
0 31 00
||
Siguiente instrucción
0 31
Dirección de salto
Instrucción Descripción
bclr BO,BI (Branch Conditional to Link Register) Si se
cumplen las condiciones dadas por BI y BO salta a
la dirección dada en el registro LR. Esta
instrucción tiene LK=0
bclrl BO,BI (Branch Conditional to Link Register then Link)
Igual que bclr, sólo que en el registro LR se
Pág 111
Ensamblador del PowerPC con Mac OS X MacProgramadores
6.2 Mnemonics
Pág 112
Ensamblador del PowerPC con Mac OS X MacProgramadores
Estos mnemonics no reciben el operando BO, pero sí que tienen que recibir 2
operandos:
cmpwi cr5,r3,0
bf 22,fin
Que significa que no salte si CR5 tiene el bit de igualdad activo, es decir, si la
comparación anterior concluyó que r3 valía 0. Véase el apartado 6.1.3 para
una mejor descripción del operando BI.
Pág 113
Ensamblador del PowerPC con Mac OS X MacProgramadores
cmpwi cr5,r3,0
bf cr5+eq,fin
Donde queda mucho más claro poner cr5+eq que poner 22.
cmpwi cr0,r3,0
bf eq,fin
Pág 114
Ensamblador del PowerPC con Mac OS X MacProgramadores
Abreviatura Descripción
lt Less Than
le Less than or Equal
eq EQual
ge Greater than or Equal
gt Greater Than
nl Not Less
ne Not Equal
ng Not Greater than
so Summary Overflow
ns Not Summary Overflow
un UNordered (para comparaciones en punto flotante)
nu Not Unordered (para comparaciones en punto flotante)
Tabla 2.50: Abreviaturas para los mnemonics de comparación
Obsérvese que las instrucciones que actualizan LR se escriben igual que las
que no lo actualizan, pero se las añade una l al final. La excepción esta en
las instrucciones de tipo bcla donde la l se pone antes de la última a. Por
ejemplo, en vez de poner bleal se pone blela.
cmpwi cr2,r3,0
bge cr2,fin
; Hacer algo
············
fin: ; Otras cosas
············
Pág 115
Ensamblador del PowerPC con Mac OS X MacProgramadores
Además existen mnemonics que nos permiten acceder a ellos más fácilmente
que se muestran en la Tabla 2.51:
Mnemonic Descripción
mfctr rD (Move From CTR) Copia el contenido de CTR en rD
mtctr rS (Move to CTR) Copia el contenido de rS en CTR
mflr rD (Move From LR) Copia el contendo de LR en rD
mtlr rS (Move To LR) Copia el contenido de rS en CTR
Tabla 2.51: Mnemonics para acceso a los registro CTR y LR
Pág 116
Ensamblador del PowerPC con Mac OS X MacProgramadores
if (a>0)
{
// Hacer esto
}
else if (a<0)
{
// Hacer lo otro
}
else
{
// Hacer lo de más allá
}
Pág 117
Ensamblador del PowerPC con Mac OS X MacProgramadores
switch (x)
{
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
// Hacer algo
}
Pág 118
Ensamblador del PowerPC con Mac OS X MacProgramadores
Una tercera forma de hacer esta comparación es usando una tabla de salto,
en la cual tenemos guardadas las direcciones a las que hay que saltar para
cada caso.
switch (x)
{
case 0:
// Código del caso 0
case 1:
// Código del caso 1
case 2:
// Código del caso 2
case 3:
// Código del caso 3
case 4:
// Código del caso 4
case 5:
// Código del caso 5
·················
}
Pág 119
Ensamblador del PowerPC con Mac OS X MacProgramadores
tabla contiene las direcciones a las que hay que saltar en cada caso, lo cual
es especialmente útil cuando todos los casos son valores consecutivos que
saltan a direcciones distintas.
Para las instrucciones de salto en los bucles se han creado los mnemonics que
se resumen en la Tabla 2.53 y Tabla 2.54:
Equivale a
Condición de salto bc bca bclr
Decrementa CTR y salta si CTR≠0 bdnz bdnza bdnzlr
Decrementa CTR y salta si CTR≠0 y la condición bdnzt bdnzta bdnztlr
es true
Decrementa CTR y salta si CTR≠0 y la condición bdnzf bdnzfa bdnzflr
es false
Decrementa CTR y salta si CTR=0 bdz bdza bdzlr
Decrementa CTR y salta si CTR=0 y la condición bdzt bdzta bdztlr
es true
Decrementa CTR y salta si CTR=0 y la condición bdzf bdzfa bdzflr
es false
Tabla 2.53: Mnemonics para bucles sin actualización de LR
Equivale a
Condición de salto bc bca bclr
Decrementa CTR y salta si CTR≠0 bdnzl bdnzla bdnzlrl
Decrementa CTR y salta si CTR≠0 y la bdnztl bdnztla bdnztlrl
condición es true
Pág 120
Ensamblador del PowerPC con Mac OS X MacProgramadores
La Tabla 2.55 ayuda a recordar las abreviaturas usadas por estos mnemonics:
Abreviatura Descripción
t True
f False
d Decrement
z Zero
nz Not Zero
Tabla 2.55: Abreviaturas de los mnemonics para bucles
Todos estos mnemonics actúan sobre el registro CTR y sólo reciben como
operando la dirección a la que saltar, es decir, tienen la forma:
MNEMONIC ETIQUETA
int acumulador = 0;
int contador = 1;
do
{
acululador += contador;
contador++;
}
while (contador<=100);
li r2,0 ; r2 es el acumulador
li r3,1 ; r3 es el contador
do: add r2,r2,r3 ; r2 += r3
Pág 121
Ensamblador del PowerPC con Mac OS X MacProgramadores
li r2,0 ; r2 es el acumulador
li r3,1 ; r3 es el contador
li r4,100 ; Numero de repeticiones
mtctr r4 ; Carga el CTR
do: add r2,r2,r3 ; r2 += r3
add r3,r3,1 ; r3++
bdnz do ; Hasta que CTR llege a 0
fin:
Como ejemplo vamos a hacer un bucle que cuente la longitud de una cadena
de caracteres, tal como hace la función strlen() de C.
Pág 122
Ensamblador del PowerPC con Mac OS X MacProgramadores
for (inicialización;condición;actualización)
{
cuerpo
}
Inicialización
No
Actualización Condición Fin
Sí
Cuerpo
Como ejemplo vamos a hacer un programa que dado un número nos dice si
es primo, para ello hacemos un bucle que divida al número por todos sus
divisores y si es divisible por alguno de ellos entonces es que no es primo.
Pág 123
Ensamblador del PowerPC con Mac OS X MacProgramadores
.data
SD: .comm esprimo, 4 ; Aquí se deposita si es primo
n: .long 13 ; Número que queremos ver
; si es primo
.text
.globl _main
_main:
lis r2,ha16(SD) ; r2 apunta a la base del
; segmento de datos
lwz r3,lo16(n)(r2) ; r3 es el número a comprobar
addi r4,r3,-2; ; Calculamos el contador para CTR
mtctr r4 ; Fijamos el CTR
; Inicialización
addi r4,r3,-1 ; r4 es el contador
; Condición. Acaba si llega a 1 el contador
; significando que es primo
bucle:
cmpwi r4,1
beq primo
; Cuerpo
; Dividimos y multiplicamos r3 por r4
; Si es el mismo número es que es divisible
divw r5,r3,r4
mullw r5,r5,r4
cmpw r5,r3
beq noprimo
;Actualización
addi r4,r4,-1
bdnz bucle
primo:
li r10,1
b fin
noprimo:
li r10,0
fin: stw r10,lo16(esprimo)(r2)
blr
Podemos realizar operaciones lógicas con los bits (no los campos) del registro
CR, cuyo resultado podemos volver a guardar en otro campo de CR.
Pág 124
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
crand CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un and
binario con el bit de la posición CRBB y el
resultado se almacena en el bit CRBD
cror CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un or
binario con el bit de la posición CRBB y el
resultado se almacena en el bit CRBD
crxor CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un xor
binario con el bit de la posición CRBB y el
resultado se almacena en el bit CRBD
crnand CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un nand
binario con el bit de la posición CRBB y el
resultado se almacena en el bit CRBD
crnor CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un nor
binario con el bit de la posición CRBB y el
resultado se almacena en el bit CRBD
creqv CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un xor
binario con el bit de la posición CRBB y el
complemento a 1 del resultado se almacena
en el bit CRBD
crandc CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un and
binario con el bit de la posición CRBB y el
complemento a 1 del resultado se almacena
en el bit CRBD
crorc CRBD,CRBA,CRBB Al bit de la posición CRBA se le hace un or
binario con el bit de la posición CRBB y el
complemento a 1 del resultado se almacena
en el bit CRBD
mcrf CRD,CRS Los 4 bits del campo CRS se copian en el
campo CRD
Tabla 2.56: Operaciones lógicas con campos del registro CR
Pág 125
Ensamblador del PowerPC con Mac OS X MacProgramadores
cmpwi cr2,rA,5
cmpwi cr3,rB,3
crand 17,9,13
bng cr4,fin
; Haz algo
·············
fin: ·············
Hay que tener en cuenta que crand opera a nivel de bit de CR, no a nivel de
campo de CR, con lo que tenemos que decirle que bits origen leer y en que
bit destino depositarlo.
Como los bits de CR están ordenados como muestra la Figura 2.3, si las
comparaciones las depositamos en los campos CR2 y CR3, el bit que indica si
se cumple la condición “mayor que” es el segundo de los 4 bits del campo,
luego tendremos que leer los bits 9 y 13. Para depositar el resultado en CR4
debemos depositarlo también en el segundo bit de CR4 que es el bit 17.
Por último, bng comprueba si cr4 contiene la condición “mayor que” en cuyo
caso significa que cr2 y cr3 también cumplían la condición.
Pág 126
Ensamblador del PowerPC con Mac OS X MacProgramadores
7.1 Introducción
Respecto a los formatos de tipos de datos, PowerPC soporta sólo los tipos
simple y doble. El tipo doble extendido no lo soporta PowerPC directamente
debiéndose implementar el trabajo con números en este formato por
software.
El procesador de PowerPC tiene como tipo de dato por defecto los números
en formato doble, lo cual significa que a no ser que se lo pidamos
explícitamente todos los cálculos y los resultados se obtienen sobre datos de
tipo doble. Aun así el procesador dispone de instrucciones para convertir
entre representaciones simple y doble, así como de operaciones que nos
permiten trabajar directamente con datos en formatos simple.
Los registros FPR siempre trabajan con números en formato doble, aunque
podemos leer/almacenar en memoria tanto números en formato simple como
en formato doble. Las reglas que sigue PowerPC son las siguientes:
Pág 127
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por otro lado, el sistema de punto flotante dispone de otros dos registros que
permiten modificar el funcionamiento de la unidad de punto flotante, así
como obtener resultados de esta, que son los registros FPSCR y CR.
0 34 78 11 12 15 16 19 20 23 24 27 28 31
Flags de Flags de
Flags de
exception habilitación
summary Bits de
inválida de excepción
exception redondeo
Flags de Códigos de
exception condición
Pág 128
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 129
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 130
Ensamblador del PowerPC con Mac OS X MacProgramadores
A los bits del registro de FPSCR podemos acceder a nivel de registro, a nivel
de campo o a nivel de bit individual.
Pág 131
Ensamblador del PowerPC con Mac OS X MacProgramadores
Como es habitual, las instrucciones de la Tabla 2.58 que llevan punto (.)
producen una actualización del registro CR.
Pág 132
Ensamblador del PowerPC con Mac OS X MacProgramadores
¿Redondeo?
FI <- 0
FI <- 1
FR <- 0
¿Fración
incrementada?
FR <- 1 FR <- 0
Para que se activen los flags de excepción debemos de habilitar los llamados
flags de habilitación de excepción, de los cuales hay uno para cada tipo
principal, tal como muestra la Tabla 2.59:
Pág 133
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los bits 16-19 indican el resultado de una comparación, la cual debe activar
sólo uno de los cuatro bits < (menor que), > (mayor que), = (igual) ó ? (sin
relación de orden).
Los bits 16-19 combinados con el bit 15 (bit de clase) nos pueden servir para
saber a que clase pertenece el resultado de una instrucción de punto flotante
(número normalizado, número denormalizado, cero, NaN o infinito).
Pág 134
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por ejemplo, para saber de qué tipo es el número que obtenemos como
resultado de una suma en punto flotante podríamos hacer un programa tal
que así:
Pág 135
Ensamblador del PowerPC con Mac OS X MacProgramadores
denormal:
; f0 es un número denormalizado
7.4 El registro CR
La Tabla 2.62 muestra cuáles son los bits del registro FPSCR que se copian al
registro CR en caso de usar instrucciones con punto.
Bit Descripción
4 Contiene el valor del bit FX del registro FPSCR que indica que alguna
excepción se ha producido
5 Contiene el valor del bit FEX del registro FPSCR que indica que
alguna excepción para la que su flag de habilitación de excepción
estaba encendido se ha producido
6 Contiene el valor del bit VX del registro FPSCR que indica que alguna
invalid exception se ha producido
7 Contiene el valor del bit OX del registro FPSCR que indica que se ha
producido un desbordamiento
Tabla 2.62: Bits del registro FPSCR copiados al registro CR
El valor del campo CR1 del registro CR se puede consultar tras ejecutar una
instrucción para ver si se ha producido una excepción de la siguiente manera:
Pág 136
Ensamblador del PowerPC con Mac OS X MacProgramadores
fadd. f0,f1,f2
bt 5,excepcion ; Si FEX está activo
; No ha habido excepcion
·············
·············
excepcion:
mcrfs 2,1 ; Copia FPSCR[4-7] a CR2
bt 6,invalid ; Miramos los bits de CR para ver que
bt 7,overflow ; tipo de excepción se ha producido
bt 8,underflow
bt 9,divbyzero
bt 10,inexact
invalid:
mcrfs 2,2 ; Copia FPSCR[8-11] a CR2
mcrfs 3,3 ; Copia FPSCR[12-15] a CR3
mcrfs 4,5 ; Copia FPSCR[20-23] a CR4
; Ahora podemos saber el tipo exacto de invalid
; operation en base al flag de excepción invalid
; operation que esté activo
overflow:
; Se ha producido un overflow
underflow:
; Se ha producido un underflow
divbyzero:
; Se ha intentado dividr entre cero
inexact:
; Redondeo inexacto
PowerPC permite tanto usar flags de habilitación de traps, como usar flags de
habilitación de excepción, será el diseñador del sistema operativo quien deba
tomar esta decisión.
La Tabla 2.63 describe los valores que pueden tomar los flags FE0 y FE1:
Pág 137
Ensamblador del PowerPC con Mac OS X MacProgramadores
Antes de que PowerPC pueda operar con un dato en punto flotante situado en
memoria, debe de cargarlo en alguno de los FPR. Análogamente PowerPC
puede depositar los datos en memoria una vez que acaba de trabajar con
ellos.
Como se explicó en el aparatado 7.2, los registros FPR siempre trabajan con
números en formato doble, aunque podemos leer/almacenar en memoria
tanto números en formato simple como en formato doble.
Las instrucciones de acceso a memoria para punto flotante (al igual que
pasaba con las de acceso a memoria con enteros) se pueden dividir en dos
tipos:
Pág 138
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
lfs fD,d(rA) (Load Floating-point Single) El word en la dirección de
memoria d(rA) se interpreta como un número en
punto flotante de precisión simple, y se carga en fD
convertido a punto flotante de precisión doble
lfsu fD,d(rA) (Load Floating-point Single with Update) Igual a lfs,
sólo que rA se actualiza con el valor de d(rA)
después de leer la memoria
lfd fD,d(rA) (Load Floating-point Double) El doble-word en la
dirección de memoria d(rA) se carga en fD
lfdu fD,d(rA) (Load Floating-point Double with Update) Igual a
lfd, sólo que rA se actualiza con el valor de d(rA)
después de leer la memoria
Tabla 2.64: Instrucciones de carga de números en punto flotante con indireccionamiento de
registro base e índice inmediato
Instrucción Descripción
sfs fD,d(rA) (Store Floating-point Single) El contenido de fD se
convierte a precisión simple y se guarda en el word de
la dirección de memoria apuntada por d(rA)
sfsu fD,d(rA) (Store Floating-point Single with Update) Igual a sfs,
sólo que rA se actualiza con el valor de d(rA)
después de escribir la memoria
sfd fD,d(rA) (Store Floating-point Double) El contenido de fD se
guarda en memoria, en el doble-word apuntado por
d(rA)
sfdu fD,d(rA) (Store Floating-point Double with Update) Igual a
sfd, sólo que rA se actualiza con el valor de d(rA)
después de escribir la memoria
Tabla 2.65: Instrucciones de almacenamiento de números en punto flotante con
indireccionamiento de registro base e índice inmediato
Instrucción Descripción
lfsx fD,rA,rB (Load Floating-point Single indeXed) El word en la
dirección de memoria (rA|0)+rB se interpreta como
un número en punto flotante de precisión simple, y se
Pág 139
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
sfsx fD,rA,rB (Store Floating-point Single indeXed) El contenido de
fD se convierte a precisión simple y se guarda en el
word de la dirección de memoria apuntada por
(rA|0)+rB
sfsux fD,rA,rB (Store Floating-point Single with Update indeXed)
Igual a sfsx, sólo que rA se actualiza con el valor de
(rA|0)+rB después de escribir la memoria
sfdx fD,rA,rB (Store Floating-point Double indeXed) El contenido de
fD se guarda en memoria, en el doble-word apuntado
por (rA|0)+rB
sfdux fD,rA,rB (Store Floating-point Double with Update indeXed)
Igual a sfdx, sólo que rA se actualiza con el valor de
(rA|0)+rB después de escribir la memoria
Tabla 2.67: Instrucciones de almacenamiento de números en punto flotante con
indireccionamiento de registro base y registro índice
o Suma
o Resta
o Multiplicación
o Multiplicación-suma
o División
o Raíz cuadrada (opcional)
o Redondeo a entero (opcional)
Pág 140
Ensamblador del PowerPC con Mac OS X MacProgramadores
Las dos últimas son operaciones opcionales, lo que significa que no todos los
micros las poseen, debemos de consultar el manual del microprocesador para
ver si la soporta.
Pág 141
Ensamblador del PowerPC con Mac OS X MacProgramadores
fA/fB
fsqrt fD,fS (Floating SQuare RooT) en fD Doble
fsqrt. fD,fS obtenemos la raíz cuadrada de fS.
Esta operación es opcional
fsqrts fD,fS (Floating SQuare RooT Single) En fD Simple
fsqrts. fD,fS obtenemos la raíz cuadrada de fS.
Esta operación es opcional
fres fD,fS (Floating Reciprocal Estimate Simple) Simple
fres. fD,fS En fD obtenemos 1/fS. Esta
operación es opcional. No existe su
correspondiente operación para
números de precisión doble
frsqrte fD,fS (Floating Reciprocal SQuare Root Doble
frsqrte. fD,fS Estimate) En fD obtenemos
1/sqrt(fS). Esta operación es
opcional. No existe su
correspondiente operación para
números con precisión simple
fsel fD,fA,fB,fC (Floating Select) El valor de fA se Doble
fsel. fD,fA,fB,fC compara con 0. Si fA es mayor o
igual que 0, fB se deposita en fD,
sino fC se deposita en fD. La
comparación ignora el signo de 0 (+0
ó -0). Esta operación es opcional.
Tabla 2.68: Instrucciones aritméticas
Todas ellas disponen de una versión con punto (.) que actualiza el registro
CR.
Casi todas las operaciones se proporcionan tanto para precisión simple como
para precisión doble. Las instrucciones de precisión simple se diferencian
porque tienen una s al final de su nombre.
; f1 = 7.0
; f2 = 2.0
fdiv f0,f1,f2 ; f3 = 3.5
Pág 142
Ensamblador del PowerPC con Mac OS X MacProgramadores
Instrucción Descripción
frsp fD,fS (Floating Round to Single Precision) Redondea el
frsp. fD,fS dato almacenado en fS al número más cercano que
pueda ser representado en formato simple, y los
guarda en fD (en formato doble)
fctiw fD,fS (Floating Convert To Integer Word) El número
fctiw. fD,fS almacenado en fD lo convierte a entero de 32 bits,
usando el modo de redondeo activo, y lo deposita en
los bits fD[32-63], quedando los bits fD[0-31]
indefinidos.
fctiwz fD,fS (Floating Convert To Integer Word round toward
fctiwz. fD,fS Zero) El número almacenado en fD lo convierte a
entero de 32 bits eliminando los decimales, y lo
deposita en los bits fD[32-63], quedando los bits
fD[0-31] indefinidos.
Tabla 2.69: Instrucciones de conversión
Pág 143
Ensamblador del PowerPC con Mac OS X MacProgramadores
Bit Significado
0 fA < fB
1 fA > fB
2 fA = fB
3 fA ? fB (unordered)
Tabla 2.70: Reglas de activación de los campos del registro CR
Además de los bits del campo CR que especifiquemos, los bits FPSCR[16-19]
también se activan convenientemente.
Instrucción Descripción
fcmpo CRFD,fA,fB (Floating CoMPare Ordered) Compara fA con fB,
produciendo una VXVC si alguno de los operandos es
un NaN. El resultado se deposita en el campo de CR
dado por CRFD.
fcmpu CRFD,fA,fB (Floating CoMPare Unordered) Compara fA con fB,
pudiendo ser alguno de los operandos en un NaN. El
resultado se deposita en el campo de CR dado por
CRFD.
Tabla 2.71: Instrucciones de comparación
Pág 144
Ensamblador del PowerPC con Mac OS X MacProgramadores
Estas instrucciones no alteran el registro FPSCR, y sólo las que tienen punto
(.) alteran el registro CR y se detallan en la Tabla 2.72.
Instrucción Descripción
fmr fD,fS (Floating Move Register) Copia el contenido de fS a
fmr. fD,fS fD
fneg fD,fS (Floating Negate) Copia el contenido de fS a fD y
fneg. fD,fS cambia el signo durante la copia
fabs fD,fS (Floating ABSolute value) Copia el contenido de fS a
fabs. fD,fS fD y pone el bit de signo a 0 durante la copia
fnabs fD,fS (Floating Negate ABSolute value) Copia el contenido
fnabs. fD,fS de fS a fD y pone el bit de signo a 1 durante la copia
Tabla 2.72: Instrucciones de movimiento de datos
Pág 145
Ensamblador del PowerPC con Mac OS X MacProgramadores
#include <stdio.h>
int main () {
asm ( "addis r2,r3,1 \n sub r5,r6,r7" );
return 0;
}
Si ahora hiciésemos:
$ gcc -S cyasm.c
#include <stdio.h>
int G=4;
int main () {
asm ( "addis r2,0,ha16(_G) \n lwz r3,lo16(_G)(r2) \n"
"addi r3,r3,1 \n stw r3,lo16(_G)(r2)" );
Pág 146
Ensamblador del PowerPC con Mac OS X MacProgramadores
A las variables locales no se les asigna nombre, con lo que tenemos que usar
otras técnicas para acceder a ellas desde ensamblador, como veremos en
breve.
Los nombres que usa C++ para estas funciones son _suma__Fii y
_suma__Fiii respectivamente.
Para poder saber el nombre que da a los símbolos C++ podemos usar el
comando nm (Name Mangling), que recibe como argumento un fichero .o, o
un fichero ejecutable (con información de depuración), y nos muestra los
símbolos que contiene:
$ nm cyasm.o
0000007c D _G
000000a0 s ___FRAME_BEGIN__
00000000 T _main
U _printf
U _suma__Fii
U _suma__Fiii
U dyld_stub_binding_helper
Pág 147
Ensamblador del PowerPC con Mac OS X MacProgramadores
#include <stdio.h>
int main () {
int dividendo=14;
int divisor=3;
int cociente;
asm ( "divw %0,%1,%2" : "=r" (cociente)
: "r" (dividendo) , "r" (divisor));
printf("El resultado de la división es %i",cociente);
return 0;
}
Pág 148
Ensamblador del PowerPC con Mac OS X MacProgramadores
int ret;
asm ("li r0,0x6009\n"
"sc\n"
"mr %0,r3\n"
: "=r" (ret) /* operando de salida */
: /* no hay operandos de entrada*/ );
Cada operando lleva asociadas unas constraints que indican el tipo del
operando según la Tabla 2.73:
Constraint Significado
r Registro GPR
b Registro GPR distinto de r0
f Registro FPR
m Referencia a memoria
i Operando inmediato entero. Son literales cuyo valor es
conocido en tiempo de compilación
F Operando inmediato en punto flotante de doble precisión. Son
literales cuyo valor es conocido en tiempo de compilación
X Se acepta un operando de cualquier tipo: registro, dirección de
memoria o operando inmediato.
Tabla 2.73: Constraints de una expresión C
Modificador Significado
= Operando de sólo escritura. No se garantiza que contenga el
valor previo de la variable
+ Operando de lectura/escritura. Antes de usarse va a contener
el valor de la variable o expresión, y después de ejecutarse las
instrucciones ensamblador su valor se guardará
apropiadamente
& No asignar el mismo registro al operando de entrada y de
salida
Tabla 2.74: Modificadores de una constraint
Pág 149
Ensamblador del PowerPC con Mac OS X MacProgramadores
addi rD,(rA|0),SIMM
addi r3,r0,1
En este caso debemos de usar la constraint b, que significa usar uno de los
registros de r1 a r31. Con lo que el problema no se producirá. Es decir la
forma correcta de codificar la instrucción anterior es:
lis r9,r31,ha16(_N)
addi r9,lo16(_N)(r9)
lwz r3,0(r9)
Pág 150
Ensamblador del PowerPC con Mac OS X MacProgramadores
#include <stdio.h>
int N=4;
int main () {
asm ( " addi %0,%0,1 " : "=r" (N) );
printf("N incrementada vale %i",N);
return 0;
}
#include <stdio.h>
int N=4;
int main () {
asm ( " addi %0,%0,1 " : "+r" (N) );
printf("N incrementada vale %i",N);
return 0;
}
Otra forma, más compleja pero igual de válida, de resolver este problema es
declarar dos operandos, uno de lectura y otro de escritura. La conexión entre
estos debe de expresarse con constraints que indican que ambos deben de
estar en el mismo registro cuando la instrucción se ejecute.
#include <stdio.h>
int N=4;
int main () {
asm ( " addi %0,%1,1 " : "=r" (N) :"0" (N) );
printf("N incrementada vale %i",N);
return 0;
}
Pág 151
Ensamblador del PowerPC con Mac OS X MacProgramadores
Otra cosa importante es que podemos evitar los efectos laterales que se
producirían si el programa C estuviese usando uno de los registros que
usamos desde ensamblador. Por ejemplo, esta instrucción daría problemas si
el registro r3 estuviese siendo usado por el programa C.
Pág 152
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por último debemos comentar que la directiva asm supone que las
instrucciones que estamos ejecutando no tienen más efectos laterales que el
de modificar los operandos de salida. Esto no significa que no podamos usar
instrucciones con efectos laterales, sino que debemos tener cuidado con las
optimizaciones que pudiera hacer el compilador, ya que si los operandos de
salida no se usan en ningún punto del programa el optimizador del
compilador podría eliminar nuestras instrucciones ensamblador. También
podría aplicar otras optimizaciones como sacarlas fuera de un bucle,
remplazar dos instrucciones que calculan una subexpresión por una sola
guardando el operando de salida en un registro y ejecutar la instrucción una
sola vez.
#include <stdio.h>
int main () {
int dividendo=14;
int divisor=3;
int cociente;
asm ( "divw %[c],%[n],%[d]"
: [c] "=r" (cociente)
: [n] "r" (dividendo)
, [d] "r" (divisor));
printf("El resultado de la división es %i",cociente);
return 0;
}
Pág 153
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los nombres simbólicos que damos a los operandos no tienen por qué
coincidir con los nombres de las variables C a las que los asociamos.
9 Llamada a funciones
Vamos a ver ahora cuál es el mecanismo de llamada a funciones en Mac OS
X. Esto nos va a permitir poder llamar a funciones escritas en otros lenguajes,
como p.e. C, desde ensamblador, o viceversa, poder llamar a funciones
escritas en ensamblador desde C.
Además de estos tipos la Tabla 2.76 muestra los tipos de datos para AltiVec.
Pág 154
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 155
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 156
Ensamblador del PowerPC con Mac OS X MacProgramadores
Variables locales
Callee
Área de parámetros
Área de enlace
GPR1
Pág 157
Ensamblador del PowerPC con Mac OS X MacProgramadores
Cada vez que una función llama a otra se crea en la pila un nuevo frame, el
cual almacena toda la información que necesita el procedimiento para sus
autogestión.
A esta área se la considera volátil en el sentido de que una vez que llamamos
a un procedimiento, éste si quiere puede modificar el valor de los parámetros
aquí depositados, esto se hace, por ejemplo, cuando una función como parte
de un cálculo que está llevando a cabo, modifica el valor de sus parámetros,
depositando en ellos valores intermedios que necesita para calcular un valor
final.
Los valores de este área lo fija en parte el caller (al que pertenece el área de
enlace) y en parte el callee, en cada llamada que le hagamos. En concreto
aquí encontramos:
o Offset 0: Back chain. El caller (el dueño del área) guarda aquí el valor
del puntero a pila antes de que el callee lo decremente para crear un
nuevo frame.
o Offset 4: El callee guarda aquí el valor del registro CR. Este valor sólo
tiene que guardarlo el callee si modifica algún campo no volátil de CR
(CR2-CR4 son los no volátiles) durante su ejecución.
o Offset 8: El callee guarda aquí la dirección de retorno al caller, es decir,
el valor del registro LR. Este valor lo guarda el callee sólo si el callee
Pág 158
Ensamblador del PowerPC con Mac OS X MacProgramadores
Obsérvese que el área de enlace está en una posición fija que el callee puede
conocer (a un determinado offset de la posición del puntero a la cima del
frame del caller). Esto es necesario para que el callee pueda acceder a la
información del área de enlace, así como al área de parámetros, que está
inmediatamente después del área de enlace. A estos datos debe de acceder el
callee antes de decrementar el puntero a pila (crear su frame), es decir, el
callee debe recoger los parámetros y fijar los valores del área de enlace,
antes de crear su frame.
Pág 159
Ensamblador del PowerPC con Mac OS X MacProgramadores
stwu r1,-tamanoFrame(r1)
Pág 160
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por último vamos a ver que realmente el compilador gcc de Mac OS X actúa
como aquí hemos explicado. Para ello vamos a crear un fichero llamado
llamadas.c que aparece en el Listado 2.13:
void funcion_b(void)
{
}
void funcion_a()
{
Pág 161
Ensamblador del PowerPC con Mac OS X MacProgramadores
funcion_b();
}
int main ()
{
funcion_a();
return 0;
}
Listado 2.13: Ejemplo de funciones
$ gcc -S llamadas.s
Usando la versión 2.95.2 del compilador obtenemos una salida como la del
Listado 2.14 (la cual puede variar ligeramente en otra versión del
compilador):
.text
.align 2
.globl _funcion_b
_funcion_b:
; Prologo
stmw r30,-8(r1) ; Guarda r30 y r31 en su área de
; registro guardados
stwu r1,-48(r1) ; Crea su frame de 48 bytes
; (3*16 bytes)
mr r30,r1 ; Pone el puntero a pila en r30
L6:
; Epílogo
lwz r1,0(r1) ; Recoge el puntero a pila del
; área de enlace del caller
lmw r30,-8(r1) ; Recupera los valores de r30 y r31
blr ; Retorna
.align 2
.globl _funcion_a
_funcion_a:
; Prólogo
mflr r0 ; Recoge en r0 el LR
stmw r30,-8(r1) ; Guarda r30 y r31 en su área de
; registro guardados
stw r0,8(r1) ; Guarda el LR en el área de enlace
; del caller
stwu r1,-80(r1) ; Crea su frame de 80 bytes
; (5*16 bytes)
mr r30,r1 ; Pone el puntero a pila en r30
; Llamada
bl _funcion_b
Pág 162
Ensamblador del PowerPC con Mac OS X MacProgramadores
L7:
; Epílogo
lwz r1,0(r1) ; Recoge el puntero a pila del
; área de enlace del caller
lwz r0,8(r1) ; Recoge el LR del área de enlace
; del caller
mtlr r0 ; Fija la dirección de retorno
lmw r30,-8(r1) ; Recupera los valores de r30 y r31
blr ; Retorna
.align 2
.globl _main
_main:
; Prólogo
mflr r0
stmw r30,-8(r1) ; Guarda r30 y r31 en su área de
; registros guardados
stw r0,8(r1) ; Guarda LR en el área de enlace
; del caller
stwu r1,-80(r1) ; Crea su frame de 80 bytes
; (5*16 bytes)
mr r30,r1 ; Pone el puntero a pila en r30
; Llamada
bl _funcion_a
; Epílogo
li r3,0 ; Pone un 0 en el retorno de la
main()
b L8
L8:
lwz r1,0(r1) ; Recupera el puntero a pila del
; área de enlace de su caller
lwz r0,8(r1) ; Recupera el LR del área de enlace
; de su caller
mtlr r0
lmw r30,-8(r1) ; Restaura los registros r30 y r31
blr ; Retorna
Listado 2.14: Código ensamblador generado por gcc
Pág 163
Ensamblador del PowerPC con Mac OS X MacProgramadores
.text
.align 2
.globl _funcion_b
_funcion_b:
blr
.align 2
.globl _funcion_a
_funcion_a:
b _funcion_b
.align 2
.globl _main
_main:
mflr r0
stw r0,8(r1)
stwu r1,-64(r1)
bl _funcion_a
li r3,0
lwz r0,72(r1)
la r1,64(r1)
mtlr r0
blr
Listado 2.15: Código ensamblador generado por gcc optimizado
Esto aunque habitual no es obligatorio, ya que las posiciones que están más
allá del puntero a pila, que es lo que se llama la zona vacía (véase Figura
2.18), están sin usar y si el procedimiento lo desea también puede usarlas.
Pág 164
Ensamblador del PowerPC con Mac OS X MacProgramadores
Zona
El procedimiento de paso de parámetros vacía
que vamos a ver es el que define Mac OS X
para C. Para C++ y Objective-C estos
mecanismos varían ligeramente.
Pág 165
Ensamblador del PowerPC con Mac OS X MacProgramadores
struct Parametros
{
int pi1;
float pf2; +44
ps9
double pd3; +40
short ps4; pf8
double pd5; +36
ps7
char pc6; +32
short ps7; pc6
float pf8; +28
short ps9; pd5
};
+20
ps4
Esta estructura sirve como plantilla +16
para construir el área de parámetros
de la pila. El elemento que acaba en pd3
la dirección de memoria más baja es +8
pi1, y a partir de ahí van ocupando pf2
direcciones de memoria positivas a lo +4
pi1
largo del área de memoria, 0
respetando las reglas de padding que Zona vacía
hemos dado. Luego la organización
exacta de los parámetros sería la de Figura 2.19: Ejemplo de organización
la Figura 2.19. de parámetros en la pila
Pág 166
Ensamblador del PowerPC con Mac OS X MacProgramadores
+44
ps9
+40
pf8
+36
ps7 FPR4
+32
pc6 GPR10
+28
GPR9
pd5 FPR3
GPR8
+20
ps4 GPR7
+16
GPR6
pd3 FPR2
GPR5
+8
pf2 GPR4 FPR1
+4
pi1 GPR3
0
Zona vacía
Por último respecto a los parámetros que sean vectores (AltiVec) estos se
pasan en los registros v2 a v13, y en el caso de los vectores, su presencia no
afecta a los registros GPR ni FPR. El caller no debe reservar espacio en el área
de parámetros de la pila a no ser que su número exceda el número de
parámetros que podemos pasar en los registros de AltiVec.
Pág 167
Ensamblador del PowerPC con Mac OS X MacProgramadores
double s = suma(3,4.5,6.7,3.2);
double* p = (double*)(&n+1);
Pág 168
Ensamblador del PowerPC con Mac OS X MacProgramadores
Cuando una función retorna un valor, la forma de devolverlo depende del tipo
del valor retornado:
9.6 Ejemplo
.set tamanoFrame,16
.text
.align 2
.globl _factorial
_factorial:
; Prólogo
mflr r0 ; Recoge en r0 el LR
stw r0,8(r1) ; Guarda el LR en el área
; de enlace del caller
stwu r1,-tamanoFrame(r1) ; Crea su frame
Pág 169
Ensamblador del PowerPC con Mac OS X MacProgramadores
; Cuerpo de la función
cmpwi r3,1 ; Si (n>1)
bgt sigue
li r3,1 ; Retorna 1
b epilogo
sigue:
stw r3,tamanoFrame+12(r1) ; Guarda r3 en el área de
; parámetros del padre
; para poder hacer otra
; llamada recursiva
subi r3,r3,1 ; Decrementa n
bl _factorial ; Llama a factorial
mr r4,r3 ; Recoge el retorno y
; lo guarda en r4
lwz r3,tamanoFrame+12(r1) ; Recupera el parámetro
; del área de enlace
; del padre
mulhw r5,r3,r4 ; Calcula n*factorial(n-1)
cmpwi r5,0 ; Si hay acarreo
bne acarreo ; devolvemos 0
mullw r3,r3,r4 ; r3 = n*factorial(n-1)
b epilogo
acarreo:
li r3,0
epilogo:
; Epílogo
lwz r1,0(r1) ; Recoge el puntero a pila
; de su área de enlace
; con lo que destruye
; el frame
lwz r0,8(r1) ; Recoge el LR del área de
; enlace del caller
mtlr r0 ; Fija la dirección de
; retorno
blr ; Retorna
Listado 2.16: Llamada a una función C
Pág 170
Ensamblador del PowerPC con Mac OS X MacProgramadores
#include <stdio.h>
int main()
{
int n=100002;
int sol = factorial(n);
printf("El factorial de %i es %i",n,sol);
return 0;
}
Listado 2.17: Función llamada desde ensamblador
Pág 171
Apéndice A
Aritmética binaria
Sinopsis:
Aunque, como se dijo en el prólogo, este libro presupone que el lector está
familiarizado con la representación binaria y su aritmética, un repaso podría
ayudar a un lector que llevase algún tiempo sin tocar este tema.
4
En castellano muchas veces se les llama coma fija y coma flotante, ya que en castellano el
delimitador de la parte fraccionaria es la coma y no el punto
Ensamblador del PowerPC con Mac OS X MacProgramadores
ai bi ci si ci+1
0 0 0 0 0
0 1 0 1 0
1 0 0 1 0
1 1 0 0 1
0 0 1 1 0
0 1 1 0 1
1 0 1 0 1
1 1 1 1 1
Tabla A.1: Proceso de suma de números binarios
Por ejemplo para sumar 23 y 56, primero los pasamos a binario, y después
aplicando la regla anterior tenemos:
Pág 173
Ensamblador del PowerPC con Mac OS X MacProgramadores
si=ai*(~bi) + (~ai)*bi
ci+1=ai*bi.
El bit menos significativo entra por el sumador más a la derecha. Vemos que
la salida del i-ésimo sumador alimenta el acarreo del sumador (i+1)-ésimo.
Como el acarreo de orden inferior es 0, el primer sumador basta con que sea
un semisumador. Sin embargo, más tarde veremos que inicializar el bit de
acarreo de orden inferior a 1, es útil para realizar la resta.
Pág 174
Ensamblador del PowerPC con Mac OS X MacProgramadores
La resta actúa de forma parecida a la suma, sólo que ahora cuando el bit del
minuendo es 0 y el bit de sustraendo es 1, en vez de “pasar” un bit al dígito
de mayor peso, se le “pide” un bit.
ai bi ci si ci+1
0 0 0 0 0
0 1 0 1 1
1 0 0 1 0
1 1 0 0 0
0 0 1 1 1
0 1 1 0 1
1 0 1 0 0
1 1 1 1 1
Tabla A.2: Proceso de resta de números binarios
Por ejemplo para calcular 56-23, primero los pasamos a binario, y después
aplicando la regla anterior tenemos:
Ya en el bit más a la derecha vemos que hemos tenido que pedir al nivel
superior, y el acarreo de petición se ha mantenido hasta el cuarto bit
empezando a contar por la derecha.
Pág 175
Ensamblador del PowerPC con Mac OS X MacProgramadores
(minuendo) 14 1111
(sustraendo) 7 - 0111 -
(diferencia) 7 0111
3. Descartar el overflow
1110 (minuendo)
+ 1001 (sustraendo en complemento a 2)
10111
0 - Suma
1 - Resta
00100010 (34)
x 01000011 (67)
————————
00100010
00100010
00000000
00000000
00000000
00000000
00100010
00000000
———————————————
000100011100110
El multiplicador hardware más sencillo opera sobre dos números sin signo
produciendo cada vez un bit como muestra la Figura A.4. Los números que
vamos a multiplicar son an-1...a1a0 y bn-1...b1b0 los cuales se colocan en
los registros A y B (con el bit menos significativo a la derecha, como es
habitual). El registro P se pone inicialmente a cero:
Pág 177
Ensamblador del PowerPC con Mac OS X MacProgramadores
Desplazamiento
P A
B 1 bit
n bits
Desplazamiento
P A
B 1 bit
n bits
Pág 178
Ensamblador del PowerPC con Mac OS X MacProgramadores
Inicialmente tendremos:
Pasos 1-9:
Como los 9 bits más a la izquierda de A son ceros, P recibirá 9 bits 0 y P-B
siempre será negativo con lo que el programa se limitará a desplazar los
ceros a la izquierda obteniendo:
Pág 179
Ensamblador del PowerPC con Mac OS X MacProgramadores
10º paso:
Desplazamos
11º paso:
Desplazamos
12º paso:
Desplazamos
13º paso:
Desplazamos
14º paso:
Desplazamos
Pág 180
Ensamblador del PowerPC con Mac OS X MacProgramadores
15º paso:
Desplazamos
16º paso:
Desplazamos
Pág 181
Ensamblador del PowerPC con Mac OS X MacProgramadores
00011011 (27)
11100100 (complemento a 1)
1 +
————————
11100101 (-27)
11100101 (-27)
00011010 (complemento a 1)
1 +
————————
00011011 (27)
00010001 (17)
11101110 (complemento a 1)
1 +
————————
11101111 (-17)
00100010 (34)
11101111 (-17) +
————————
100010001 (17)
Pág 182
Ensamblador del PowerPC con Mac OS X MacProgramadores
00100010 (+34)
11101111 (-17) -
————————
100110011 (+51)
(-80)+(-120) tendremos:
10110000 (-80)
10001000 (-120) +
————————
100111000 (56)
Pág 183
Ensamblador del PowerPC con Mac OS X MacProgramadores
Flag Descripción
SO (Summary Overflow) Se activa cuando hay un overflow y queda
activo hasta que lo desactivamos explícitamente con mtxer. Es útil
para saber si durante la ejecución de una serie de instrucciones
hubo un overflow
OV (OVerflow) Indica si la última operación aritmética produjo
overflow
CA (Carry) Indica si la última operación aritmética produjo acarreo
Tabla A.3: Flags de excepción en PowerPC
Pág 184
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 185
Ensamblador del PowerPC con Mac OS X MacProgramadores
Sin embargo sólo hay una representación no entera cuyo uso se ha extendido
ampliamente, y es la representación en punto flotante. En este sistema, la
representación de un número se divide en tres partes: un signo, un
exponente y una mantisa. Y el valor del número así representado se
calcula como:
Aunque esta fórmula no vale para calcular números en binario, si que nos
será útil en los ejemplos ya que las personas estamos más familiarizadas con
números en base 10.
Obsérvese que la mantisa nunca tiene signo, ya que el signo se separa aparte
en el campo destinado a tal propósito, sin embargo el exponente siempre es
un número con signo.
Pág 186
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 187
Ensamblador del PowerPC con Mac OS X MacProgramadores
mantisa = 1,0010110
exponente = 11111110 (-2)
Pág 188
Ensamblador del PowerPC con Mac OS X MacProgramadores
De los cuatro formatos definidos por el IEEE 754, sólo el formato simple es
obligatorio de implementar, el formato doble es recomendado y todas las
implementaciones de IEEE 754 existentes lo implementan. Por último los
formatos simple extendido y doble extendido sólo los tienen algunas
implementaciones. PowerPC implementa los formatos simple, doble y doble
extendido, pero no el simple extendido.
El tamaño de los campos para los formatos simple y doble está estandarizado
por el IEEE 754 y son los que se muestran el la Tabla A.5, pero el tamaño de
los campos para los formatos simple extendido y doble extendido no están
estandarizados por el IEEE 754, sino que el IEEE754 sólo da unos tamaños
mínimos para cada campo.
Pág 189
Ensamblador del PowerPC con Mac OS X MacProgramadores
1b 15b 112b
16 B
Explicit
Sin usar Signo Exponente leading Fracción
12 B
Por último comentar que los exponentes con valor máximo y mínimo (0 y 255
en el caso del formato simple) se utilizan con valores especiales, como
muestra la Tabla A.6, y que comentaremos en los siguientes apartados.
Pág 190
Ensamblador del PowerPC con Mac OS X MacProgramadores
Una característica del estándar IEEE 754 es que permite representar números
por debajo de este umbral, a los que llaman números denormalizados,
para ello lo que hacemos es dejar el exponente polarizado a 0 de forma que
ahora la parte fraccionaria se interpreta como si a la izquierda de la coma
hubiera un 0 en vez de un 1.
lim 1/x
x->∞
Pág 191
Ensamblador del PowerPC con Mac OS X MacProgramadores
Para una discusión matemática más a fondo sobre este tema puede consultar
[UNDERFLOW].
Otra peculiaridad del estándar IEEE 754 es que nos permite representar los
valores +∞ y -∞, para ello utiliza los patrones de bits especiales de la Figura
A.10:
Por último la otra gran peculiaridad del estándar IEEE 754 es que puede
representar números no válidos que se obtienen en cálculos especiales como
por ejemplo 0/0, ∞+(-∞), o la raíz de un número negativo. Estos son valores
indefinidos en el campo de los números reales y se representan con el valor
especial NaN (Not a Number). Este valor se codifica dejando el exponente
a su valor máximo y dejando una fracción distinta de cero tal como muestra
la Figura A.11, con lo que más que haber un número NaN, hay una familia
completa de NaN.
Pág 192
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los NaN pueden ser de dos tipos: quiet NaN y signaling NaN. Cuando un
signaling NaN se encuentra en una operación aritmética, si está activo el
tratamiento de excepciones se produce una excepción. Cuando se encuentra
un quiet NaN no se produce la excepción.
Los signaling NaN no tienen por qué ser producidos por operaciones
aritméticas no válidas, nosotros mismos podemos crearlos manualmente, por
ejemplo para rellenar un área de memoria sin inicializar, de forma que si el
programa encuentra un número de estos podemos saber que el programa a
accedido a un trozo de memoria sin inicializar.
Pág 193
Ensamblador del PowerPC con Mac OS X MacProgramadores
Vamos a explicar cómo se calculan estos rangos. Sólo vamos a ver cómo se
calcularían para el formato simple, aunque el mismo razonamiento se puede
aplicar para los demás tipos.
Pág 194
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 195
Ensamblador del PowerPC con Mac OS X MacProgramadores
Un hecho evidente con el que nos vamos a encontrar cuando trabajamos con
números en punto flotante es que tenemos que representar infinitos números
reales usando sólo un conjunto finito (aunque muy grande) de números
binarios en notación de punto flotante. Para afrontar este problema vamos a
utilizar redondeos, donde lo que hacemos es representar un número real
usando el número en punto flotante más cercano a él.
Para ver este hecho podemos dibujar los números en una línea de
coordenadas suponiendo que tenemos números en notación de punto flotante
binario con una parte fraccionaria de 3 bits. En este caso se cumple la regla
de que entre 2n-1 y 2n habrá un total de 8 números uniformemente
distribuidos. Esta regla será cierta para cualquier n, aunque la distancia se
dobla cada vez que incrementamos n tal como observamos en la Figura A.13.
0 2-1 20 21 22 23 24
Pág 196
Ensamblador del PowerPC con Mac OS X MacProgramadores
Esto implica que la precisión que consiguen los redondeos cuando estamos
trabajando con números pequeños sea mucho mayor que la que se consigue
cuando estemos trabajando con números grandes. Obsérvese que en parte
esto es normal, ya que no es la misma la precisión con la que trabaja, por
ejemplo, un microscopio, en la que una micra puede echar a perder todos los
cálculos, que la precisión que necesita un astrónomo al calcular la distancia
de la tierra al sol, o la distancia entre galaxias, donde unos miles de metros
más o menos son inapreciables.
Pág 197
Ensamblador del PowerPC con Mac OS X MacProgramadores
El estándar IEEE 754 define 4 modos de redondeo, los cuales indican cómo
realizar un redondeo cuando un número real no se puede representar
exactamente en la notación de punto flotante utilizada.
Los otros modos de redondeo son redondeo hacia cero, redondeo hacia
+∞ y redondeo hacia -∞. Todo sistema de numeración en punto flotante
que siga el estándar IEEE 754 debe disponer de un mecanismo que nos
permita cambiar este modo de redondeo. En el caso de PowerPC se usa el los
flag RN del registro FPSCR para indicar el tipo de redondeo de acuerdo a la
Tabla A.9.
Pág 198
Ensamblador del PowerPC con Mac OS X MacProgramadores
5 Las excepciones
Cuando se produce una situación anómala en la ejecución de instrucciones de
punto flotante se produce una excepción. IEEE 754 recomienda que existan
flags asociados a las excepciones, en el caso de PowerPC estos flags están en
el registro FPSCR. Al empezar un programa su ejecución todos los flag de
excepción están apagados. Cuando se produce una excepción se activa el
flag apropiado, pero la aplicación se continúa ejecutando. Después la
aplicación puede consultar los flag de excepción o bien modificarlos.
fdiv f0,f1,f2
fadd f2,f3,f4
PowerPC permite tanto usar flags de habilitación de traps como usar flags de
habilitación de excepción, será el diseñador del sistema operativo quien deba
tomar esta decisión.
IEEE 754 define cinco tipos de excepciones que vamos a detallar. Las
implementaciones son libres de disponer de más flags de excepción si lo
consideran apropiado, tal como pasa en PowerPC que dispone de una gran
cantidad de flags de excepción, aunque básicamente las excepciones se
pueden resumir en estas cinco.
Pág 199
Ensamblador del PowerPC con Mac OS X MacProgramadores
Además estos flag pueden ser flags retenidos (sticky), no serlo, o bien
existir un flag de retenido y su correspondiente de no retenido, a elección de
la implementación.
5. Inexact. Ocurre siempre que hay que redondear un número por no existir
una representación exacta de ese número en punto flotante. Se usa porque el
programa puede estar interesado en saber si ha habido redondeo, los cuales
se vuelven especialmente perjudiciales cuando hay una acumulación de
operaciones con redondeo.
Pág 200
Ensamblador del PowerPC con Mac OS X MacProgramadores
6.1 Redondeo
Esta regla que en principio parece difícil de cumplir, por la dificultad que tiene
un ordenador para realizar cálculos con precisión infinita, no es tan difícil
como parece, de hecho, veremos que podemos obtener los resultados que
pide la regla, con sólo un poco más de esfuerzo.
2,34*102
8,51*102 +
––––––––
10,85*102 ––––> Redondea a 10,8*102
Pág 201
Ensamblador del PowerPC con Mac OS X MacProgramadores
2,34*102
2,56*100 +
––––––––
2,3656*102 ––––> Redondea a 2,37*102
9,51*102
6,42*101 +
––––––––
10,152*102 ––––> Redondea a 10,2*102
En cada uno de estos casos la suma se debe calcular con más dígitos con el
fin de realizar correctamente el redondeo. Se ha demostrado que para que el
resultado de una suma en punto flotante sea el mismo que si redondeásemos
el resultado de una suma con precisión infinita, basta con disponer de dos bits
adicionales a la derecha de los registros del sumador, llamados bits de
guarda.
4,5674*100
2,5001*10-4 +
–––––––––
4,56765001*100 ––––> Redondea a 4,5677*100
Pág 202
Ensamblador del PowerPC con Mac OS X MacProgramadores
m1= 4567400
m2= 0000250
m1= 4567400
m2= 0000251
m3= 04567651
a3= 4,5677*100
Pág 203
Ensamblador del PowerPC con Mac OS X MacProgramadores
Pág 204
Ensamblador del PowerPC con Mac OS X MacProgramadores
67,45
x 34,98
––––––––––
2359,4010
Pág 205
Ensamblador del PowerPC con Mac OS X MacProgramadores
1. Usando el divisor de enteros del apartado 1.1.4 dividir las dos mantisas
m1 y m2 para obtener un cociente de |m| bits en el registro A y un
resto en el registro P.
2. Si el resto r3 así obtenido es mayor a la mitad del divisor entonces al
cociente se le suma uno, si no se deja igual, es decir, si 2*r3>a2
entonces a2=a2+1, si 2*r3=a2 se aplica el método de redondeo que
esté activo, si no a2 se deja como está.
3. Para calcular el exponente resultado e3, se calcula como e3=e1-e2.
Dividendo=2352
Divisor=1275
Obteniendo:
Cociente = 1844
Resto = 900
Ahora como el resto es mayor a 1/2 cociente debemos sumar uno al cociente
obteniendo:
Cociente = 1845
Resto = 900
Pág 206
Ensamblador del PowerPC con Mac OS X MacProgramadores
9 Comparaciones y conversiones
IEEE 754 define que un sistema en punto flotante debe de disponer de
operaciones que permitan comparar números en punto flotante. La tricotomía
comparativa usual de los números reales se extiende en el estándar para que
sólo una de estas cuatro comparaciones sea cierta:
o a<b
o a>b
o a=b
o a y b no mantienen relación de orden
Pág 207
Ensamblador del PowerPC con Mac OS X MacProgramadores
Apéndice B
La segmentación
Sinopsis:
Este apéndice está pensado para lectores que desconozcan en que consiste la
segmentación, la cual se menciona repetidamente en distintos contextos de
los temas anteriores.
Pág 208
Ensamblador del PowerPC con Mac OS X MacProgramadores
1 ¿Que es la segmentación?
La segmentación (pipelines) es un técnica usada por los
microprocesadores más avanzados (la mayoría de los procesadores actuales:
Pentium, SPARC, PowerPC, Alpha,...) por la cual se solapa la ejecución de
varias instrucciones.
Pág 209
Ensamblador del PowerPC con Mac OS X MacProgramadores
que no las segmentan, en cuyo caso esa unidad funcional sólo puede ser
usada por una instrucción a la vez.
De cada uno de los tres tipos de unidades funcionales que existen, un micro
suele disponer de más de una, con el fin de que varias instrucciones puedan
estar ejecutando en distintas unidades funcionales del mismo tipo, aunque si
la unidad funcional está segmentada, esto podría no ser tan necesario.
Pág 210
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por otro lado entre las etapas hay que dejar un pequeño tiempo de reajuste
de los cerrojos (latchs) que conectan las distintas etapas que es lo que se
llama el sesgo de reloj (clock skew).
50 50 60 50 50 50 50 60 50 50 50 50 60 50 50
455
Instrucción 1 65 65 65 65 65
Instrucción 2 65 65 65 65 65
Instrucción 3 65 65 65 65 65
Pág 211
Ensamblador del PowerPC con Mac OS X MacProgramadores
R=1300ns/325ns=4
2 Etapas multiciclo
No es práctico exigir que todas las etapas de una instrucción se ejecuten en
un solo ciclo de reloj, como por ejemplo en las operaciones de punto flotante.
Hacer esto significaría aceptar un reloj lento.
FE DE DI EX EX EX EX EX WB
FE DE DI DI DI EX WB
Pág 212
Ensamblador del PowerPC con Mac OS X MacProgramadores
3 Los riesgos
Su instinto es correcto si encuentra difícil pensar que la segmentación es tan
simple como esto, porque no lo es. En esta sección vamos a comentar unos
problemas que surgen en la segmentación llamados riesgos (hazards), que
impiden que se ejecute la siguiente instrucción del flujo de instrucciones
durante su ciclo de reloj designado. Los riesgos reducen el rendimiento de la
velocidad ideal lograda con la segmentación. Hay tres tipos de riesgos:
Por ejemplo, un recurso que suele producir riesgos estructurales son los
puertos de memoria, muchas máquinas tienen un único puerto de memoria
con lo que si una instrucción accede a memoria (lo cual puede llevar varios
ciclos) y otra instrucción también intenta acceder a memoria, ésta última
queda detenida hasta que la primera acaba.
Pág 213
Ensamblador del PowerPC con Mac OS X MacProgramadores
¿Por qué permite el diseñador riesgos estructurales?. Hay dos razones: Para
reducir el coste de fabricación y para reducir la latencia de una unidad
funcional, ya que la segmentación de algunas unidades funcionales aumentan
mucho su latencia porque sus etapas están muy desequilibradas, y si la
segmentamos debemos de hacer que cada etapa dure lo que un ciclo de reloj.
Si los riesgos estructurales no se presentan con frecuencia, puede no merecer
la pena el coste de evitarlos. Además con frecuencia merece más la pena
diseñar una unidad funcional no segmentada, pero con una latencia menor.
add r1,r2,r3
sub r4,r1,r5
La instrucción sub tiene como dato de entrada r1, que es el dato de salida
de la instrucción add. Como muestra la Figura B.4, la instrucción add escribe
el valor de r1 en la etapa WB, mientras que la instrucción sub lee el valor del
registro en la etapa DI.
Pág 214
Ensamblador del PowerPC con Mac OS X MacProgramadores
Luego si no hacemos nada para impedirlo, sub leerá un dato erróneo. En este
caso, el microprocesador tiene que detener a la instrucción sub hasta que el
dato este disponible, como muestra la siguiente Figura B.5.
Pág 215
Ensamblador del PowerPC con Mac OS X MacProgramadores
add r1,r2,r3
sub r4,r1,r5
Para evitar este tipo de riesgos se recomienda siempre que sea posible
intercalar una instrucción sin dependencias en medio. Por ejemplo, en
nuestro ejemplo podemos intercalar una instrucción sin dependencias
así:
add r1,r2,r3
add r6,r7,r8
sub r4,r1,r5
divf fr2,fr3,fr4
addf fr2,fr5,fr6
Al ser más rápida addf que divf, aunque addf empezase después,
escribiría en fr2 antes de que divf.
Para evitar este tipo de riesgos basta con renombrar los operandos:
divf fr2,fr3,fr4
addf fr7,fr5,fr6
Pág 216
Ensamblador del PowerPC con Mac OS X MacProgramadores
lwz r2,0(r3)
addi r3,r4,r5
lwz r2,0(r3)
addi r4,r5,r6
Pág 217
Ensamblador del PowerPC con Mac OS X MacProgramadores
• Saltos incondicionales
• Saltos condicionales, los cuales seleccionan la siguiente instrucción a
ejecutar entre 2 alternativas dependiendo de si se cumple o no una
condición que se encuentra en uno de los campos del registro CR
• Saltos multidestino, son saltos en los que, al igual que los
condicionales, evalúan una condición puesta en un campo de CR, pero
la dirección de destino del salto es también variable (estará en el
registro LR o CTR), con lo que puede haber muchos destinos.
Los saltos sin resolver nunca se producen en los saltos incondicionales, pero
sí que se producen en los demás tipos de saltos, veamos un ejemplo:
lis r2,ha16(dato)
li r2,lo16(dato)
lwz r4,0(r2)
cmpwi cr0,r3,0
beq alla
aqui:
subi r4,r4,1
alla:
addi r4,r4,1
Pág 218
Ensamblador del PowerPC con Mac OS X MacProgramadores
cmpwi cr0,r3,0
lis r2,ha16(dato)
li r2,lo16(dato)
lwz r4,0(r2)
beq alla
aqui:
subi r4,r4,1
alla:
addi r4,r4,1
Pág 219
Ensamblador del PowerPC con Mac OS X MacProgramadores
Vamos a ver ejemplos de cómo resolver el problema de los saltos sin resolver
en las estructuras de control de flujo más conocidas.
3.5.1 Estructura if
Pág 220
Ensamblador del PowerPC con Mac OS X MacProgramadores
trabajado las instrucciones son sólo de uso interno al bucle. La Figura B.12
muestra un ejemplo de adelantamiento de instrucciones en un bucle while.
Pág 221
Ensamblador del PowerPC con Mac OS X MacProgramadores
En estas estructuras se pueden eliminar los saltos sin resolver usando saltos
condicionales en función del registro CTR, que son saltos que siempre están
resueltos.
·············
instrucciones1
·············
mtctr r5
inicio:
·············
instrucciones2
·············
bdnz inicio
fin:
li r3,1 ; Desde 1
li r4,n ; Hasta n
subi r5,r4,1
mtctr r5 ; Fijamos el contador hasta 0
inicio:
·············
instrucciones2
·············
add r3,r3,1
bdnz inicio
fin:
Pág 222
Ensamblador del PowerPC con Mac OS X MacProgramadores
Los algoritmos que usa el procesador para decidir si llevar a cabo o no el salto
se clasifican en dos grupos:
BO Descripción
0000y Decrementa el registro CTR y después salta si CTR≠0 y la condición
es FALSE
0001y Decrementa el registro CTR y después salta si CTR=0 y la condición
es FALSE
001zy Salta si la condición es FALSE
0100y Decrementa el registro CTR y después salta si CTR≠0 y la condición
es TRUE
0101y Decrementa el registro CTR y después salta si CTR=0 y la condición
es TRUE
011zy Salta si la condición es TRUE
1z00y Decrementa el registro CTR y después salta si CTR≠0
1z01y Decrementa el registro CTR y después salta si CTR=0
1z1zz Salta siempre
z Es un bit que se reserva para el futuro, y que de momento debe ser siempre 0
y Indica si es más probable que el salto se realice a que no se realice
Tabla B.1: Configuración del operando BO
Pág 223
Ensamblador del PowerPC con Mac OS X MacProgramadores
·············
instrucciones1
·············
inicio:
·············
instrucciones2
·············
cmpw cr0,r2,0
bc 13,2,inicio
fin:
bucle:
cmpwi r3,100
beq+ bucle
Pág 224
Ensamblador del PowerPC con Mac OS X MacProgramadores
Dirección de la Estado
instrucción de salto
00 - Strongly Taken
01 - Weakly taken
10 - Weakly Not taken
11 - Strongly Not Taken
T T T
Strongly Weakly
NT Weakly Strongly T
Not NT Not NT NT
Taken Taken
Taken Taken
Figura B.16: Estado de los bits de salto T - Taken NT- Not taken
Pág 225
Ensamblador del PowerPC con Mac OS X MacProgramadores
Una última solución hardware a los saltos sin resolver que están empezando a
usar los procesadores más avanzados es el scheduling, que consiste en que
el procesador puede pasar las instrucciones a ejecución en orden distinto al
que están escritas en el programa. El procesador puede decidir cambiar el
orden de ejecución de las instrucciones en base a dos criterios: El primero es
que el procesador puede leer adelantadamente varias instrucciones en el
llamado fetch buffer y decide si pasar las instrucciones a ejecución en el
orden que están llegando o bien adelantar alguna de ellas si encuentra que
esa instrucción va a producir una detención. El segundo criterio es que el
procesador puede detectar dependencias, y si las encuentra detiene una
instrucción aunque deja pasar a otras con las que no hay dependencias.
3.7 La serialización
Esto ocurre por ejemplo cuando hay más de una unidad funcional de punto
fijo donde recursos comunes no duplicados como el registro XER van a ser
actualizados. Por esta razón las instrucciones que modifican este registro
llevan un nombre especial como addc o addo, las cuales pueden ejecutar
considerablemente más lento que la instrucción que no modifica este registro
(add). Lo mismo ocurre con las instrucciones con punto (.) como por
ejemplo add., que al escribir en le campo CR0 puede necesitar ejecutar
secuencialmente.
Pág 226
Ensamblador del PowerPC con Mac OS X MacProgramadores
Por último están las llamadas máquinas vectoriales, que usan a la vez
ambas técnicas. Habitualmente son supersegmentadas, y tienen potentes
operaciones vectoriales que se pueden considerar equivalentes a emitir
múltiples operaciones independientes.
Pág 227
Ensamblador del PowerPC con Mac OS X MacProgramadores
Referencias
[DEVTOOLS] Herramientas de desarrollo de Apple
http://developer.apple.com/tools/index.html
Pág 228