MANIPULAR POSICIONES DE MEMORIA EN UN PROGRAMA ASSSEMBLY

En assembly podemos mover valores de una posición de memoria origen a una posición de memoria destino, siendo esta, una de las actividades mas frecuentes en un programa assembly. Para mover valores de memoria de un register a otro, usamos la instrucción MOV(x) existen 3 variables de este comando dependiendo del tamaño del origen y del destino, estas son:

  • MOVL : Mueve un valor de 32 bits. movl %eax, %ebx
  • MOVW: Mueve un valor de 16 bits. movw %ax, %bx
  • MOVB: Mueve un valor de 8 bits. movb %ah, %bh

NOTA: Las instrucciones anteriores corresponden a una plataforma de 32 bits en una plataforma de 64 bytes, los movimientos de memoria son de 64, 32 y 16 respectivamente

La elección de una de las opciones del comando MOV depende del tamaño de las posiciones o variables que estemos manejando, por ejemplo:
Moviendo valores entre Registers:

movl %eax, %ebx

Moviendo valores entre Regiters y Memoria

location:

.int 10

movl %eax, location

movl location, %ebx

Moviendo valores a un register:

movl $10, %ebx

Moviendo valores a una localizacion de Memoria

location:

.int 0

movb $10, location

Moviendo valores a una localizacion de Memoria indexada (Array)

ArrayIntegers

.int 10,20,30,40,50

movl %eax, ArrayIntegers(0,2,4) //Asigna la posición de memoria del tercer elemento del array (30)

Lo anterior corresponde a la siguiente estructura en assembly
BaseAddress(Offset, Index, Size)

Donde se indican en primer lugar desde que posición se debe iniciar a contar el registro de memoria, el indice que se desea obtener y finalmente el numero total de registros existentes en el array.

Asignación indirecta de valores usando registers

Usando el carácter “$” antes del nombre de una etiqueta toma la dirección de memoria de la variable y no su valor, es decir, lo que en lenguaje C se conoce como un puntero, accedemos a la localización de memoria directamente, por ejemplo

movl $location, %edi: Mueve la localización de memoria de la variable “location” al register %edi

movl $9, (%edi): Establece el valor nueve a la dirección de memoria a la que apunta el register %edi

movl $9, 4(%edi): Establece el valor nueve a la direccion de memoria a la que apunta el register (%edi + 4 bytes de posiciones en memoria)

movl $9, -2(%edi): Establece el valor nueve a la dirección de memoria a la que apunta el register (%edi – 2 bytes de posiciones en memoria)

El los casos anteriores, al estar el register entre paréntesis, se indica que no se debe copiar la dirección de memoria de la variable al register, en lugar de esto, se debe copiar el valor de la variable al valor de la dirección de memoria a la que apunta el register.

Ejemplo de operaciones Mov

#Ejemplo simple que enseña como usar los tipos de datos y las instrucciones MOVx.dataHelloWorld:.ascii «Hello»

ByteLocation:

.byte 10

Int32bytes:

.int 6

Int16bytes:

.short 3

Float:

.float 10.10

IntAsArrays:

.int 10,20,30,40,50

.bss

.comm BufferLargo, 10000

.text

.globl _start

_start:

nop

#1. Mov valor a un register.

movl $10, %eax

#2. Mov valor a una variable de 16 bytes.

movw $5, Int16bytes

#3. Mover datos entre registers.

movl %eax, %ebx

#4. Mover datos desde memoria a un register.

movl Int32bytes, %eax

#5. Mover datos desde un register a memoria.

movb $7, %al

movb %al, ByteLocation

#6. Mover datos en la localizacion de memoria indexada.

movl $0, %ecx

movl $2, %edi

movl $22, IntAsArrays(%ecx, %edi, 4)

#7. Se obtiene el valor del register y se asigna a otro.

movl $Int32bytes, %eax

movl (%eax), %ebx

movl $9, (%eax)

movl $1, %eax

movl $0, %ebx

int $0x80

Para compilar: as –gstabs -o MovDemo.o MovDemo.s

Para enlazar el programa Objeto con un programa ejecutable: ld -o MovDemo MovDemo.o

Finalmente ejecutarlo: ./MovDemo

Procedemos a depurar con gdb: gdb ./MovDemo

Ahora, en modo de depuración podemos visualizar los valores que tienen cada una de las variables y los registers en cada momento de ejecución, con el fin de ver el desplazamiento de la memoria en cada una de las instrucciones ejecutadas.

Primera instrucción:

#1. Mov valor a un register.

movl $10, %eax

(gdb) info registers

rax 0xa 10

rbx 0x0 0

rcx 0x0 0

…..

Segunda instrucción:

#2. Mov valor a una variable de 16 bytes.

movw $5, Int16bytes

(gdb) x/1dh &Int16bytes

0x6000fe <Int16bytes>: 5

Tercera instrucción:

#3. Mover datos entre registers.

movl %eax, %ebx

(gdb) info registers

rax 0xa 10

rbx 0xa 10

……………

Cuarta instrucción:

#4. Mover datos desde memoria a un register.

movl Int32bytes, %eax

(gdb) info registers

rax 0x6 6

rbx 0xa 10

……………

Quinta instrucción:

#5. Mover datos desde un register a memoria.

movb $7, %al

(gdb) info registers

rax 0x7 7

rbx 0xa 10

…………….

Sexta instrucción:

#6. Mover datos en la localización de memoria indexada.

movl $0, %ecx

movl $2, %edi

movl $22, IntAsArrays(%ecx, %edi, 4)

movl $0, %ecx

(gdb) info registers

rax 0x7 7

rbx 0xa 10

rcx 0x0 0

…………….

movl $2, %edi

(gdb) info registers

rax 0x7 7

rbx 0xa 10

rcx 0x0 0

rdx 0x0 0

rsi 0x0 0

rdi 0x2 2

…………….

movl $22, IntAsArrays(%ecx, %edi, 4)

(gdb) x/5dw &IntAsArrays

0x600104 <IntAsArrays>: 10 20 22 40

0x600114 <IntAsArrays+16>: 50

Séptima instrucción:

#7. Se obtiene el valor del register y se asigna a otro.

movl $Int32bytes, %eax

movl (%eax), %ebx

movl $9, (%eax)

– movl $Int32bytes, %eax

(gdb) print &Int32bytes

$1 = (<data variable, no debug info> *) 0x60010a

(gdb) s

48 movl (%eax), %ebx

(gdb) info registers

rax 0x60010a 6291722

rbx 0xa 10

rcx 0x0 0

rdx 0x0 0

rsi 0x0 0

rdi 0x2 2

#Se ha copiado el valor de la dirección de memoria de la variable al register (0x60010a ).

-movl (%eax), %ebx

rax 0x60010a 6291722

rbx 0x6 6

rcx 0x0 0

rdx 0x0 0

rsi 0x0 0

rdi 0x2 2

#Se ha copiado el valor del register eax al register ebx (el valor es 6).

-movl $9, (%eax)

(gdb) x/1dw &Int32bytes

0x60010a <Int32bytes>: 9

Se ha cambiado el valor de la variable que apunta a la dirección de memoria del register %eax, es decir la variable Int32bytes, el nuevo valor es 9 para la variable Int32bytes, ya que este valor se ha establecido a la dirección de memoria de %eax, que indirectamente es la variable Int32bytes.