Publicado originalmente para CodeSec.org, autoría propia.Este es un manual que comencé a escribir hace tiempo, acerca de Netwide Assembler.
Atención: dudas y mensajes sobre este tema se responderán por mensaje privado o mediante la creación de un nuevo hilo.Introducción a Netwide Assembler (NASM)
Actualmente, es muy difícil encontrar programas escritos completamente en Assembler, sin embargo, son utilizados por su portabilidad y facilidad de uso, además, al estar creado en un lenguaje de programación de nivel bajo, no tiene empaquetado ni tanta basura que puede contener otro programa creado, por ejemplo, en VB, lo que puede generar un ejecutable de apenas 2'5Kb, cuando el mismo programa, en VB, sería de 21Kb. Ya veremos más adelante estos datos.
¿Por qué necesitamos aprender Assembler?
-> Genera un código más rápido y pequeño que otro programa escrito en otro lenguaje de alto nivel
-> Para ciertas plataformas, los lenguajes de alta programación son ineficientes, debido a restricciones del hardware (Ej.: Sistemas embebidos)
-> Permite acceder al Hardware directamente (Ej.: Sistemas operativos)
-> Conocerás como funciona completamente un PC internamente
Registros
Registros de datos EAX EBX ECX EDX
Punteros de pila ESP EBP
Registros de índice EDI ESI
Registros de segmento FS CS DS ES SS
EAX: También llamado acumulador
EBX: Puede ser usado como registro base de direccionamiento (por ejemplo, para apuntar a direcciones de memoria con el)
ECX: Usado como contador (ciclos, rotaciones...)
EDX: Registro de datos, a veces usado con EAX en instrucciones especiales.
Los sistemas de 32 bits, están construidos por registros de 16 bits, y estos a su vez, están divididos en subsegmentos de 8 bits, que a su vez, están formados por dos códigos hexadecimales, de 4 bits cada uno (Cada bit es un impulso eléctrico, positivo (1) o negativo (2)). La siguiente tabla muestra un ejemplo:
##############
# Segunda entrega #
##############
-
No hay forma de acceder a los 16 bits superiores.
Estas direcciones requieren un número de 20 bits, el cual, no cabrá en un registro de 16 bits. Desde la llegada de Intel, se usaban 2 valores de 16 bits (32 bit) para determinar una dirección. Los valores del seleccionador deben estar en registros de segmento, y el segundo valor de 16 bits, es el desplazamiento (Offset). Se puede obtener la dirección mediante la siguiente formula:
16 * Seleccionador + Desplazamiento
Una curiosidad es la forma en la que la máquina obtiene un número hexadecimal a partir de uno decimal. He aquí la fórmula:
Decimal: 31278
31278:16 = 1954 resto= 14 (E)
1954:16 = 122 resto= 2 (2)
122:16 = 7 resto= 10 (A)
7:16 = 0 resto= 7 (7)
7A2E (Hexadecimal)
Como vemos, realiza algo similar a una conversión decimal binaria, pero usando 16 para obtener un número valido para continuar dividiendo, y el resto, el valor hexadecimal. Pueden ponerlo en práctica.
Operadores lógicos
Hay de 4 tipos, y se representan como en la siguiente tabla:
And: Vale 1 si ambos bites están a 1
1 | 1 = 1
1 | 0 = 0
0 | 0 = 0
0 | 1 = 1
Or: Vale 1 si algún bit vale 1
1 | 1 = 1
1 | 0 = 1
0 | 0 = 0
0 | 1 = 1
Xor: Vale 1 si los bits son diferentes, y 0 si no lo son
1 | 1 = 0
1 | 0 =1
0 | 0 =0
0 | 1 =1
Not: Invierte el valor del bit
Not 1 = 0
Not 0 = 1
Flags
Son registros especiales, en donde se guardan los resultados de la última operación matemática, o de comprobación. No se almacenan resultados numéricos, sino su estado.
Aunque es un registro de 16 bits, sólo algunos de ellos tienen significado. Los otros adquieren valores indeterminados, y se dice que son bits reservados; un programa no debe tocarlos, pues aunque un equipo dado puede que no los use, otros micros podrían manipularlos internamente, con resultados impredecibles.
* CF Carry Flag o indicador de acarreo. Normalmente indica si "nos llevamos algo" despues de haber sumado o restado.
* OF Overflow Flag o indicador de desbordamiento. Si después de una operación el resultado no cabe en el tamaño del registro, se pone a 1.
* ZF Zero Flag o indicador de cero. Si el resultado da 0 se pone a 1.
* SF Sign Flag o indicador de signo. Si el resultado es negativo se pone a 1.
* PF Parity Flag o indicador de paridad. Con algunas operaciones lógicas o aritméticas se pone a 1 si el resultado es par.
* AF Auxiliary Flag o indicador auxiliar. Se usa para operaciones BCD (si es que éstas valen para algo)
* DF Direction Flag o indicador de dirección. Se usa en operaciones llamadas "de cadena", indicando el sentido (ascendente o descendente) en que se recorre la memoria. (Este flag es más divertido de lo que parece.)
* IF Interrupt Flag o indicador de interrupciones. Cuando se pone a 1 se permiten las interrupciones, a 0 se ignoran; se dice que se enmascaran. Hay no obstante algunas muy especiales que pasan del flag; por ejemplo, si arrancas (físicamente, me refiero; coger con la mano y zás!) una tarjeta de RAM con el trasto encendido, la interrupción que salta -alerta roja, inmersión, inmersión, auuuuu- pasa de este flag olímpicamente (algo así no se puede pasar por alto bajo ninguna circunstancia).
* TF Trap Flag o indicador de trampa (para ejecución paso a paso, como en los depuradores; podemos olvidarnos de él)
###############
# Tercera entrega #
###############
Tipos de datos
Lo que hace diferente a Assembler frente a otros lenguajes, es que tu mismo puedes indicar el tamaño reservado a una variable. Existen 4 tipos, dependiendo del tamaño a ocupar:
->
BYTE - Reserva 8 bit - 2 ^ 8 = 256
->
WORD - Reserva 16 bit - 2 ^ 16 = 65536
->
DWORD - Double Word, reserva 32 bit - 2 ^ 32 = 4294967296
->
QWORD - Quad Word, reserva 64 bit - 2 ^ 64 = 18446744073709551616 (Únicamente usado en plataformas X64)
Juegos de instrucciones
Bueno, esta lista la obtuve de Los enlaces son solo para miembros.
Registrate o
iniciá sesión, ya que se trata de una gran lista, dependiendo del sistema que utilices. Esta se basa en arquitecturas 80X86:
acum uno de los acumuladores: AX o AL.
reg cualquiera de los registros
segreg uno de los registros de segmento
r/m uno de los operandos generales: registro, memoria, basado, indexado o basado-indexado
inmed constante o símbolo de 8 o 16 bits
mem un operando de memoria: símbolo, etiqueta, variable.
etiqueta etiqueta de instrucciones.
src fuente en operaciones de cadena
dest destino en operaciones de cadena.
8086/8088AAA Ajuste ASCII para adición.
AAD Ajuste ASCII para división.
AAM Ajuste ASCII para multiplicación.
AAS Ajuste ASCII para división.
ADC acum, inmed Suma con acarreo.
r/m,inmed
r/m, reg
reg, r/m
ADD acum,inmed Suma.
r/m,inmed
r/m, reg
reg, r/m
AND acum,inmed Operación AND a nivel bit.
r/m,inmed
r/m, reg
reg, r/m
CALL etiqueta Llamado.
r/m
CBW Convierte byte apalabra.
CLC Limpia bandera de acarreo.
CLD Limpia bandera de dirección.
CLI Limpia bandera de interrupción.
CMC Complementa bandera de acarreo.
CMP acum,inmed Comparación
r/m,inmed
r/m, reg
reg, r/m
CMPS src,dest Comparación de cadenas.
CMPSB Compara cadenas byte por byte.
CMPSW Compara cadenas palabra por palabra.
CWD Convierte palabra a palabra doble.
DAA Ajuste decimal para adición.
DAS Ajuste decimal para substracción.
DEC r/m Decremento.
reg
DIV r/m División.
ESC inmed, r/m Escape con 6 bits.
HLT Alto.
IDIV r/m División entera.
IMUL r/m Mutiplicación entera.
IN accum,inmed Entrada desde puerto.
acum, DX
INC r/m Incremento.
reg
INT3 Interrupción3 codificada como un byte.
INT inmed Interrupción0-255.
INTO Interrupción en overflow.
IRET Retorno de interrupción.
JMP etiqueta Brinco incondicional.
LAHF Carga AH con las banderas.
LDS r/m Carga DS.
LEA r/m Carga la dirección.
LES r/m Carga ES.
LOCK Cierra bus.
LODS src Carga cadena.
LODSB Carga byte de cadena en AL.
LODSW Carga palabra de la cadena en AX.
LOOP etiqueta Ciclo.
LOOPE etiqueta Ciclo mientras igual.
LOOPNE etiqueta Ciclo mientras no igual.
LOOPNZ etiqueta Ciclo mientras no cero.
LOOPZ etiqueta Ciclo mientras cero.
MOV acum,mem Mueve un valor del segundo al primer operando
r/m,inmed
mem, acum
r/m, reg
r/m,segreg
reg, inmed
reg,r/m
segreg,r/m
MOVS dest, src Mueve cadena.
MOVSB Mueve cadena byte por byte.
MOVSW Mueve cadena palabra por palabra.
MUL r/m Multiplicación.
NEG r/m Niega(complemento a 2).
NOP Operación ociosa.
NOT r/m Invierte valores de bits (complemento a 1).
OR acum, inmed Operación OR a nivel de bit.
r/m,inmed
r/m, reg
reg,r/m
OUTDX, accum Salida por el puerto dado por el primer operando.
inmed, acum (inmediato de 8 bits)
POP r/m Recupera valor de la pila.
reg
segreg
POPF Recupera banderas.
PUSH r/m Guarda valor en la pila.
reg
segreg
PUSHF Guarda banderas.
RCL r/m,1 Rotación a la izquierda con acarreo.
r/m,CL
RCR r/m, 1 Rotación a la derecha con acarreo.
r/m, CL
REP Repite.
REPE Repite si igual.
REPNE Repite si no igual.
REPNZ Repite si no cero.
REPZ Repite si cero.
RET [inmed] Regresa después de recuperar bytes de la pila.
ROL r/m,1 Rotación a la izquierda.
r/m, CL
ROR r/m,1 Rotación a la derecha.
r/m, CL
SAHF Carga banderas con el valor de AH.
SAL r/m, 1 Desplazamiento aritmético a la izquierda.
r/m, CL
SAR r/m, 1 Desplazamiento aritmético a la derecha.
r/m, CL
SBB acum, inmed Substracción con acarreo.
r/m,inmed
r/m, reg
reg,r/m
SCAS dest Explora cadena.
SCASB Explora cadena para el byte en AL.
SCASW Explora cadena por la palabra en AX.
SHL r/m, 1 Desplazamiento a la izquierda.
r/m, CL
SHR r/m, 1 Desplazamiento a la derecha.
r/m, CL
STC Fija bandera de acarreo.
STD Fija bandera de dirección.
STI Fija bandera de interrupción.
STOS dest Guarda cadena.
STOSB Guarda byte en AL en la cadena.
STOSW Guarda palabra en AX en la cadena.
SUB accum, inmed Substracción.
r/m,inmed
r/m, reg
reg,r/m
TEST acum, inmed Comparación.
r/m,inmed
r/m, reg
reg,r/m
WAIT Aguarda.
XCHG acum, reg Intercambio.
r/m,inmed
r/m, reg
reg,r/m
XLAT Traduce.
XOR acum, reg Operación XOR a nivel bit.
r/m,inmed
r/m, reg
reg,r/m
8087F2XM1 Calcula 2x-1.
FABS Toma valor absoluto del tope de la pila.
FADD mem Suma real.
FADD ST,ST(i) Suma real desde la pila.
FADD ST(i),ST Suma real a la pila.
FADDP ST(i), ST Suma real y saca de pila.
FBLD mem Carga un decimal empacado de 10 bytes en lapila.
FBSTP mem Almacena un decimal empacado de 10 bytes y saca de pila.
FCHS Cambia signo del valor en el tope de la pila.
FCLEX Borra las excepciones después de un WAIT.
FCOM Compara real.
FCOM ST Compara real con el tope de la pila.
FCOM ST(i) Compara real con la pila.
FCOMP Compara real y saca de pila.
FCOMP ST Compara real con el tope dela pila y saca de pila.
FCOMP ST(i) Compara real con el tope de la pila y saca.
FCOMPP Compara real y saca dos valores de la pila.
FDECSTP Decrementa el apuntador de la pila.
FDISI Deshabilita las interrupciones después de un WAIT.
FDIV mem División real.
FDIV ST,ST(i) División real desde la pila.
FDIV ST(i), ST División real en la pila.
FDIVPST(i), ST División real sacando valor de la pila.
FDIVR División real invertida.
FDIVR mem División real invertida desde memoria.
FDIVR ST, ST(i) División real invertida desde la pila.
FDIVR ST(i), ST División real invertida desde la pila.
FDIVRPST(i), ST División con un real invertido y sacando valor de la pila.
FENI Habilita interrupciones después de un WAIT.
FFREE Libera elemento dela pila.
FIADD mem Suma entera de un número de2 ó 4 bytes.
FICOM mem Compara enteros de 2 ó 4 bytes y saca de la pila.
FICOMP mem Compara entero de 2 ó4 bytes y saca de pila.
FIDIV mem División entera.
FDIVR mem División entera invertida.
FILD mem Carga un entero de 2, 4 u 8 bytes en la pila.
FIMUL mem Multiplicación entera de 2 ó 4 bytes.
FINCSTP Incrementa el apuntador de la pila.
FINIT Inicializa el procesador después de WAIT.
FIST mem Almacena entero de 2 ó 4 bytes.
FISTP mem Almacena entero de 2, 4 u 8 bytes y saca de la pila.
FISUB mem Resta entero de 2 ó 4 bytes.
FISUBR mem Resta entera de 2 ó 4 bytes invertida.
FLD mem Carga real de 4, 8 ó 10 bytes en la pila.
FLD1 Pone +1.0 en el tope de la pila.
FLDCW mem Carga la palabra de control.
FLDENV mem Carga entorno 8087 (14 bytes).
FLDL2E Cargalog2 e en el tope dela pila.
FLDL2T Cargalog2 10en el tope de la pila.
FLDLG2 Cargalog102 en el tope de la pila.
FLDLN2 Cargaloge2 en el tope de la pila.
FLDPI Carga p en el tope dela pila.
FLDZ Carga +0.0 en el tope de la pila.
FMUL Multiplicación real.
MUL mem Multiplicación real desde memoria.
FMUL ST, ST(i) Multiplicación real desde pila.
FMUL ST(i), ST Multiplicación real a la pila.
FMULP ST, ST(i) Multiplicación real y saca de la pila.
FNCLEX Borra excepciones sin WAIT.
FNDISI Inhabilita interrupciones sin WAIT.
FNENI Habilita interrupciones sin WAIT.
FNINIT Inicializa procesador sin WAIT.
FNOP Operación nula.
FNSAVE mem Salva estado 8087 (94 bytes) sin WAIT.
FNSTCW mem Almacena la palabra de control sin WAIT.
FNSTENV mem Guarda el entorno 8087 sin WAIT.
FNSTSW mem Almacena el estado8087 sin WAIT.
FPATAN Función arcotangente parcial.
FPREM Residuo parcial.
FPTAN Función tangente parcial.
FRNDINT Redondea a entero
FRSTOR mem Restablece estado8087 (94 bytes)
FSAVE mem Conserva el estado8087 (94 bytes).
FSCALE Escala
FSQRT Raíz cuadrada
FST Almacena real.
FST ST Almacena real desde el tope de la pila.
FST ST(i) Almacena real desde lapila.
FSTCW mem Almacena palabra de control con WAIT.
FSTENV mem Guarda el entorno 8087 después de WAIT.
FSTP mem Guarda real de 4, 8 ó 10 bytes y saca de la pila.
FSTSW mem Almacena la palabra de estado depués de WAIT.
FSUB Substracción real.
FSUB mem Substracción real desde memora.
FSUB ST, ST(i) Substracción real desde la pila.
FSUB ST(i), ST Substracción real a la pila.
FSUBPST, ST(i) Substrae real y saca de pila.
FSUBR Substracción real invertida.
FSUBR mem Substracción real invertida desde memoria.
FSUBR ST,ST(i) Substracción real invertida desde la pila.
FSUBR ST(i), ST Substracción real invertida a la pila.
FSUBRPST(i), ST Substracción real invertida a la pila y saca.
FTST Prueba el tope dela pila.
FWAIT Aguarda que la última operación 8087 termine.
FXAM Examina el elemento del tope de la pila.
FXCH Intercambia contenido de los elementos de la pila.
FFREEST Intercambia el elemento del tope de la pila.
FFREEST(i) Intercambia el elemento del tope de la pila y el i-ésimo elemento.
FXTRACT Extrae el exponente y significando.
FYL2X Calcula Y log2 X.
FYL2PI Calcula Y log2 (x+1)