;--------------------------
; INICIO
;--------------------------
cli ; Desactivamos interruptores
mov ax,0x1000 ; AX = 0x1000 donde es cargado el kernel
mov ds,ax ; DS = 0x1000
mov es,ax ; ES = 0x1000
mov ss,ax ; SS = 0x1000
mov sp,0xFFFF ; SP = 0xFFFF final de la memoria
sti ; Reactivamos los interruptores
call clear ; Borramos la pantalla
call cursor ; Ponemos el cursor
mov si,NoDOS ; Apuntamos SI a la cadena
call puts ; Ponemos el prompt
mov si,elprompt; Apuntamos SI a la cadena
call puts ; Ponemos el prompt
;-------------------------------------------------------------------------------
;--------------------------
; MAIN (CLI)
;--------------------------
main:
hlt ; Evitamos que el CPU se caliente (halt)
mov cx,64 ; Limitamos las cadenas a 60 caracteres
mov di,comando; Apuntamos a la cadena del comando
call gets ; Obtenemos el comando del teclado
procesar:
pusha ; Guardamos todos los registros en la pila
push es ; Guardamos ES en la pila
;---------
; cHOLA
;---------
mov si,comando; Ponemos la direccion de "comando" en SI
mov cx,5 ; Numero de letras del comando (incluye el 0)
mov di,cHOLA ; Apuntamos DI a la cadena del comando
repe cmpsb ; REPE = Repetir mientras sea igual y
; disminuir CX
; CMPSB = Comparar SI con DI
; SI+1 y DI+1
jne no_cHOLA ; Si no es igual seguimos
call saludar ; Llamamos a la funcion saludar
jmp fin_procesar; Terminamos con este comando
no_cHOLA:
;--------------------------
; PONER COMANDOS AQUI!!
;--------------------------
fin_procesar:
call prompt ; Ponemos el prompt
pop es ; Recuperamos ES
popa ; Recuperamos los registros generales
jmp main ; Repetimos
;-------------------------------------------------------------------------------
;--------------------------
; FUNCIONES
;--------------------------
clear: ; CLEAR @@@@
mov ah,0x06 ; AH = 0x06 BIOS Scroll
mov al,0x00 ; AL = 0x00 (lineas) 0 = Pantalla completa
mov bh,0x07 ; BL = 0x07 0 = Fondo Negro, 7 = Texto Blanco
mov ch,0x00 ; CH = 0x00 Linea superior (y = 0)
mov cl,0x00 ; CL = 0x00 Columna Izquierda (x = 0)
mov dh,0x18 ; DH = 0x18 Linea Inferior (y = 24)
mov dl,0x4F ; DL = 0x4F Columna Derecha (x = 79)
int 0x10 ; BIOS VIDEO
ret
;-------------------------------------------------------------------------------
prompt: ; PROMPT @@@@
mov si,elprompt; SI apunta a la cadena
call puts ; Llamamos al procedimiento puts
ret ; Regresamos
;-------------------------------------------------------------------------------
cursor: ; CURSOR @@@@
mov ah,0x02 ; BIOS posicion del cursor
mov bh,0x00 ; Pagina de memoria
mov dh,0x00 ; Fila, posicion en Y
mov dl,0x00 ; Columna, posicion en x
int 0x10 ; BIOS VIDEO
ret ; Regresamos
;-------------------------------------------------------------------------------
saludar: ; SALUDAR @@@@
mov si,hola ; SI apunta a la cadena
call puts ; Llamamos al procedimiento print
ret ; Regresamos
;-------------------------------------------------------------------------------
putc: ; PUTC @@@@
push ax ; Guardamos AX en la pila
cmp al,0x09 ; Comparamos Al para ver si es TAB (0x09)
je .esTAB ; Si es TAB saltamos
mov ah,0x0E ; BIOS poner caracter
mov bh,0x00 ; Pagina 0
mov bl,0x07 ; Blanco sobre Negro
int 0x10 ; BIOS VIDEO
jmp .fin ; Terminamos
.esTAB:
mov al,0x20 ; Ponemos en AL el caracter de espacio
call putc ; Llamamos a esta misma funcion 5 veces
call putc ; para poner en pantalla un TAB
call putc ; de 5 espacios
call putc ; ...
call putc ; ...
.fin:
pop ax ; Recuperamos AX de la pila
ret ; Regresamos
;-------------------------------------------------------------------------------
gets: ; GETS @@@@
push cx ; Guardamos CX en la pila
push ax ; Guardamos AX en la pila
push dx ; Guardamos DX en la pila
push di ; Guardamos DI en la pila
mov dx,di ; Guardamos el inicio de la cadena en SI
.tecla:
cmp cx,0 ; Terminamos?
je .fin ; Si CX es 0 terminamos
xor ax,ax ; AH = 0 - BIOS obtener tecla
int 0x16 ; BIOS Servicios de Teclado
dec cx ; CX = CX-1
cmp al,0x0D ; Es ENTER? (ascii decimal 13)
je .enter ; Si es igual terminamos
cmp al,0x08 ; Es Backspace (ascii decimal 8)
je .backspace; Si es igual saltamos a backspace
call putc ; Si no ponemos el caracter
mov [di],al ; Copiamos AL (caracter) en la cadena [DI]
inc di ; DI = DI+1
jmp .tecla ; Repetimos con la siguiente tecla
.backspace:
cmp dx,di ; Comparamos con el principio de la cadena
je .tecla ; Si son iguales pedimos otra tecla
dec di ; DI = DI-1
mov ah,0Eh ; BIOS Poner caracter
mov al,0x08 ; Movemos el cursor hacia atras (backspace)
mov bh,0x00 ; Pagina 0
mov bl,0x01 ; Borramos
int 0x10 ; BIOS VIDEO
mov ah,0Eh ; BIOS Poner caracter
mov al,0x20 ; Ponemos espacio
mov bh,0x00 ; Pagina 0
mov bl,0x01 ; Borramos
int 0x10 ; BIOS VIDEO
mov ah,0Eh ; BIOS Poner caracter
mov al,0x08 ; Movemos el cursor hacia atras (backspace)
mov bh,0x00 ; Pagina 0
mov bl,0x01 ; Borramos
int 0x10 ; BIOS VIDEO
jmp .tecla ; Pedimos otra tecla
.enter:
mov al,0x0D ; Retorno de Linea (13)
call putc ; Ponemos en pantalla
mov al,0x0A ; Nueva Linea (10)
call putc ; Ponemos en pantalla
.fin:
mov byte [di],0; Terminamos la cadena con cero
pop di ; Recuperamos los registros
pop dx ; ...
pop ax ; ...
pop cx ; ...
ret ; Regresamos
;-------------------------------------------------------------------------------
puts:
lodsb ; Cargamos el caracter de DS:SI en AL
or al,al ; Hacemos un OR al registro AL
jz .fin_puts ; Terminamos si es cero
mov ah,0x0E ; Poner caracter (parametro int 0x10)
int 0x10 ; BIOS VIDEO
jmp puts ; Siguiente caracter
.fin_puts:
ret ; termina el procedimiento y regresamos
;-------------------------------------------------------------------------------
;--------------------------
; VARIABLES
;--------------------------
comando: times 128 db 0; Espacio para almacenar el comando
elprompt db '@:',0 ; El prompt "@:"
cHOLA db "hola",0 ; Comando "hola"
hola db "Hola CLI!!",13,10,0; Texto del comando "hola"
NoDOS db "NoDOS 0.1",13,10,0; Cadena de Bienvenida!