jueves, 7 de marzo de 2019

JMP EMU8086

Vamos a hablar de la librería JMP. Y estos son algunos de los ejemplos de los saltos:


Y aquí el primer ejemplo de la librería JMP:


org    100h

mov    ax, 5          ; set ax to 5.
mov    bx, 2          ; set bx to 2.

jmp    calc            ; go to 'calc'.

back:  jmp stop      ; go to 'stop'.

calc:
add    ax, bx         ; add bx to ax.
jmp    back           ; go 'back'.

stop:

ret                   ; return to operating system.




Y el segundo ejemplo de saltos es el que viene con un IF:

include 'emu8086.inc'
.model small
.stack
.data
 
    num1 db 8
    num2 db 8

.code
    main:
    mov ax, @data
    mov ds, ax
    
    mov al, num1
    
    cmp al, num2
    
    jc mayor2
    jz igual
    jnz mayor1
    
.exit

igual:
    printn 'LOS NUMEROS SON IGUALES'
    jmp fin


mayor1:
    printn 'EL PRIMER NUMERO ES MAYOR'
    jmp fin

mayor2:
    print 'EL SEGUNDO NUMERO ES MAYOR'
    jmp fin     

fin:

.exit





miércoles, 6 de marzo de 2019

BANDERAS

CODIGO
.model small
.stack
.data

.code
     mov al,255
     mov bl,1
     add al,bl


.exit
end 




.model small
.stack
.data

.code
     mov al,2
     mov bl,2
     sub al,bl


.exit

end




1.8 DESPLEGADO DE MENSAJES DE MONITOR

Usando el servicio 02 de 21h:

El servicio 02 de la interrupción 21h nos permitirá mostrar en pantalla el despliegue de un carácter en pantalla, generalmente un carácter guardado en alguna de las localidades de dx:



Usando el servicio 09 de 21h:

El servicio  09 de esta interrupción nos pemitira imprimir cadenas de caracteres. Esto se puede hacer de 2 maneras, utilizando offset o con el nmonico lea.

Offset: En ingeniería informática y programación de bajo nivel (como el lenguaje ensamblador), un offset normalmente indica el número de posiciones de memoria sumadas a una dirección base para conseguir una dirección absoluta específica. Con este significado (que es el original) de offset, sólo se usa la unidad básica de direccionamiento, normalmente el byte de 8 bits, para especificar el tamaño del offset. En este contexto se puede llamar a veces dirección relativa.

En pocas palabras offset va a conseguir cada dirección de memoria de cada carácter y lo devolverá a la instrucción solicitada.
Con lea esta solicitud de direcciones por cada carácter se hace de forma automática.

 

 Por ultimo podemos hacer uso de librerias para la impresion de cadenas en pantalla:

1.7 COMPILADORES, PROCESO DE ENSAMBLADO Y LIGADO

Código Fuente: El código fuente es aquel que contiene las lineas de código escritas en el lenguaje de programación sobre el cual estamos trabajando.

 Sin embargo este código no es entendible por el ordenador dado su origen de solo reconocer instrucciones en lenguaje maquina (0 y 1) por lo tanto todo nuestro código solo es una maraña de símbolos raros para el ordenador, para poder ser reconocible todo lo escrito, el lenguaje de programación se vale de un programa llamado interprete o compilador (ya es cuestión del lenguaje), el cual traduce o interpreta vaya la redundancia todo nuestro código a lenguaje maquina, de esta manera se obtiene un archivo el cual es llamado: 

Código Objeto: archivo compuesto por un conjunto de datos escritos en un lenguaje de programación  de tipo binario o código maquina obtenidos de la traducción de un anterior código fuente. En la practica generalmente se genera un codigo intermedio, como lo es, ensamblador, es decir se transforma el codigo fuente a codigo ensamblador y posteriormente se traduce a lenguaje maquina.
En python por ejemplo podemos considerar a los archivos .pyc archivos de código objeto ya que el intérprete no puede leer directamente el texto en el archivo * .py, por lo que este texto se convierte primero en un código de bytes que está dirigido al PVM (no al hardware sino a PVM "Python Virtual Machine" ) . PVM ejecuta este código de bytes. *.
En resumen nuestro programa lo escribimos en el lenguaje de programación que deseamos y el compilador o interprete lo traduce en un archivo diferente para que la maquina pueda leerlos.

Y por ultimo, una vez que estamos completamente seguros que nuestro código funciona perfectamente es cuando creamos el ejecutable, es decir nuestro programa, pues deja decirte que un programa también es un archivo de texto el cual contiene las instrucciones finales de un programa, las cuales se tiene pensado ya no sera necesario modificar de manera que se codifican enteramente en lenguaje maquina es asi que obtenemos 

Código Ejecutable: es básicamente el programa final.
Si eres un usuario de windows el ejemplo mas sencillo de un código ejecutable son los archivos *.EXE.
 
Como podemos ver, el código final es mucho menos entendible que el código objeto, esto es debido a que se encuentra por una parte cifrado y por otra parte se encuentra escrito totalmente en  lenguaje maquina.
 
 
Compiladores y Ensambladores:
En fin, los ejemplos vistos anteriormente estan hechos con python, python es un lenguaje interpretado, es decir utiliza un interprete, el cual traduce las instrucciones a medida que estas son ingresadas.

Por otro lado, anteriormente, los primeros pioneros en la programación son los compiladores y ensambladores, ambos son considerados como traductores, esto es, traducen lo escrito en un archivo de texto a lenguaje maquina.

La principal diferencia entre compilador y ensamblador llega en el hecho de que generalmente los compiladores traducen un codigo a un lenguaje intermedio, como puede ser ensamblador, una vez que se hizo esto, se apoyan de esa traducción para tranformar el codigo a lenguaje maquina.

Por el contrario el ensamblador, lee tu codigo, te detecta errores, y si no tenemos errores traduce directamente a lenguaje maquina, es decir, hace una traducción directa.

Ambos utilizan lo que se conoce como ligadores o enlazadores, estos al traducir un formato ejecutable, generamente se topan con segmentos de codigo como las importaciones o llamadas a otros programas, es aqui donde ellos se encargan de enlazar los codigos y archivos faltantes para una correcta traducción a Lenguaje Maquina.

En resumen, el proceso que sigue un compilador o un ensamblador es:
1. El programa utiliza un editor de texto para crear un archivo de texto ASCII, conocido como archivo de código fuente.

2. El ensamblador lee el archivo de código fuete y produce un archivo de código objeto, una traducción del programa a lenguaje máquina. De manera opcional, produce un archivo de listado. Si ocurre un error, el programador debe regresar al paso 1 y corregir el programa.

3. El enlazador lee el archivo de código objeto y verifica si el programa contiene alguna llamada a los procedimientos en una biblioteca de enlace. El enlazador copia cualquier procedimiento requerido de la biblioteca de enlace, lo combina con el archivo de código objeto y produce el archivo ejecutable. De manera opcional, el enlazador puede producir un archivo de mapa.

4. La herramienta cargador (loader) del sistema operativo lee el archivo ejecutable y lo carga en memoria, y bifurca la CPU hacia la dirección inicial del programa, para que éste empiece a ejecutarse.

1.4 INTERRUPCIONES

CONCEPTO DE INTERRUPCIONES
Una interrupción es una situación especial que suspende la ejecución de un programa de modo que el sistema pueda realizar una acción para tratarla. Tal situación se da, por ejemplo, cuando un periférico requiere la atención del procesador para realizar una operación de E/S.
Las interrupciones constituyen quizá el mecanismo más importante para la conexión del microcontrolador con el mundo exterior, sincronizando la ejecución de programas con acontecimientos externos.


PASOS PARA EL PROCESAMIENTO
1. Terminar la ejecución de la instrucción máquina en curso.
2. Salva el valor de contador de programa, IP, en la pila, de manera que en la CPU, al terminar el proceso, pueda seguir ejecutando el programa a partir de la última instrucción.
3. La CPU salta a la dirección donde está almacenada la rutina de servicio de interrupción (ISR, Interrupt Service Routine) y ejecuta esa rutina que tiene como objetivo atender al dispositivo que generó la interrupción.
4. Una vez que la rutina de la interrupción termina, el procesador restaura el estado que había guardado en la pila en el paso 2 y retorna al programa que se estaba usando anteriormente.
Las interrupciones mas comunes son:
21h: Invoca a todos los servicios de llamada a función DOS, generalmente usado en convinacion con otros servicios para la entrada o salida de datos.
20h: Invoca al servicio de terminación de programa del DOS (termina un programa, como el exit).
10h: Despliega opciones de video
16h: Esta interrupción se encarga de controlar el teclado del PC

1.2 EL PROCESADOR Y SUS REGISTROS INTERNOS

Definición de registros:
un registro es una memoria de alta velocidad y poca capacidad, integrada en el microprocesador, que permite guardar transitoriamente y acceder a valores muy usados, generalmente en operaciones matemáticas.

Función de los registros:
• Los registros están en la cumbre de la jerarquía de memoria, y son la manera más rápida que tiene el sistema de almacenar datos. Los registros se miden generalmente por el número de bits que almacenan; por ejemplo, un "registro de 8 bits" o un "registro de 32 bits“.
• La CPU contiene un conjunto de localidades de almacenamiento temporal de datos de alta velocidad llamada registro. Algunos de los registros están dedicados al control, y solo la unidad de control tiene acceso a ellos. Los registros restantes son los registros de uso general y el programador es el usuario que tiene acceso a ellos.

El procesador 8086 esta dividido en los siguientes registros: 

La UCP o CPU tiene 14 registros internos, cada uno de ellos de 16 bits (una palabra). Los bits están enumerados de derecha a izquierda, de tal modo que el bit menos significativo es el bit 0. Los registros se pueden clasificar de la siguiente forma:
Registros de datos:
AX: Registro acumulador. Es el principal empleado en las operaciones aritméticas.
BX: Registro base. Se usa para indicar un desplazamiento.
CX: Registro contador. Se usa como contador en los bucles.
DX: Registro de datos. También se usa en las operaciones aritméticas.
Estos registros son de uso general y también pueden ser utilizados como registros de 8 bits, para utilizarlos como tales es necesario referirse a ellos como por ejemplo: AH y AL, que son los bytes alto (high) y bajo (low) del registro AX. Esta nomenclatura es aplicable también a los registros BX, CX y DX.
 
Registros de segmentos:
CS: Registro de segmento de código. Contiene la dirección de las instrucciones del programa.
DS: Registro segmento de datos. Contiene la dirección del área de memoria donde se encuentran los datos del programa.
SS: Registro segmento de pila. Contiene la dirección del segmento de pila. La pila es un espacio de memoria temporal que se usa para almacenar valores de 16 bits (palabras).
ES: Registro segmento extra. Contiene la dirección del segmento extra. Se trata de un segmento de datos adicional que se utiliza para superar la limitación de los 64Kb del segmento de datos y para hacer transferencias de datos entre segmentos.
Registros punteros de pila:
SP: Puntero de la pila. Contiene la dirección relativa al segmento de la pila.
BP: Puntero base. Se utiliza para fijar el puntero de pila y así poder acceder a los elementos de la pila.
Registros índices:
SI: Índice fuente.
DI: Índice destino.
 
 
Puntero de instrucciones:

IP: Registro puntero de instrucción o contador de programa (PC). Contiene el desplazamiento de la siguiente instrucción a ejecutar respecto al segmento de código en ejecución. Por lo tanto, la dirección completa de la siguiente instrucción sería CS:IP. La única forma de influir en este registro es de forma indirecta mediante instrucciones de bifurcación.
Registro de banderas (flags):
Cada bandera es un bit y se usa para registrar la información de estado y de control de las operaciones del microprocesador. Hay nueve banderas (los 7 bits restantes no se utilizan):
Banderas de estado: 
Registran el estado del procesador, normalmente asociado a una comparación o a una instrucción aritmética.
CF: Bandera de acareo.
OF: Bandera de desbordamiento (aritmético).
ZF: Bandera de resultado 0 o comparación igual.
SF: Bandera de resultado o comparación negativa.
PF: Bandera de paridad (número par de bits).
AF: Bandera auxiliar. Indica si hay necesidad de ajuste en las operaciones aritméticas con números
BCD.
Banderas de control:
DF: Bandera de dirección. Controla la dirección de las operaciones con cadenas de caracteres
incrementando o decrementando automáticamente los registros índices (SI y DI)
IF: Bandera de interrupciones. Indica si están permitidas o no las interrupciones de los dispositivos
externos.
TF: Bandera de atrape. Controla la operación de modo paso a paso (usada por el programa DEBUG).

1.1 MACROS Y PROCEDIMIENTOS DE EMU8086

Ya hemos visto que EMU8086 trabaja con interrupciones del procesador de esa arquitectura pero es posible trabajar con librerías que incluyen macros y procedimientos para hacer mas fácil la programación en el lenguaje ensamblador.

En esta ocasión les presentare los diferentes macros y procedimientos con su respectiva descripción de la librería EMU8086.

Macros

  • PUTC char - Macro con un parámetro. Imprime un carácter ASCII en la posición actual del cursor.
  • GOTOXY col, fila - Macro con dos parámetros. Establece la posición del cursos.
  • PRINT string - Macro con 1 parámetro. Imprime una cadena.
  • PRINTN string - Macro con un parámetro. Imprime una cadena. Lo mismo que PRINT pero agrega automáticamente "retorno de carro' al final de la cadena.
  • CURSOROFF - Apaga el cursor de texto.
  • CURSORON - Enciende el cursor de texto.

Para usar cualquiera de las macros anteriores, simplemente se escribe el nombre y los parámetros donde sea conveniente.

Procedimientos

  • PRINT_STRING: Procedimiento para imprimir una cadena terminada en nulo en la posición actual del cursor, recibe la dirección de la cadena en el registro DS: SI. Para usarlo declara: DEFINE_PRINT_STRING antes de la directiva END.
  • PTHIS: procedimiento para imprimir una cadena terminada en nulo en la posición actual de cursor (igual que PRINT_STRING), pero recibe la dirección de la cadena desde la pila. La cadena terminada a cero debe definirse justo después de la instrucción CALL. Por ejemplo:

    CALL PTHIS
    DB 'HELLO WORLD', 0
    Para usarlo declare: DEFINE_PTHIS antes de la directiva END.
  • GET_STRING: procedimiento para obtener una cadena terminada en nulo de un usuario, la cadena recibida se escribe en el búfer en DS: DI , el tamaño del búfer debe estar en DX . El procedimiento detiene la entrada cuando se presiona 'Enter'. Para usarlo declare: DEFINE_GET_STRING antes de la directiva END.
  • CLEAR_SCREEN: procedimiento para borrar la pantalla (que se realiza al desplazar la ventana completa de la pantalla) y establecer la posición del cursor en la parte superior. Para usarlo declare: DEFINE_CLEAR_SCREEN antes de la directiva END.
  • SCAN_NUM: procedimiento que obtiene el número FIRMADO de varios dígitos del teclado y almacena el resultado en el registro CX . Para usarlo declare: DEFINE_SCAN_NUM antes de la directiva END.
  • PRINT_NUM: procedimiento que imprime un número firmado en el registro AX . Para usarlo declare: DEFINE_PRINT_NUM y DEFINE_PRINT_NUM_UNS antes de la directiva END .
  • PRINT_NUM_UNS: procedimiento que imprime un número sin firma en el registro AX . Para usarlo declare: DEFINE_PRINT_NUM_UNS antes de la directiva END.
 Para utilizar cualquiera de los procedimientos anteriores, primero debe declarar la función en la parte inferior de su archivo (pero antes de END ), y luego usar la instrucción CALL seguida de un nombre de procedimiento.

Suma de dos números utilizando librería

Ahora veremos como se suma en el programa emu8086 utilizando librerías. Y aquí el código:

name "suma de dos numeros"
include "emu8086.inc"
org 100h

.data
suma db 2 dup (?)
.code
sumas proc
    print " Introduce el primer numero: "
    call scan_num
    mov suma[0],cl
    printn " "
    print " Introduce el segundo numero: "
    call scan_num
    mov suma[1],cl
    xor ax,ax
    add al,suma[0]
    add al,suma[1]
    printn " "
    print " La suma es: "
    call print_num
sumas endp
exit:
    print " "
    printn " "
    print "Presiona enter para salir..."
    mov ah,0  ;servicio de pulsación de teclado
    int 16h   ;invoca a servicios de taclado
    ret
define_print_string
define_print_num
define_print_num_uns
define_scan_num
end



Resta de dos números en emu8086 utilizando librerías

Aquí el código y las capturas del programa:

name 'resta dos numeros'
include 'emu8086.inc'
org 100h

.data
resta db 2 dup (?)

.code
restas proc
printn " "
print "Introduce el primer numero: "
call scan_num
mov resta[0],cl
printn " "
print "Introduce el segundo numero: "
call scan_num
sub resta[1],cl
printn ""
xor ax,ax
add al,resta[0]
add al, resta[1]
print " "
print "La resta es: "
call print_num
restas endp

exit:
printn " "
printn " "
print "Presiona enter para salir..."
mov ah,0
int 16h
ret
define_print_string
define_print_num
define_print_num_uns
define_scan_num
end



ret


miércoles, 20 de febrero de 2019

Comparar la edad en lenguaje ensamblador

Con ustedes el código para emu8086:

ORG 100H

.MODEL SMALL
.STACK 64 ;SEGMENTO DE PILA

.DATA
DIEZ DB 10 ;VARIABLE
NUM1 DB 0 ;VARIABLE PARA EDAD
MENS DB 'INGRESE LA EDAD: $'
MENS1 DB 13,10, 'ERES MAYOR DE EDAD $'
MENS2 DB 13,10, 'ERES MENOR DE EDAD $'

.CODE
  INICIO PROC FAR
    MOV AX,@DATA ;DIRECCIONAMIENTO
    MOV DS,AX
    
    ;SE COLOCA EL PRIMER LETRERO
    MOV AH,09
    LEA DX,MENS
    INT 21H
    
    MOV AH,01
    INT 21H
    SUB AL,30H ;CONVERTIR A VALOR
    MUL DIEZ ;SE MULTIPLICA EL NUMERO INGRESADO POR DIEZ
    MOV NUM1,AL
    
    MOV AH,01
    INT 21H
    SUB AL,30H
    ADD NUM1,AL ;SE SUMA A LAS DECENAS
    MOV AL,NUM1
    
    CMP AL,18
    JGE MAYOR
    JMP MENOR
    
    MAYOR:
      MOV AH,09
      LEA DX,MENS1
      INT 21H
      JMP FIN
      
    MENOR:
      MOV AH,09
      LEA DX,MENS2
      INT 21H
      JMP FIN
    
    FIN:
      MOV AX,4C00H
    
    INICIO ENDP
  
RET







División en emu8086

El código para hacerlo en lenguaje ensamblador:

ORG 100H

MOV AX,100
MOV BX,5
DIV BX

RET


Multiplicación en emulador emu8086

Aquí está el código para el programa de la multiplicación pero no en consola:


ORG 100h

mov ax,80
mov bx,1000
mul bx
ret


Obtener el promedio y si es aprobatorio

Aquí les va el código del programa

.MODEL SMALL
.STACK 64
.DATA
    MSG1 DB 'INGRESA UNA CALIFICACION (SEGUIDO DE UN ENTER): ',13,10,'$'
    APROBADO DB 13,10, 'APROBADO$',
    REPROBADO DB 13,10, 'REPROBADO$'
 
    VAR1 DW ?, '$' ;de tipo write (escritura)
    VAR2 DW ?, '$'
    VAR3 DW ?. '$' ;para guardar enter
 
.CODE ;inicia la seccion de codigo
RESULTADO PROC FAR
    ;-----------iniciar
    MOV AX,@DATA
    MOV DS,AX
 
    ;----------desplegar el primer mensaje 
    MOV ah,09H
    LEA dx,MSG1
    INT 21H
 
    ;----------introducir un caracter
    MOV AH,01
    INT 21H
    MOV VAR1,AX
 
    ;----------introducir el segundo caracter
    MOV AH,01
    INT 21H
    MOV VAR2,AX
 
    ;----------introducir un caracter para enter
    MOV AH,01
    INT 21H
    MOV VAR3,AX
 
    ;----------uso de if y comparacion
    CMP AL,13 ; pregunta si en 'al' hay un enter
    JE continue
    JMP mayor
 
CONTINUE:
    MOV AX,VAR1
    CMP AL,037H ;37h es igual a 7 en hexadecimal, 55 es 7 en ASCII
    JGE MAYOR
    JMP MENOR
 
MAYOR:
    MOV AH,09H
    LEA DX,APROBADO
    INT 21H
    JMP FIN
MENOR:
    MOV AH,09H
    LEA DX,REPROBADO
    INT 21H
    JMP FIN
 
FIN:
    MOV AH,04CH
    INT 21H
 
RESULTADO ENDP ;fin del procedimiento
END RESULTADO




Suma de dos números en emu8086 con libreria emu8086.inc

Primero quiero decir que incluiré el código del programa, y es este:

;Creado por Magdiel Ruiz

name 'suma de dos numeros'
include 'emu8086.inc'
org 100h

.data
suma db 2 dup (?)

.code
Sumas proc
    printn " "
    print " Introduce el primer numero ==>"
    call scan_num
    mov suma[0],cl
    printn " "
    print "Introduce el segundo numero ==>"
    call scan_num
    mov suma[1],cl
    print " "
    xor ax,ax
    add al,suma[0]
    add al,suma[1]
    printn " "
    print "La suma es: "
    call print_num
 
Sumas endp

exit:
    printn " "
    printn " "
    print "Presione enter para salir..."
    mov ah,0
    int 16h
    ret
 
define_print_string
define_print_num
define_print_num_uns
define_scan_num
end


lunes, 11 de febrero de 2019

Suma y resta en emu8086

Vamos a aprender a restar y a sumar en el lenguaje ensamblador, aquí el código de la resta:

.MODEL SMALL
.STACK 64
.DATA
    N1 DB 0
    N2 DB 0
    RESTA DB 0
    MSG1 DB "DAME EL PRIMER VALOR ","$"
    MSG2 DB 10,13, "DAME EL SEGUNDO VALOR ","$"
    MSG3 DB 10,13, "RESTA = ",'$'
.CODE
 BEGIN PROC FAR
     MOV AX,@DATA
     MOV DS,AX
   
     MOV AH,09
     LEA DX,MSG1
     INT 21H
   
   
     MOV AH,01
     INT 21H
     SUB AL,30H
     MOV N1,AL
   
   
     MOV AH,09
     LEA DX,MSG2
     INT 21H
     MOV AH,01
     INT 21H
     SUB AL,30H
     MOV N2,AL
   
     MOV AL,N1
     SUB AL,N2
     ADD AL,30H
     MOV RESTA,AL
     MOV AH,09
     LEA DX,MSG3
     INT 21H
   
   
     MOV AH,02
     MOV DL,RESTA
     INT 21H
     MOV AH,4CH
     INT 21H
     BEGIN ENDP
     END



Y ahora el programa que hace la suma y su código:

.MODEL SMALL
.STACK 64
.DATA
    N1 DB 0
    N2 DB 0
    RESTA DB 0
    MSG1 DB "DAME EL PRIMER VALOR ","$"
    MSG2 DB 10,13, "DAME EL SEGUNDO VALOR ","$"
    MSG3 DB 10,13, "SUMA= ",'$'
.CODE
 BEGIN PROC FAR
     MOV AX,@DATA
     MOV DS,AX
   
     MOV AH,09
     LEA DX,MSG1
     INT 21H
   
   
     MOV AH,01
     INT 21H
     SUB AL,30H
     MOV N1,AL
   
   
     MOV AH,09
     LEA DX,MSG2
     INT 21H
     MOV AH,01
     INT 21H
     SUB AL,30H
     MOV N2,AL
   
     MOV AL,N1
     ADD AL,N2
     ADD AL,30H
     MOV RESTA,AL
     MOV AH,09
     LEA DX,MSG3
     INT 21H
   
   
     MOV AH,02
     MOV DL,RESTA
     INT 21H
     MOV AH,4CH
     INT 21H
     BEGIN ENDP
     END


jueves, 31 de enero de 2019

Suma de un número y de tres números en emu8086

Primero vamos con la de un solo dígito, este es su código:

org 100h

;suma numero de un solo digito

mov ax,8
mov bx,4
add ax,bx
mov bx,5
sub ax,bx
mov bx,3
inc bx

mov ax,6




Ahora veremos el de la suma con tres dígitos y su código:

ORG 100H


mov ax,80
mov bx,450
inc bx
add ax,80
mov cx,200
sub cx,bx
ret


miércoles, 30 de enero de 2019

Ejemplo 3 emu8086

En este ejemplo estará el cursor esperando a que se de clic, aquí el código:

.MODEL tiny
NAME "HOLA A TODOS" ;esta linea es solo para ponerle el nombre

.DATA
 DATO DB "HOLA MUNDO", 0Dh, 0Ah, 24h ;0Dh,0Ah,24h --> equivale a '\n' en c++
 DATO2 DB 'HOLA MUNDO 2$'

 ;msg2 db "Hola alumnos"
 ;msg2 db "como estas"

.CODE
INICIO:
MOV DX,OFFSET DATO ;lee el contenido de la variable dato en el resultado dx
MOV AH,09 ; para imprimir el valor ah debe contener el valor 09
INT 21H ; lo muestra en el puerto del video

MOV ah,0
INT 16h ; esperando presionar cualquier letra equivalente a un get

MOV DX,OFFSET DATO2 ; lee el contenido de la variable dato 2 en el resultado dx
MOV AH,09 ; para imprimir el valor el valor ah debe contener el valor 09
INT 21h ; lo muestra en el puerto del video

RET ; retorna el control al sistema operativo
END

en esta imagen podemos ver que esta esperando al get

ahora esta el segundo 


Ahora le hice una pequeña modificación al código para poder desplegar más de dos mensajes en pantalla, aquí el código:

.MODEL tiny
NAME "HOLA A TODOS" ;esta linea es solo para ponerle el nombre 

.DATA
 DATO DB "HOLA MUNDO", 0Dh, 0Ah, 24h ;0Dh,0Ah,24h --> equivale a '\n' en c++
 DATO2 DB "HOLA MUNDO 2", 0Dh, 0Ah, 24h
 DATO3 DB "HOLA DE PARTE DE MAGDIEL RUIZ$"
 
 ;msg2 db "Hola alumnos"
 ;msg2 db "como estas"

.CODE
INICIO:
MOV DX,OFFSET DATO ;lee el contenido de la variable dato en el resultado dx
MOV AH,09 ; para imprimir el valor ah debe contener el valor 09
INT 21H ; lo muestra en el puerto del video

MOV ah,0
INT 16h ; esperando presionar cualquier letra equivalente a un get

MOV DX,OFFSET DATO2 ; lee el contenido de la variable dato 2 en el resultado dx
MOV AH,09 ; para imprimir el valor el valor ah debe contener el valor 09
INT 21h ; lo muestra en el puerto del video

MOV ah,0
INT 16h ; esperando presionar cualquier letra equivalente a un get

MOV DX,OFFSET DATO3 ; lee el contenido de la variable dato 2 en el resultado dx
MOV AH,09 ; para imprimir el valor el valor ah debe contener el valor 09
INT 21h ; lo muestra en el puerto del video


RET ; retorna el control al sistema operativo
END


Ya cuenta 3 mensajes en pantalla

Ejemplo 2 en emu8086

Ahora veremos el ejemplo del programa 2 de como mostrar "Hola Mundo!" pero en posición 0

CODIGO:
CODE SEGMENT
    ASSUME CS:CODE, DS:CODE, SS:CODE, ES:CODE
    ORG 100H
   
principio:
 mov ah, 0Fh
 mov ah, 0
 int 10h
 lea dx, mensaje_a_mostrar
 mov ah, 9h
 int 21h
 int 20h
 mensaje_a_mostrar db "Hola Mundo!$",0

 CODE ENDS
end principio


Ensambladores online

Primero veremos como ensamblar en línea en esta liga, y aquí está el código:

; Simple example
; Writes Hello World to the output

JMP start
hello: DB "Magdiel Ruiz!" ; Variable
       DB 0 ; String terminator

start:
MOV C, hello    ; Point to var
MOV D, 232 ; Point to output
CALL print
        HLT             ; Stop execution

print: ; print(C:*from, D:*to)
PUSH A
PUSH B
MOV B, 0
.loop:
MOV A, [C] ; Get char from var
MOV [D], A ; Write to output
INC C
INC D 
CMP B, [C] ; Check if end
JNZ .loop ; jump if not

POP B
POP A
RET

Lenguaje ensamblador en línea 1

Añadir leyenda


Ahora veremos en el segundo lenguaje ensamblador en línea:
Lenguaje ensamblador en línea 2

section .text
global _start       ;must be declared for using gcc
_start:                     ;tell linker entry point
mov edx, len    ;message length
mov ecx, msg    ;message to write
mov ebx, 1     ;file descriptor (stdout)
mov eax, 4     ;system call number (sys_write)
int 0x80        ;call kernel
mov eax, 1     ;system call number (sys_exit)
int 0x80        ;call kernel

section .data

msg db 'Magdiel RUiz',0xa ;our dear string
len equ $ - msg ;length of our dear string


Y por ultimo en el ultimo lenguaje ensamblador en línea:

Lenguaje ensamblador en línea 3

;nasm 2.11.08

section .data
    hello:     db 'Magdiel Ruiz!',10    ; 'Magdiel Ruiz!' plus a linefeed character
    helloLen:  equ $-hello             ; Length of the 'Hello world!' string

section .text
global _start

_start:
mov eax,4            ; The system call for write (sys_write)
mov ebx,1            ; File descriptor 1 - standard output
mov ecx,hello        ; Put the offset of hello in ecx
mov edx,helloLen     ; helloLen is a constant, so we don't need to say
                     ;  mov edx,[helloLen] to get it's actual value
int 80h              ; Call the kernel

mov eax,1            ; The system call for exit (sys_exit)
mov ebx,0            ; Exit with return code of 0 (no error)
int 80h;


martes, 29 de enero de 2019

Historia del lenguaje ensamblador

Para poder programar en Bajo nivel(Ensamblador) debemos conocer desde lo básico hasta lo mas complicado.
La primera computadora programable fue la ENIAC en 1946 pero se programaba mediante circuitos complejos que no eran nada funcionales. Después se empezó a utilizar el lenguaje maquina que son claves binaras que representan un CÓDIGO DE OPERACIÓN(OPCODE). Estas se almacenan en grupos de instrucciones llamados PROGRAMAS.

Esto llego a ser muy complicado debido a que se debían aprender series enormes de códigos binarios para realizar operaciones. Por ejemplo:
Para realizar la suma se tenia una instrucción binaria muy similar a "00101010010100101". Es por eso que se complicaba demasiado manejar este tipo de programación.

Actualmente manejamos lenguajes de Alto nivel que son relativamente sencillos a comparación con el lenguaje maquina. Pero no se llego al alto nivel desde el código binario, existe un lenguaje que nació para facilitar el binary code. Este se llama "LENGUAJE ENSAMBLADOR".

QUE ES EL LENGUAJE ENSAMBLADOR?
Es la primera abstracción del lenguaje maquina , consiste en asociar los OPCODE con palabras clave que sean fáciles de recordar para el programador.
A estas palabras clave se les llama MNEMÓNICOS.
Un programa ensamblador traduce el o convierte el codigo fuente(ensamblador) a codigo objeto(lenguaje maquina).
La computadora UNIVAC fue la primera en usar ensamblador.

¿Que necesito saber antes de usar lenguaje ensamblador?(OJO)
-Conocer a detalle como traba el micro.
-conocer a detalle como opera la computadora(Memoria, discos duros, dispositivos E/S)
-Lógica computacional.
-Manejar algún lenguaje de alto nivel(C, C++, C#, Pascal, Perl, VB, JAVA, etc...)
-Manejo del sistema binario y hexadecimal(suma, resta, multiplicación, división).


¿Que ventajas ofrece el lenguaje ensamblador?
-Optimizan al máximo los programas en tamaño y velocidad.
-Rápidos y compactos.
-No genera código predefinido como el alto nivel.
-No se necesita capacidades de memoria ni computadoras sofisticadas.
-Nos da habilidades de programación avanzada.

Que desventajas tiene?(OJO)
-Una instrucción mal interpetada puede generar un caos en nuestro equipo al grado de tener que reiniciar nuestra maquina.
-La insuficiencia de conocimientos básicos y de programación causa efectos impredecibles.
-Se vuelve mas complejo conforme se agregan rutinas y funciones.
-Se pueden usar con lenguajes de alto nivel(PROGRAMACIÓN HÍBRIDA).

Aplicaciones actuales.
Sistemas embebidos: Impresoras, cámaras, autos, armas, juguetes.
Tiempo real: Control de robots, manufactura, adquisición de datos.
Transporte: Barcos, aviones, sondas espaciales.
Entretenimiento: Graficación, multimedia, videojuegos.
DSP: Procesador digital de señal para operaciones a alta velocidad.
Procesamiento de señales, voz e imagen:
-aparatos médicos
-aparatos para datos sísmicos
-reproductores de audio
-módems
-cámaras digitales.

PROGRAMANDO EN EMU8086

Ahora vamos a programar en un programa llamado emu8086

este es el código:

.MODEL SMALL
.STACK
.DATA
CADENA1 DB 'HOLAMUNDO.$'
CADENA2 DB 'MAGDIELRUIZ.$'
.CODE
PROGRAMA:
 MOV AX,@DATA
 MOV DS,AX
 MOV DX,OFFSET CADENA1
 MOV AH,9
 INT 21H
 MOV DX,OFFSET CADENA2
 MOV AH,9
 INT 21H
END PROGRAMA

Ahora veamos el programa con  su corrida