Está en la página 1de 6

Nociones de lenguaje assembler

El computador solo "entiende" el lenguaje de mquina, es decir ceros y unos.


Cada microprocesador responde a su propio set de instrucciones, y la familia de
microprocesadores por ejemplo desde el 8088 pasando por el 80386 hasta llegar a
los actuales, permite a los nuevos integrantes, comprender el lenguaje de sus
antecesores incorporando nuevas prestaciones.
Para que el microprocesador pueda ejecutar una instruccin, sta debe estar en
memoria, y en ella solo pueden residir combinaciones de ceros y unos lgicos,
que es el lenguaje que utiliza el computador. Para llevar a cabo el estudio del
lenguaje assembler, se supondr que cada instruccin consta de 8 bits divididos
en dos partes:
Cdigo de operacin: son los 3 primeros bits y especifican la operacin que debe
realizar el microprocesador.
Direccin de la memoria: son los 5 bits restantes e indican, o bien la posicin
donde se busca el dato con el cual se va a realizar la operacin descripta por los 3
bits del cdigo de operaciones, o bien, a donde se va a almacenar algn resultado
del proceso.
Las operaciones en el microprocesador se llevan a cabo en la ALU, a su vez un
registro denominado acumulador es utilizado para tener el dato antes de
realizarse la operacin y el resultado luego de la misma. Teniendo en cuenta estas
consideraciones se supondrn los siguientes cdigos de operacin:
000 -> Cargar el acumulador del microprocesador con el contenido de la
direccin que indican los 5 bits siguientes de esta instruccin.
001 -> Sumar lo que est en el acumulador con lo que indica la direccin de los 5
bits siguientes de esta instruccin, dejando el resultado en el acumulador.
010 -> Llevar el contenido del acumulador a la direccin que indican los 5 bits
siguientes de esta instruccin.
011 -> Detener el programa.
Ahora se ver a modo de ejemplo un pequeo programa ya ingresado a la RAM,
que utiliza los cdigos anteriores. A la izquierda aparece la instruccin en
lenguaje de mquina y a la derecha la operacin que se realiza:
000 11100 -> Carga el acumulador con lo que tiene la direccin 11100.
001 11101 -> Suma lo que tiene el acumulador con lo que tiene la direccin
11101.

010 11111 -> Almacena el resultado de la suma en la direccin 11111.


011 -> Detiene el programa.
Antiguamente se programaba a los computadores directamente en lenguaje de
mquina por medio de una serie de llaves o interruptores que, segn estuvieran
abiertas o cerradas, permitan el ingreso de ceros o unos lgicos.
A principios de 1950 comienza a desarrollarse el lenguaje ensamblador, conocido
generalmente como assembler, a fin de hacer ms fcil la tarea del programador.
A cada instruccin del lenguaje de mquina se le asigna una sigla o mnemnico
correspondiente al idioma ingls relacionada con el significado de la instruccin,
y las direcciones de memoria son expresadas en forma hexadecimal, que resulta
ms sencillo que en binario.
Luego, los cdigos de operacin vistos anteriormente pueden ser representados
como:
000 -> LDA (Load Accumulator): carga el acumulador con lo que indica la
direccin de la instruccin.
001 -> ADD (en ingls significa agregar o sumar): realiza la suma del contenido
del acumulador con lo que est en la direccin de memoria indicada por la
instruccin.
010 -> STA (Store Accumulator): almacena el contenido del acumulador en la
direccin de memoria especificada en la instruccin.
011 -> HLT (Halt): detiene la ejecucin del programa.
Entonces, teniendo en cuenta que las direcciones estn expresadas en el sistema
hexadecimal de numeracin, el programa quedara de la siguiente forma:
LDA 1C -> Carga el acumulador con lo que tiene en la direccin .
ADD 1D -> Suma lo que tiene el acumulador con lo que tiene la direccin .
STA 1F -> Almacena el resultado en la direccin .
HLT -> Detiene el programa.
Si bien con este tipo de lenguaje es ms fcil programar, modificar programas y
corregir errores que con el lenguaje de mquina, la programacin consume
mucho tiempo y no resulta muy sencilla. Adems, hay que recordar que el
programa desarrollado en lenguaje assembler, vale para una marca y modelo de
microprocesador y no puede transportarse a otro

Nociones sobre ASM

4 registros variables: AX, BX, CX, DX cada uno de 2 bytes (word) de 0-65535,
65536 posibles valores distintos, podemos acceder al byte alto (h) o bajo (l) de
cada registro, reemplazando la X.
Por ejemplo AL puede tener un valor de 0-255. Estos registros almacenan datos
intermedios y su acceso es muy rapido, mas que accediendo a la memoria.
A
B
C
D

(Acumulador)
(Base)
(Contador)
(Dato)
15
8 7
0
------------------|
AH
|
AL
|
------------------|
BH
|
BL
|
------------------|
CH
|
CL
|
------------------|
DH
|
DL
|
-------------------

AX
BX
CX
DX

2 punteros : ES:Di, DS:Si , donde ES y DS son registros de 16 bits, donde va la


direccion base del respectivo segmento, equivalente al primer byte del segmento.
Di y Si son los offset (en que parte estamos parados, o apuntando, o
desplazamiento) de cada segmento, valen cero cuando inicializamos.
Archivos objeto (.obj) : dentro de este archivo tenemos el famoso codigo de
maquina (binario 1-0) , y es lo que ejecutara el micro. Cada instruccion en un
lenguaje de alto nivel equivale a varias instrucciones en lenguaje de maquina.
Cada instruccion en Assembler (lenguaje bajo nivel) equivale a un codigo
nemotecnico del lenguaje de maquina, que equivale a la vez a una instruccion de
codigo de maquina.
Compilador : pasa del codigo nemotecnico (archivos .asm) a codigo de maquina
(archivos .obj) en binario.
Cada instruccion puede como maximo usar 6 bytes y puede equivaler a mas de
una microinstruccion del micro.
DIRECCIONAMIENTO DE LA FAMILIA 80x86 EN MODO REAL

micros 8086: cada registro era de 16 bits (2 bytes), entonces 2^16 = 65536
posiciones posibles para direccionar. Para acceder a un Megabyte de memoria,
Intel junto mediante segmentos y offset 20 bits, entonces 2^20 = 1048576
posiciones posibles a direccionar, o sea un Megabyte.
Ahora 32 bits (familia 80x86): entonces tenemos 2^32 = 4 Gigabytes
aproximadamente, pero para esto, debemos trabajar en modo protegido. MS DOS
trabaja solo en modo real (registros de 16 bits). Para trabajar en modo protegido
PMODE, podemos usar los manejadores dos32, dos4gw, watcom. etc.
Trabajamos en el sistema hexadecimal, y en C lo notamos con un 0x delante del
numero hexadecimal, por ejemplo 0xFF.
La memoria de video comienza en 0xA000:0x0000, lo primero es la direccion
del segmento y lo segundo es el offset (es el puntero de donde estamos parados
dentro del segmento).
Modo Texto : comienza en el segmento 0xB800 y cada 2 bytes hace un caracter,
entonces 80x25x2 = 4000 bytes.
INTERRUPCION 0x10 : maneja la entrada y salida de pantalla, el registro AX
determina el modo , algunas placas tambien usan el BX.
ejemplo : Setear el modo 320x200x256 MCGA
AX = 0x0013
INT(0x10)

ejemplo : Setear el modo 640x400x256 SVGA


AX = 0x4F02
BX = 0x0100
INT(0x10)

CORRIMIENTOS (SHIFT)
supongamos que tenemos:
00110101 = 2^5 + 2^4 + 2^2 + 2^0 = 32 +16 +4 +1 = 53
corrimiento hacia la izquierda (agregar ceros desde la derecha,

ademas siempre ocupamos un byte)


01101010 = 2^6 + 2^5 + 2^3 + 2^1 = 64 + 32 + 8 + 2 = 106 (EL DOBLE !!)
OBS: por cada corrimiento hacia la izquierda, multiplicamos por 2 al
numero.
corrimiento hacia la derecha (agregar ceros desde la izquierda, tambien
siempre ocupando un byte)
00011010 = 2^4 + 2^3 + 2^1 = 16 + 8 + 2 = 26 (LA MITAD EN DIVISION ENTERA
!!)
OBS: por cada corrimiento hacia la derecha, realizamos la division entera
del numero.

MODO 320X200X256
Vamos a ver como podemos optimizar los Putpixel, tal que podamos ver algo en
tiempo real.

Trabajamos con los siguientes tipos de variables:


typedef unsigned char byte; // unsigned char 0-255
(byte)
typedef unsigned int word; // unsigned int 0-65535 (word)
Accedemos al segmento de la memoria de video linealmente :
puntero = X + Y*320
en ASM:
mov
mov
mul
add
mov

ax,[Y];
bx,320;
bx
;
ax,[X];
di,ax ;

en ax va la coordenada Y
en bx va la ctte. 320
multiplicamos y*320 y se guarda el resultado en ax
suma X + ax
en di se guarda el resultado

Un codigo corto en ASM no quiere decir que sea rapido, esta forma de colocar un
pixel en la memoria de video es muy lenta, debido al uso del 'mul', son algo asi
como 133 ciclos de reloj. Debemos usar corrimientos.
Al usar corrimiento hacia la izquierda :
1 lugar
--> multiplico por 2
2 lugares --> multiplico por 4
3 lugares --> multiplico por 8
,,
,,

8 lugares --> multiplico por 256


9 lugares --> multiplico por 512

como con 9 lugares se pasa,


shift L con 8 lugares
(se pasa)

La solucion es muy astuta, veamos:


mov
mov
push
mov
mov
xor
shl
add
pop
add
mov

bx,[X];
dx,[Y];
bx
;
bx,dx ;
dh, dl;
;
;
dl,dl ;
bx,6 ;
;
dx,bx ;
bx
;
bx,dx ;
di,bx ;

bx toma el valor de la coordenada X


dx toma el valor de la coordenada Y
graba bx, nuestro valor de coord. X
ahora, bx=dx = valor coord. Y
copia lo que esta en dl a dh, corrimiento
implicito de 8 lugares
--> Y*256
pone en cero dl
corremos 6 lugares a la izquierda
--> bx*64 equivale a Y*64
suma dx+bx --> (Y*256 + Y*64) = Y*320 !!
restaura valor de X a bx
realiza la suma : X + Y*320
posiciona el puntero di con el valor de bx

También podría gustarte