;***************************************************;
;   programa de ordenacion de letras y numeros      ;
;   PROGRAMADO POR PAMTUMACA STUDIOS		    ;
;   Miembros:					    ;
;	Pau Bitlloch Puigvert			    ;
;	Xavier Lligadas Rodriguez		    ;
;   Contacto:					    ;
;	newthalion@hotmail.com			    ;
;***************************************************;
;
;Este programa solo tiene en cuenta las letras y numeros
;que le entre el usuario, cualquier otro codigo ascii
;sera suprimido de la frase inicial.
;
;Tieneque ser linkado con el archivo strasm que contiene
;los subprogramas STRINP, STRLON, INTASTR, STRAINT.
EXTRN           STRINP:FAR, STRLON:FAR, INTASTR:FAR, STRAINT:FAR
;
;Macro de llamada de servicios del dos
DosCall MACRO serv
	mov	ah, serv
	int	21h
	ENDM
;Macro para inicializar ds
InitDS	MACRO
	MOV AX, data
	MOV DS, AX
	ASSUME DS:data
	ENDM
;Macro para inicializar es
InitES	MACRO
	MOV AX, data
	MOV ES, AX
	ASSUME DS:data
	ENDM
;****************************************************;
;Definimos nuestro segmento de pila
;Guardamos mucho espacio devido al uso de un algoritmo
;recursivo (quicksort)
PILA SEGMENT PARA STACK 'STACK'
	db 256 dup(0)
PILA ENDS
;
;*****************************************************;
;Definimos nuestro segmento de datos
DATA SEGMENT PARA PUBLIC 'DATA'
	term db "$"
	ourcode_term db "}"
	msg1 db 13,10,"Entra les lletres a ordenar. (maxim 254): $"
	msg2 db 13,10,"Frase entrada:  $"
	msg3 db 13,10,"Frase ordenada: $"
	msg4 db 13,10,"Numero de letras procesadas: $"
	msg5 db 13,10,"Numero de letras ordenadas: $"
	frase db 256 dup(0)	  ;Entrada del usuario sin modificar
	frase_cod db 256 dup(0)   ;La frase codificada para que pueda
				  ;ser ordenada con quicksort
	orden_cod db 256 dup(0) ;frase codificada ordenada
	orden db 256 dup(0) 	;frase  en ascci ordenada
	longitut db 0	;guardaremos la longitut de nuestro codigo transformado 
	canvis db 0 	;on guardarem el numero de canvis fet pel nostre programa
	canvis_str db 4 dup(0)      ;string para mostrar los canvios
	longitut_str db 4 dup(0)    ;string para mostrar las letras procesadas
DATA ENDS
;
;*****************************************************;
;Empezamos nuestro codigo
CODE SEGMENT PARA PUBLIC 'CODE'
	assume cs:code
;*****************************************************
;Procedimiento MAIN: nos controla todo el proceso de *
;nuesto programa.                                    *  
;*****************************************************
MAIN PROC NEAR
;Inicializamos el registro de datos extendido
	InitES
;Copiamos en nuestra zona de datos la frase entrada por el usuario por la
;linea de comandos, sino entra frase le pediremos una por pantalla
	LEA ax, frase
	push ax
	call COMANDLINE
	add sp,2 ;tornem la pila a la posicio inicial
;Ahora inicializamos el registro DS
	mov bx, ax  ;ponemos en bx la longitut de la cadena para poder usar InitDS
	InitDS
;miramos si ha entrado la frase por comandos o no
	cmp bx,0
	JG empezar  ;si la frase es entrada por comandos empezamos la ordenacion    
;Pedimos al usuario que entre una frase
	lea dx, msg1
	DosCall 09h
;Leemos la frase que entra el usuario usando strinp
	;pasamos a strinp los argumentos
	lea dx, frase  ;direccion de la cadena donde guardar la entrada
	push dx
	mov al, term   ;caracter de terminacion de nuestros string
	xor ah, ah
	push ax
	;llamamos a la funcion que nos guarda la entrada
	call strinp 
	add sp, 4      ;la pila apunta al principio de nuevo
empezar:
;Transformamos el codigo ascci a un codigo ordenable usando ourcode
	;le pasamos a Ourcode la frase en código ascii,
	;el string donde pondremos codigo transformado 
	;y el caracter de terminacion
	lea dx, frase
	push dx
	lea dx, frase_cod
	push dx
	mov al, term
	mov ah, 0
	push ax
	call ourcode
	;en ax tenemos la direccion final de la frase
	lea bx, frase_cod
	sub ax, bx      ;en ax tenemos el numero de letras de nuestra frase
	mov longitut, al  ;longitut tiene el numero de letras de nuestra frase codificada
	add sp, 6	;devolvemos la pila a su posicion inicial
;copiamos la frase codificada a la zona de memoria que vamos a ordenar
	;preparamos los argumentos para MOVDATA
	lea bx, frase_cod
	push bx
	lea bx, orden_cod
	push bx
	;en ax tenemos el numero de letras, lo incrementamos para que tambien copie el
	;fin de string en nuestro codigo
	inc ax
	push ax
	call movdata
	add sp,6	;devolvemos la pila a su posicion inicial
;Hacemos la ordenacion de la frase con quicksort
	;pasamos los argumentos a quicksort
	xor	ah, ah
	mov 	al, longitut	;Tendremos en ax la longitut de la frase codificada
	lea	bx,orden_cod
	push	bx		;Apilamos el principio de la cadena
	add	bx,ax
	dec	bx		;BX apunta al caracter anterior a fin de cadena 
	push	bx		;Guardamos en la pila la direccion de fin de cadena
	call	quicksort
	add	sp,4
;Comparamos la frase inicial con la frase ordenada
	;pasamos los argumentos a COMPSTRING
	lea bx, frase_cod
	push bx
	lea bx, orden_cod
	push bx
	mov al, longitut
	xor ah, ah
	push ax
	;cridem a comp string que ens deixa en ax el numero de diferencies
	call compstring
	add sp, 6
	;guardamos el numero de canvios
	mov canvis, al
;Destransformamos el codigo de ordenacion a codigo ascii
	;frase ordenada.
	;Pasamos los argumentos a codeascii
	lea	dx, orden_cod
	push	dx		;Pasamos la direccion de la frase codificada
	lea	dx, orden	;Pasamos la direccion donde guardar 
	push	dx		;la frase ordenada en ascii
	mov	al, ourcode_term
	xor	ah, ah
	push	ax		;Pasamos el caracter final de nuestro codigo
	call 	codeascii
	add	sp,6		;devolvemos la pila a su posicion inicial
	;frase no ordenada.
	;pasamos los argumentos a codeascii
	lea	dx, frase_cod
	push	dx		;direccion de la frase codificada
	lea	dx, frase	
	push	dx		;direccion donde poner la frase ascii
	mov	al, ourcode_term
	xor	ah, ah
	push	ax		;pasamos el caracter final de nuestro codigo
	call	codeascii
	add	sp,6		;devolvemos la pila a su posicion inicial
;Convertimos el numero de canvios en un string
	LEA BX, canvis_str
	PUSH    BX	;offset de la cadena donde queremos copiar el entero
	XOR  DX,DX
	MOV  DL,term	;caracter de terminacion que queremos en el string
	PUSH    DX
	xor	ax, ax
	mov	al, canvis
	PUSH    ax            ;Apilar el numero de canvios
	CALL    INTASTR       ;Convertimos a cadena alfanumèrica
	ADD     SP,6          ;Restauramos la pila
;Convertimos el numero de letras procesadas a string
	LEA BX, longitut_str
	PUSH    BX	;offset de la cadena donde queremos copiar el entero
	XOR  DX,DX
	MOV  DL,term	;caracter de terminacion que queremos en el string
	PUSH    DX
	xor	ax, ax
	mov	al, longitut
	PUSH    ax            ;Apilar el numero de letras
	CALL    INTASTR       ;Convertimos a cadena alfanumèrica
	ADD     SP,6          ;Restauramos la pila
;Mostramos al usuario el resultado final.
;Mostramos la frase sin ordenar
	lea	dx, msg2
	DosCall 09h
	lea	dx, frase
	DosCall 09h
;Mostramos la frase ordenada
	lea	dx, msg3
	DosCall 09h
	lea	dx, orden
	DosCall 09h
;Mostramos el numero de letras procesado
	lea	dx, msg4
	DosCall 09h
	lea	dx, longitut_str
	DosCall 09h
;Mostramos el numero de canvios producido
	lea	dx, msg5
	DosCall 09h
	lea	dx, canvis_str
	DosCall 09h	
;Volvemos el control al DOS
	DosCall 4ch
	ret
MAIN ENDP

;***********************************************************
;Procedimiento OURCODE: Nos transforma el codigo ascci de   
;	la frase entrada en un codigo propio ordenable del  
;	tipo:                                                 
;	| 0 | ... | 9 | a | ... | z | A | ... | Z |   ascii      
;	| 0 | ... | 9 |10 | ... |64 |11 | ... |65 |   decimal	    
;***********************************************************
;Recibe 3 argumentos:
;		1-direccion de la frase en ascii
;		2-direccion de donde guardar la frase codificada
;		3-caracter de terminacion de la frase
;devuelve:
;		ax->direccion final de la frase transformada 
;***********************************************************	
OURCODE PROC NEAR
;
;Preparamos nuestro puntero para movernos por la pila
;
	push bp
	mov bp, sp
;
;Cogemos los argumentos de ourcode
;
	mov si, [bp+8] ;direccion de la frase
	mov di, [bp+6] ;direccion de la frase con nuestro codigo
	mov dx, [bp+4] ;caracter de terminacion de nuestras string
;
;Comenzamos el algoritmo de transformacion de ascii a nuestro codigo
;
;Comenzamos el loop
;
transform:
	;miramos si el siguiente caracter es el de terminacion
	mov	ax, [si]
	xor	ah, ah		
	cmp	ax, dx
	JE	fin
	;miramos si es un digito
	cmp	ax, '0'
	JGE	digitos
	;si no es un digito continua con el siguiente caracter sin hacer nada
	inc	si
	jmp	transform
fin:
	;guardamos el valor de fin de nuestro codigo al final de la
	;frase transformada, devolvemos el valor inicial a bp y salimos. 
	mov	al, ourcode_term
	mov	[di], al
	;devolvemos la direccion final de la cadena transformada en ax
	mov	ax,di
	pop	bp
	ret
digitos:
	;si es mayor que el ascii 9 miramos si es una mayuscula
	cmp	ax, '9'
	JG	mayusculas  
	;usamos el algoritmo de transformacion para digitos y seguimos con 
	;el siguiente caracter.
	sub	ax, '0'
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
mayusculas:
	cmp	ax, 'A'
	JGE	entre_A_B
	;el ascii introducido no lo procesamos y continuamos con el siguiente
	inc	si
	jmp	transform
entre_A_B:
	cmp	ax, 'B'
	JG	entre_C_CH
	;el ascii introducido es A o B, lo transformamos
	sub	ax, 'A'
	shl	ax,1
	add	ax,11
	;guardamos el valor y continuamos con el siguiente caracter 
	mov	[di],al
	inc	di
	inc	si
	jmp transform
entre_C_CH:
	cmp	ax, 'C'
	JG	entre_D_N
	;miramos si el siguiente es una H, entonces tendriamos CH
	push	ax	;guardamos la C
	inc	si	
	mov	ax,[si] ;miramos el siguiente caracter
	mov	ah,0
	cmp	ax, 'H'  ;si no es H seguimos con la C
	JNE	es_C
	;tenemos una CH (transformamos a nuestro codigo)
	mov	ax, 'D'
	sub	ax, 'A'
	shl	ax,1
	add	ax,11
	mov	[di],al
	inc	di
	inc	si
	pop	ax
	jmp	transform
es_C:
	;tranformamos a nuestro codigo y ya no incrementamos si pues fue
	;incrementado al mirar si teniamos una CH
	pop	ax	;tenemos el codigo ascii 'C'
	xor	ah,ah
	sub	ax, 'A'
	shl	ax,1
	add	ax,11
	mov	[di],al
	inc	di
	jmp	transform
entre_D_N:
	;miramos si es mayor que N si no significa que esta entre D y N
	cmp	ax, 'N'
	JG	posible_Ñ
	sub	ax, 'A'
	shl	ax,1
	add	ax,13  ;ya no es 11 devido a que entre medio podemos tener CH
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
posible_Ñ:
	cmp	ax, 165	  ;165 es el caracter de Ñ en decimal. ('Ñ' no funcionaba)
	JNE	entre_O_Z
	;Tenemos una Ñ, hacemos la transformacion
	mov	ax, 'O' ;'O' el valor ascii que tendria que tener Ñ si todo fuese normal
	sub	ax, 'A'
	shl	ax,1
	add	ax,13 
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
entre_O_Z:
	;miramos si es mayor que Z, sino esta entre O y Z
	cmp	ax, 'Z'
	JG	minusculas
	sub	ax, 'A'
	shl	ax,1
	add	ax,15    ;Ahora es 15 por culpa de la CH y la Ñ
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
minusculas:
	cmp	ax, 'a'
	JGE	entre_a_b_min
	;el ascii introducido no lo procesamos
	inc	si
	jmp	transform
entre_a_b_min:
	cmp	ax, 'b'
	JG	entre_c_ch_min
	;transformamos el ascii a nuestro codigo
	sub	ax, 'a'
	shl	ax,1
	add	ax,10     ;devido a que son minusculas le sumamos 10
	;guardamos el codigo transformado
	mov	[di],al
	inc	di
	inc	si
	jmp transform
entre_c_ch_min:
	cmp	ax, 'c'
	JG	entre_d_n_min
	;miramos si tenemos ch
	push	ax		;guardamos por si al final no tenemos ch
	inc	si
	mov	ax,[si]
	xor	ah,ah
	cmp	ax, 'h'
	JNE	es_c_min
	;tenemos una ch (transformamos a nuestro codigo)
	mov	ax, 'd'   ;'d' codigo ascii que tendria que tener ch
	sub	ax, 'a'
	shl	ax,1
	add	ax,10
	;guardamos el codigo transformado i seguimos con la transformacion
	mov	[di],al
	inc	di
	inc	si
	pop	ax
	jmp	transform
es_c_min:
	;tranformamos a nuestro codigo y ya no incrementamos si porque ha 
	;sido incrementada al mirar si teniamos ch
	pop	ax
	xor	ah,ah
	sub	ax, 'a'
	shl	ax,1
	add	ax,10
	mov	[di],al
	inc	di
	jmp	transform
entre_d_n_min:
	cmp	ax, 'n'
	JG	posible_ñ_min
	;el caracter esta entre 'd' y 'n'
	sub	ax, 'a'
	shl	ax,1
	add	ax,12	;12 devido a incluir ch y CH entre medio
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
posible_ñ_min:
	cmp	ax, 164		;164 codigo ascii de ñ
	JNE	entre_o_z_min
	;es una Ñ, empezamos la conversion de codigo
	mov	ax, 'o'   ;'o' codigo ascii que tendria que tener la ñ
	sub	ax, 'a'
	shl	ax,1
	add	ax,12
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
entre_o_z_min:
	;si el caracter es mayor que 'z' seguimos con el siguiente
	;sin hacer nada
	cmp	ax, 'z'
	JG	nada
	sub	ax, 'a'
	shl	ax,1
	add	ax,14	;devido a incluir ch, CH y ñ, Ñ.
	mov	[di],al
	inc	di
	inc	si
	jmp	transform
nada:
	;incrementamos los apuntadores y seguimos la transformacion
	inc	si
	jmp	transform
OURCODE ENDP

;*********************************************************
;Procedimiento CODEASCII: Transforma una frase en nuestro
;	codigo al codigo ascci.
;*********************************************************
;Argumentos:
;	1-direccion de la frase en nuestro codigo
;	2-direccion donde poner la frase en codigo ascii
;	3-caracter de terminacion de nuestro codigo '}'
;*********************************************************

CODEASCII PROC NEAR
;
;Preparamos nuestro puntero a la pila
;
	push bp
	mov bp, sp
;
;Agafem els arguments de OurCode
;
	mov si, [bp+8] ;direccion de la frase en nuestro codigo
	mov di, [bp+6] ;direccion donde poner la frase en ascii
	mov dx, [bp+4] ;caracter de terminacion de nuestro codigo
;
;Comenzamos el algoritmo de transformacion de nuestro codigo
;
;Comenzamos el loop
;
continue:
	;miramos si hemos llegado al final
	mov	ax, [si]
	xor	ah, ah
	cmp	ax, dx
	JE	final
	;sino estamos en final empezamos por ver si tenemos numeros
	cmp	ax, 0
	JGE	digits
	;esto significaria un fallo, pues tras usar ourcode todos los
	;caracteres tendrian que ser transformables
	inc	si
	jmp	continue
final:
	;colocamos a la nueva frase en ascii el final y devolvemos a bp
	;su valor inicial
	mov	ax, '$'
	mov	[di], al
	pop	bp
	ret
digits:
	;si no es un digito es una letra
	cmp	ax, 9
	JG	letras
	;transformamos a digitos ascii, lo guardamos en memoria y continuamos
	add	ax,'0'
	mov	[di],al
	inc	di
	inc	si
	jmp	continue
letras:
	;miramos si esta entre a y c y sus mayusculas
	cmp	ax, 15	;15 es C en nuestro codigo
	JG	posible_ch 
	;si es impar es una mayuscula sino es una minuscula
	mov	cx,ax
	shr	cx,1
	JC	entre_AyC
	;entre_ayc, es minuscula, empezamos el algoritmo de conversion
	sub	ax, 10	;de los digitos
	shr	ax,1	;devido a que entre medio hay mayusculas
	add	ax,'a'
	;lo guardamos y continuamos
	mov	[di], al
	inc	di
	inc 	si
	jmp	continue
entre_AyC:
	;era una mayuscula, hacemos la conversion
	sub	ax,11
	shr	ax,1
	add	ax,'A'
	mov	[di], al
	inc	di
	inc	si
	jmp	continue
posible_ch:
	cmp	ax, 16		;16 es el valor de ch en nuestro codigo
	JNE	posible_CH_may
	;convertimos nuestro codigo a los dos codigos ascii 'c' y 'h'
	mov	ax, 'c'
	mov	[di], al	
	;pasamos a la siguiente zona de memoria de la frase en ascii
	inc	di
	;copiamos el caracter 'h'
	mov	ax, 'h'
	mov	[di], al	 
	inc	di
	inc	si
	jmp	continue
posible_CH_may:
	cmp	ax, 17		;17 es el valor de CH en nuestro codigo
	JNE	letras2
	;convertimos nuestro codigo a los dos codigos ascii 'C' y 'H'
	mov	ax, 'C'
	mov	[di],  al	
	;pasamos a la siguiente zona de memoria de la frase en ascii
	inc	di
	mov	ax, 'H'
	mov	[di],  al	
	inc	di
	inc	si
	jmp	continue
letras2:
	;miramos si estamos entre la 'd' y la 'n'
	cmp	ax, 39		;39 es el valor de 'n' en nuestro codigo
	JG	posible_ñ
	;miramos si el codigo es impar, lo cual implica mayusculas
	mov	cx, ax
	shr	cx,1
	JC	entre_DyN
	sub	ax, 12 ;12 en vez de 10 devido a que tenemos ch y CH entre medio
	shr	ax,1
	add	ax, 'a'
	mov	[di], al
	inc	di
	inc	si
	jmp	continue
posible_ñ:
	cmp	ax, 40     ;40 es el valor de 'ñ' en nuestro codigo
	JNE	posible_Ñ_may
	mov	ax, 164     ;164 valor de 'ñ'en ascii
	mov	[di], ax 	
	inc	di
	inc	si
	jmp	continue
posible_Ñ_may:
	cmp	ax, 41	   ;41 es el valor de 'Ñ' en nuestro codigo
	JNE	letras3
	mov	ax, 165
	mov	[di], ax	;165 valor de 'Ñ' en ascii
	inc	di
	inc	si
	jmp	continue
entre_DyN:
	;mayscula entre DyN	
	sub	ax, 13	   ;13 devido a que son mayusculas y esta ch entre medio
	shr	ax,1
	add	ax, 'A'
	mov	[di], al
	inc	di
	inc	si
	jmp	continue
letras3:
	;estamos entre O y Z
	mov	cx,ax
	shr	cx,1
	JC	entre_OyZ
	;estamos en minusculas
	sub	ax, 14    ;14 devido a que tenemos a la ch y la ñ
	shr	ax,1
	add	ax, 'a'
	mov	[di], al
	inc	di
	inc	si
	jmp	continue
entre_OyZ:
	cmp	ax, 65	   ;65 es el valor de Z en nuestro codigo
	JG	noferres
	sub	ax, 15    ;devido a que son mayusculas y tenemos a ch y ñ
	shr	ax,1
	add	ax, 'A'
	mov	[di], al
	inc	di
	inc	si
	jmp	continue
noferres:
	;si llegamos aqui es que ourcode o codeascii han fallado
	inc	di
	inc	si
	jmp	continue
CODEASCII ENDP

;*************************************************************
;Quicksort: procedimiento de ordenacion recursiva.           
;	Argumentos:                                           
;		1-:direccion inicial de la cadena a ordenar  
;		2-:direccion final de la cadena a ordenar    
;*************************************************************
QUICKSORT  PROC  NEAR
;Guardamos Bp por si ubiese algo importante	
	PUSH 	BP
	MOV	BP, SP
;Cogemos los argumentos de la funcion	
	MOV	si, [BP+6]	;Principi
	MOV	di, [BP+4]	;Final
;Miramos si el principio a superado al final
;si es asi salimo del procedimiento	
	CMP	si, di
	JL	Ordenacio
;Salimo del procedimiento devolviendo a BP su valor inicial
	POP	BP
	RET

Ordenacio:
;Preparamos los argumentos para el procedimiento partir
	PUSH	si		;Guardamos principio del vector en la pila
	PUSH	di		;Guardamos final del vector en la pila
;Realizamos la particion de nuestro vector en dos, uno con
;los numeros mayores y el otro con los menores.
;vector menor: (principio->ax), (final->cx)
;vector mayor: (principio->dx), (final->bx)	
	CALL 	PARTIR
;Devolvemos a ax y bx sus valores anteriores a la llamada a partir
	pop	di		
	pop	si		
	
;Ordenamos el vector inferior 
	;preparamos la llamada para el vector superior
	push	dx
	push	di
	;preparamos la llamada y ordenamos el vector inferior
	push	si
	push	cx
	call	QUICKSORT
	add	sp,4	;Podemos hacer la llamada a quicksort preparada antes
;Ordenamos la parte superior	
	call	QUICKSORT
	add	sp,4		;la pila apunta al principio
	pop	bp
	ret
QUICKSORT ENDP

;*************************************************************
;Prodedimiento PARTIR: Nos divide un vector en 2 zonas 
;	diferenciadas, la primera los valores menores que el
;	valor del centro del vectro, la segunda los valores
;	mayores que el del centro del vector.
;*************************************************************
;Argumentos:
;	1-Principio del vector a dividir
;	2-Final del vector a dividir
;Devuelve:
;	1-el final de la primera zona en CX
;	2-el principio de la segunda zona en DX
;************************************************************** 
PARTIR	PROC	NEAR
;Preparamos nuestro puntero a pila	
	PUSH 	BP
	MOV 	BP, SP
;Cogemos los argumentos del procedimiento	
	MOV 	si, [BP+6]	;Principio del vector
	MOV 	di, [BP+4]	;Final del vector
;Guardamos en dx el valor del elemento del medio de la tabla
	MOV	bx, si
	add	bx, di
	shr	bx,1 ;bx apunta al elemento del medio de la tabla
	mov	dx, [bx] 
	xor	dh, dh  ;trabajamos con bytes
;
;Empezamos el algoritmo de particion
;

vector_menor:	
	;mientras lo que hay en la direccion si sea menor que el valor medio
	;miro que pasa en la siguiente posicion
	mov	cx, [si]
	xor	ch, ch
	CMP	cx, dx
	JGE	vector_mayor
	INC	si
	JMP	vector_menor
;
vector_mayor:
	;mientras lo que hay en la direccion di sea mayor que el valor medio
	;miro que pasa en la siguiente posicion menor a esta
	mov	cx, [di]
	xor	ch, ch
	CMP	cx, dx
	JLE	intercanvi  ;realizo un intercanvio entre lo que apunta si y di
	DEC	di
	JMP	vector_mayor
;
intercanvi: 
	;si estamos aqui es porque lo que hay en la direccion si es mayor que
	;el valor medio y lo que hay en la di es menor, por tanto los tenemos
	;que intercanviar a no ser que las direcciones se hayan cruzado.
	CMP	si,di ;si la direccion superior i la inferior se han cruzado
	      	      ;salimos del bucle.
	JG 	elfin
	;realizamos el intercanvio
	mov	ax, [si] ;guardamos en ax el valor mayor
	mov	bx, [di] ;guardamos en bx el valor menor
	mov	[si],bl  ;donde teniamos el valor mayor ponemos el menor
	mov	[di],al  ;donde teniamos el valor menor ponemos el mayor 	
	;continuamos el algoritmo
	inc	si
	dec	di
	JMP	vector_menor

elfin:
	;preparamos los valores que devuelve la funcion y a bp 
	;su valor original
	mov	cx,di
	mov	dx,si 
	POP BP
	RET

PARTIR ENDP

;*******************************************************
;procediment COMANDLINE: Ens porta a la nostre zona de 
;	dades la frase entrada per comandes.
;*******************************************************
;Arguments
;	1-direccio de memoria on posar la frase
;Torna
;	1-torna en ax la longitut de la frase
;******************************************************* 
COMANDLINE PROC NEAR
;Preparem bp com a punter de pila
	push bp
	mov bp, sp
;Agafem els arguments de COMANDLINE
	MOV BX, [bp+4]	;la direccio on guardar la linea entrada per comandes
	
	XOR AH,AH		;passem AX a un sol byte
	MOV AL,DS:[80h]	;llegim el nombre de carácters introduits
	;si la longitut de la cadena es menor o igual a cero tornar a main 
	CMP AX, 1    ;uno por si solo ha entrado un espacio antes del return
	JLE  long_0	

	DEC AX		;quitamos el espacio
	MOV SI,82h	;direcció origen DS:SI (cadena de la linea de comandes)
	MOV DI,BX	;direcció destinació ES:DI
	MOV CX,AX		;longitud de la cadena, cops que es repetirà l'operació REP
	

	CLD	;posa a zero el flag DF --> SI i DI s'incrementaran a cada iteració
	REP MOVSB	;copia dades de linia comandes a cadena string

	add BX, AX ;fem que BX apunti al final de la cadena
	xor cx, cx
	mov cx, '$'
	mov ES:[BX],cx		;afegim els termes de final de cadena
	;sortim retornant en ax la longitut y a bp el seu valor original
	pop bp
	ret
long_0:
	;poseam ax a 0 tornem a bp el seu valor original i acabem el procediment
	xor ax,ax
	pop bp
	ret

COMANDLINE ENDP

;**********************************************
;Procediment MOVDATA: Nos mueve datos de una zona
;	de memoria a otra.
;**********************************************
;Argumentos:
;	1-direccion fuente de datos a copiar
;	2-direccion destino de datos a copiar
;	3-numero de caracteres a copiar
;***********************************************
MOVDATA PROC NEAR
;preparamos nuestro puntero a pila
	push bp
	mov bp,sp
;cogemos los argumentos de movdata
	mov si, [bp+8]      ;string fuente
	mov di, [bp+6]	    ;string destino
	mov cx, [bp+4]      ;numero de caracteres a copiar
	xor ch,ch           ;ponemos el byte alto de cx a 0 por si acaso.
	
	;el tomar los argumentos ya hemos preparado e "bucle" rep movsb
	cld	;ponemos a zero el flag DF. SI i DI se incrementaran en cada iteracion
	rep movsb	;copia los datos de ds:si a es:di

	;devolvemos a bp su valor inicial y salimos
	pop bp
	ret 
MOVDATA ENDP

;****************************************************
;procedimiento COMPSTRING: nos mueve compara dos cadenas
; 	y nos devuelve el numero de datos distintos.
;****************************************************
;Argumentos:
;	1-direccion de la primera frase a comparar
;	2-direccion de la segunda frase a comparar
;	3-longitut de la frases a comparar
;Devuele:
;	ax->numero de datos distintos
;*****************************************************
COMPSTRING PROC NEAR
;preparamos nuestro puntero a pila
	push bp
	mov bp, sp
;cogemos los argumentos de compstring
	mov si, [bp+8]	;direccion de la frase sin ordenar en nuestro codigo
	mov di, [bp+6]  ;la direccion de la frase ordenada en nuestro codigo
	mov cx, [bp+4]  ;numero de letras a comparar
	

	xor ax,ax   ;ponemos ax a 0
	;si no hay letras a comparar salimos
	cmp cx, 0
	JE finalizar
	cld      ;ponemos a 0 el flag df
	

bucle:
	cmpsb     ;compara el caracter de la cadena es:di con ds:si
	je retorn
	inc al    ;incrementa en uno el contador de letras distintas
retorn:  loop bucle
;tornem al programa principal tenin en ax el numero de lletres diferents y tornem
;a bp el seu valor original
finalizar:
	pop bp
	ret
COMPSTRING ENDP
CODE ENDS
	END MAIN
