Instrucciones de Carga y Almacenamiento Múltiple
Estas instrucciones permiten:
Cargar múltiples registros de propósitos generales ( un subset o todos ellos) desde la memoria
Almacenar múltiples registros de propósitos generales ( un subset o todos ellos) en la memoria
Las direcciones desde donde se leen los registros o hacia donde se guardan serán siempre posiciones consecutivas, donde el menor registro se almacenará o leerá desde la posición mas baja, y el mayor número de registro lo hará con las posición mas alta.
La sintaxis de la instrucción será
LDM||STM{cond}<modo direccion> <Rn>{!}, <Listado de Registros>{^}
donde:
cond, indica la condición para ejecutar la instrucción.
modo direccion,indica de que forma se irán guardando o leyendo los registro desde o hacia la memoria, existen cuatro tipos distintos.
IA (Increment After) la primera posición de memoria a guardar o leer los datos es la indicada por Rn luego los registros posteriores se irán guardando en posiciones contiguas incrementadas de a 4 bytes, corresponde a P = 0 U = 1.
IB (Increment Before) la primera posición de memoria a guardar o leer los datos es la indicada por Rn + 4, los registros posteriores se irán guardando en posiciones contiguas incrementadas de a 4 bytes, corresponde a P = 1 U = 1.
DA (Decrement After) la última posición de memoria a guardar o leer los datos es la indicada por Rn luego los registros anteriores se irán guardando en posiciones contiguas decrementadas de a 4 bytes, corresponde a P = 0 U = 0.
DB (Decrement Before) la última posición de memoria a guardar o leer los datos es la indicada por Rn - 4, los registros anteriores se irán guardando en posiciones contiguas decrementadas de a 4 bytes, corresponde a P = 1 U = 0.
! indica si el registro base se actualizará una vez que se termine de guardar o leer todos los registro (corresponde al bit W).
^ si se coloca en una instrucción STM o LDM que no usan PC, indica que los registros a cargar o leer son los correspondiente al modo usuario y no al modo actual, si se coloca en LDM que usan el PC, este modificador indica que el SPSR es guardado en el CPSR.(corresponde al bit S)
Listado de Registros Indica los registros a guardar o leer, es un listado de los nombres de los registros separados con coma.
31 |
30 |
29 |
28 |
27 |
26 |
25 |
24 |
23 |
22 |
21 |
20 |
19 |
18 |
17 |
16 |
15 |
14 |
13 |
12 |
11 |
10 |
09 |
08 |
07 |
06 |
05 |
04 |
03 |
02 |
01 |
00 |
cond |
1 |
0 |
0 |
P |
U |
S |
W |
L |
Rn |
Listado de Registros |
Bit P
- P = 0 Indica que el registro Rn está incluido en el rango de la memoria.
- P = 1 Indica que el registro Rn no está incluido en el rango de memoria, en este caso los datos se tomarán a partir de la siguiente posición de memoria o de la anterior a Rn dependiendo de si se guardan o leen en forma ascendente o descendente.
Bit U Indica el modo en que se toman las sucesivas posiciones de memoria
- U = 1 con cada lectura o escritura de un registro se incrementa la posición de memoria, Rn en este caso indica la posición mas baja del bloque en donde se escriben o leen los datos (si Rn es la posición mas baja o es la anterior a la mas baja depende del bit P).
- U = 0 con cada lectura o escritura de un registro se decrementa la posición de memoria, Rn en este caso indica la posición mas alta del bloque en donde se escriben o leen los datos (si Rn es la posición mas alta o es la posterior a la mas alta depende del bit P).
Bit S Este bit tiene dos funciones:
- Instrucciones LDM con carga del PC, este bits indica que el CPSR es cargado desde SPSR,
Nota cuando el procesador esta en modo usuario o sistema, este funcionamiento del LDM dará resultados impredecibles.
- STM o LDM que no usan PC, indica que cuando el procesador está en modo privilegio, los registros correspondiente al modo usuario son transferidos en vez de los registros del modo en uso.
Bit W Indica si el registro base es actualizado o no después de transferirse los datos. En caso de actualizarse, el mismo se decrementará (U=0) o incrementará (U=1) cuatro veces la cantidad de registros utilizados.
Bit L L = 1 indica instrucción de carga (LDM), L = 0 instrucción de almacenamiento (STM)
Listado de Registros posee un bit para cada registro, por ejemplo el bit 15 corresponde al registro 15 (PC), un bit en 1 indica que el registro correspondiente sera cargado o almacenado desde memoria, la instrucción no está diseñada para tener todos los bits en 0 y dará resultados impredecibles para este caso.
Operaciones con el Stack
Las instrucciones de Carga y Almacenamiento son utilizadas mayormente en dos situaciones, para guardar o recuperar un bloque de datos o como instrucciones de manejo del stack.
En el primer caso, tenemos como dato una dirección de memoria, en el momento de guardar un bloque de dato lo haremos a partir de ese valor, el mismo valor que utilizaremos luego para recuperarlos.
Cuando se usan para manejar el stack, la idea es formar una pila, donde cada vez que se guardan los datos la posición de memoria es actualizada, en este caso si utilizamos un modo de guardado que implica que los datos se almacenen en posiciones de memorias incrementales, si queremos luego leer los mismos, deberemos utilizar lecturas decrementales, debido a que por cada paquete de datos guardados la dirección origen se perdió y el dato que se posee es la dirección final de los datos.
De esta forma podemos definir el tipo de funcionamiento del stack de la siguiente forma.
Según donde apunta el stack lo dividimos en:
- Full Stacks el puntero del stack indica la dirección del ultimo dato.
- Empty Stack el puntero del stack indica la primera dirección libre.
Según la forma en que guardan los datos:
- Descending stack los datos son guardados en posiciones decrementadas 4 bytes con respecto a la anterior mientras que son leidos incrementando 4 bytes respecto al anterior.
- Ascending stack los datos son guardados en posiciones incrementadas 4 bytes con respecto a la anterior mientras que son leidos decrementando 4 bytes respecto al anterior.
De estas dos clasificaciones, podemos definir 4 tipos de stack
- Full Descending, con la sintaxis FD.
- Empty Descending, con la sintaxis ED.
- Full Ascending, con la sintaxis FA.
- Empty Ascending, con la sintaxis EA.
Estos modificadores forman un conjunto nuevo de instrucciones, los cuales tienen una equivalencia con la anterior tabla, pero ahora la forma en que funcionará una instrucción de Carga en un modo de stack dado, será distinta al funcionamiento de una instrucción de Almacenamiento en ese mismo modo, esto queda reflejado en la siguiente tabla.
Modo Stack |
Modo Convencional |
||||
Modo |
Instrucciones |
Instrucciones |
|||
|
Carga |
Almacenamiento |
Carga |
Almacenamiento |
|
Full Ascending |
LDMFA |
STMFA |
LDMDA |
STMIB |
|
Full Descending |
LDMFD |
STMFD |
LDMIA |
STMDB |
|
Empty Ascending |
LDMEA |
STMEA |
LDMDB |
STMIA |
|
Empty Descending |
LDMED |
STMED |
LDMIB |
STMDA |
En esta tabla vemos en la primeas columnas, las instrucciones con el subfijo que determina el modo de funcionamiento para manejo de stack, luego en las últimas dos columnas las instrucciones que funcionan en modo equivalente pero usando el modo convencional de subfijo.
Como ejemplo del uso de estas instrucciones para el manejo del stack, vamos a guardar dos registros el R1 y R2 en el stack cuyo puntero está guardado en el registro R13, este registro no es casual, es el que ARM propone como SP o Stack Pointer y tiene un trato especial al igual que el R14 y R15 o LR y PC respectivamente, el modo del stack que usaremos es el mas común y el que utiliza por ejemplo INTEL, en nuestras PC
Modo de stack Full Descending Registros a guardar y luego recuperar R1 y R2
Instrucción para Guardar
STMFD R13!,{R1,R2}
Estado antes de Guardar |
Estado luego de Guardar |
|
|
Instrucción para Leer
LDMFD R13!,{R1,R2}
Estado antes de Leer |
Estado luego de Leer |
|
|
Este modo al ser el mas común, el compilador provee un sinónimo para estas instrucciones, como se observa, además de reemplazar el nombre de la instrucción estamos omitiendo el uso del registro que provee la dirección de memoria donde se almacena o recupera los datos, esto es debido a que ARM presupone el uso de R13 como registro SP y por lo tanto lo utiliza por defecto en la instruccion PUSH y POP
PUSH{....} -> STMFD R13!,{....} POP{....} -> LDMFD R13!,{....}