Curso de Asembler - La pila

8 - La pila

[editar]
Curso gratis creado por Pablo Barrón Ballesteros ( Wintermute ).
04 de Noviembre de 2005
Para explicar ‚sta parte, voy a hacerlo lo m s mundanamente posible y

sin mucho t‚rmino complicado, porque las explicaciones muchas veces suelen

liar m s sobre una cosa tan sencilla como es ‚sto.

La pila es una especie de "almac‚n de variables" que se encuentra en una

dirección determinada de memoria, dirección que viene indicada por SS:SP,

como mencion‚ antes, registros que son SS de segmento de pila y SP de

Offset de ‚sta.

Entonces nos encontramos con dos órdenes b sicas respecto a la pila, que

son PUSH y POP. La órden PUSH empuja una variable a la pila, y la órden POP

la saca. Sin embargo, no podemos sacar el que queramos, no podemos decir

"quiero sacar el valor de DX que he metido antes y que fue el cuarto que

metí", por ejemplo.

La estructura de la pila se denomina LIFO, siglas inglesas que indican

'Last In First Out'. Esto significa que al hacer un POP, se sacar  el

último valor introducido en la pila. Vamos con unos ejemplitos majos:

PUSH    DX              ; Mete en la pila el contenido de DX

PUSH    CX              ; Y ahora el contenido de CX

POP     AX              ; Ahora saca el último valor introducido ( CX )

;y lo coloca en AX.

POP     BP              ; Y ahora saca en valor anterior introducido, que

;es el contenido de DX cuando hicimos el PUSH DX

;y se lo asigna a BP.

Ahora, una rutina algo m s detallada:

MOV     DX,0301h        ; DX vale ahora 0301 hexadecimal.

PUSH    DX              ; Empuja DX a la pila. SP se decrementa en dos.

MOV     DX,044C4h       ; Ahora DX vale 044C4h

POP     CX              ; Y con ‚sto, CX vale 0301 hexadecimal, el valor

;que habíamos introducido con anterioridad.

Dije en la segunda línea: SP se decrementa en dos. Cuando por ejemplo

ejecutamos un .COM, SS es el segmento del programa ( o sea, igual que CS,

y si no han sido modificados, DS y ES ), y SP apunta al final, a 0FFFFh.

Cuando empujamos un valor a la pila, SP se decrementa en dos apuntando a

0FFFDh, y en ‚sta dirección queda el valor introducido. Cuando lo saquemos,

se incrementar  de nuevo en dos el valor de SP, y el valor se sacar  de

la pila.

Se puede operar con ‚sta instrucción con los registros AX, BX, CX, DX,

SI, DI, BP, SP, CS, DS y ES, sin embargo no se puede hacer un POP CS, tan

sólo empujarlo a la pila.

He aquí un ejemplo de lo que hace en realidad un POP en t‚rminos de MOVs,

aunque sea un gasto inútil de código, tiene su aplicación por ejemplo para

saltarse la heurística en un antivirus, que busca un POP BP y SUB posterior,

bueno, supongo que ya aprender‚is a aplicarlo cuando ve is el curso de

virus/antivirus:

Partamos de que hay cierto valor en la pila que queremos sacar.

MOV     BP,SP       ; Ahora BP es igual al offset al que apunta SP

MOV     BP,Word ptr [BP] ; Y ahora BP vale el contenido del offset al

;que apunta, que al ser el offset al que apunta

;el de pila, ser  el valor que sacaríamos

;haciendo un POP BP.

ADD     SP,2            ; Para acabarlo, sumamos dos al valor de offset

;de la pila.

Y ‚sto es lo que hace un POP BP, símplemente. Para ver lo que hace un PUSH

no habría m s que invertir el proceso, lo pongo aquí, pero sería un buen

ejercicio que lo intent rais hacer sin mirarlo y luego lo consult rais, por

ejemplo introduciendo DX a la pila.

SUB     SP,2

MOV     BP,SP

MOV     Word ptr[BP],DX

Como última recomendación, hay que tener bastante cuidado con los PUSH

y POP, sacar tantos valores de la pila como se metan, y estar pendiente de

que lo que se saca es lo que se tiene que sacar. La pila bien aprovechada

es fundamental para hacer programas bien optimizados, ya que entre otras

cosas las instrucciones PUSH y POP sólo ocupan un byte.

Es por ejemplo mucho mejor usar un PUSH al principio y un POP al final

en vez de dejar partes de código para almacenar variables, m s velocidad

y menos tama¤o.

Y finalmente, hay otras dos órdenes interesantes respecto a la pila,

PUSHF y POPF, que empujan el registro ( 16 bits ) de flags y lo sacan,

respectivamente

                                LA ORDEN CALL

Se trata de una órden que se utiliza para llamar a subrutinas, y est

relacionada con la pila, por lo que la incluyo en ‚sta lección del curso.

La sintaxis del Call es casi la de un Jmp, pudi‚ndose tambi‚n utilizar

etiquetas, direcciones inmediatas o registros. Si compar semos un Jmp con

un 'GOTO', el Call sería el 'GOSUB'. Es una instrucción que nos va a servir

para llamar a subrutinas.

Su forma de actuación es sencilla. Empuja a la pila los valores de CS e

IP ( o sea, los del punto en el que est  en ese momento el programa ),

aunque IP aumentado en el tama¤o del call para apuntar a la siguiente

instrucción, y hace un salto a la dirección indicada. Cuando encuentre una

instrucción  RET, sacar  CS e IP de la pila, y así retornar  al lugar de

origen. Veamos un ejemplo:

xor     ax,ax       ; Ax vale ahora 0

Call    quebi‚n     ; Mete CS e IP a la pila y salta a quebi‚n

Int     20h         ; sta órden sale al dos, explicar‚ todo ‚sto

;en el próximo capítulo, sólo que sep is eso

quebi‚n: mov     ax,30h

Ret                 ; Vuelve a la instrucción siguiente al punto

;de llamada, o sea, a la de "INT 20h"

La órden RET puede tener tambi‚n varios formatos: RETN o RETF, según se

retorne desde un sitio cercano ( RETN, near ) o lejano ( RETF, far ). No

obstante, pr cticamente no lo usaremos, la mayoría de las veces se quedar

en RET y punto.

Existe entonces la llamada directa cercana, en la que sólo se introduce

IP ( lógicamente, apuntando a la órden siguiente al Call ), y al retornar,

lo hace en el mismo segmento, y la llamada directa lejana, en la que se

introducen CS e IP ( y luego se sacan, claro ). A veces se podrían producir

confusiones, con lo que quiz  pueda ser conveniente usar RETN y RETF

respectivamente.

Y el próximo capítulo empezamos con interrupciones,... venga, que ya

queda menos para poder programar ;-)
[editar]

7 opiniones

Opinión.

Obsoleto. Poco práctico. Inservible. Para un museo puede estar bien. Jajaja no sería obsoleto si fueras a programar un sistema operativo , es un lenguaje muy poderoso , en el que está hecho parte de windows , y de linux

saludos.
Felicitaciones.

Excelente explicacion gracias.
Bueno.

El curo esta bueno pero necesito tener mas informacion para crear programas.
Mvp.

Excelente.
Bueno.

Excelente trabajo. Siga adelante.
1 2 | siguiente >

Cursos gratis relacionados con 'Curso de Asembler'

Completo curso de lenguaje ensamblador.

Autor y licencia de 'Curso de Asembler'


Curso gratis de Pablo Barrón Ballesteros ( Wintermute ). Extraido de: CopyLeft
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.