; Programa PARAM.ASM que escribe un mensaje en pantalla
; en funcion del parametro que se le pasa en la
; linea de comandos
;	Ej: c:\param 3
;	ASI PSP+80h = ( 2 caracteres:blanco + '3')
;	PSP+81h = blanco, PSP+82h = '3'
;
	NAME	Param
;
; Macro per INT 21h
DosCall	MACRO 	Serv
	MOV	AH,Serv
	INT	21h
ENDM
;
; Macro para inicializar ES apuntando al segmento data
InitES	MACRO
		MOV	AX,data
		MOV 	ES,AX
	; establece direccionamiento segmento de datos
		ASSUME ES:data
ENDM
;
; Macro para inicializar DS apuntando al segmento data
InitDS	MACRO
		MOV	AX,data
		MOV	DS,AX
	; establece direccionamiento segmento de datos
		ASSUME DS:data
ENDM
;
pila	SEGMENT para stack 'STACK'
		DB	128 DUP(0)
pila	ENDS
;
data	SEGMENT word public 'DATA'
	; definiciones de datos
	msg_long DB 15 		;longitud del mensaje	
	parm	DB 128 DUP(0)	;area para mover datos
	msg_vec DB "Debes dividir un gran problema en dos "
		DB "La programación del 8086 es divertida " 
		DB "El BASIC era más sencillo, claro!  " 
		DB "El PSP es muy útil ¿ lo ves ahora ?  "
		DB "Con paciencia se puede programar todo  "
		DB "Ultimo mensaje del día           "
	NMSG 	= 6 ;numero de mensajes
	msg_err	DB "Error: parametro no valido         "
	msg_err1 DB "Error primer               "
	msg_err2 DB "Error segon               "
	msg_err3 DB "Error tercer               "
	msg_err4 DB "Error quart               "
	msg_err5 DB "Error cinquè               "
data	ENDS
;
;
;
;
code	SEGMENT byte public 'CODE'
	ASSUME CS:code
main	PROC	far
	;
	; Prólogo estándar del programa
	;
	InitDS
	InitES
	; Instrucciones de código
	; Mover area de parametros desde el PSP hasta nuestro
	; segmento de datos
		MOV 	SI,80h ; direccion origen DS:SI, DS=PSP+0
		MOV	DI,OFFSET parm ; direccion destino de ES:DI
		MOV	CX,128	; longitud de la cadena a mover
		CLD	; operaciones de cadena hacia adelante
		REP MOVSB
	; Inicializamos ahora el DS que apunte a nuestros datos
	InitDS
	; Comprobación de validez de los datos y conversión
	; a valor numérico
		MOV	AX,0
	; El primer carácter debe ser un espacio en blanco
	; El segundo carácter debe ser el numero de mensaje escogido
		CMP 	parm,2 ; num de car 2?
		JNZ 	error1 ;si no es =2 saltar a error
		MOV	AL,[parm+2] ;tomar el segundo carácter
		SUB	AL,'0' ;convers. de ASCII a num
		JC	error ;error si no es un numero
		CMP	AL,NMSG ; AL=num de mensajes
		JA 	error ;si es mayor que el numero de mensajes
	;seleccionar mensaje
		MOV 	BX,OFFSET msg_vec ;dir. del 1er mens.
		MUL	msg_long ;AX=AL*msg_long
		ADD 	BX,AX ;desplazamos puntero BX segun el mnsj.
		CALL	Escribe
	;
		DosCall	4Ch ;Retorno al DOS
		RET
	error:
		MOV	BX,OFFSET msg_err
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
	error1:
		MOV	BX,OFFSET msg_err1
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
	error2:
		MOV	BX,OFFSET msg_err2
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
	error3:
		MOV	BX,OFFSET msg_err3
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
	error4:
		MOV	BX,OFFSET msg_err4
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
	error5:
		MOV	BX,OFFSET msg_err5
		CALL Escribe
		DosCall	4Ch ;Retorno al DOS
	;
		RET
	;
main	ENDP
;
;
; Procedimiento para escribir en pantalla el mensaje apuntado porBX
; de longitud msg_long
;
Escribe	PROC near
		MOV	CH,0
		MOV	CL,msg_long ;num de caract. a escribir
	;
	Escr1:
		MOV	AL,[BX] ;AL=caracter actual
		CALL	Escribe_Car ;escribe un caracter
		INC	BX
		LOOP	Escr1 ;siguiente caract.
	;
		MOV	AL,13 ;caracter de retorno
		CALL	Escribe_Car
		MOV	AL,10 ;caracter de LF linefeed (slto.lin.)
		CALL	Escribe_Car
	;
		RET
Escribe	ENDP
;
;
;Procedimiento para escribir en pantalla el caractes en AL:
;
Escribe_Car	PROC near
		PUSH	BX ;salva registro BX
		MOV	BX,0
		MOV	AH,14 ;servicio 14 = escritura
		INT	10h ;interrupcion BIOS de pantalla
		POP	BX
	;
		RET
Escribe_Car	ENDP
;
code	ENDS
	END	main