Copia de ficheros

Programa en ensamblador que copia un fichero sobre otro.
				;****************************************************************
; //////******Comentarios a [email protected]******* *
;*Sencillo programa para iniciarse en el lenguaje ensamblador *
;*Este programa copia un fichero sobre otro existente, o crea *
;*el fichero de salida. *
;*En Ambos casos desaparece el contenido original del fichero de*
;*Salida , si lo hubiese.
;*Puede ocurrir, que en algunas partes de los registros analizados*
;*con el Debug, no sean coincidentes, con secuencias anteriores. *
;*Esto puede ser debido, a que el ejemplo se ha explicado en *
;*sucesivas ejecuciones del programa. * *
;*****************************************************************

.MODEL SMALL
.STACK
.DATA
;Bloque de datos para la entrada informativa de cabecera

Informativo db 0AH,0DH, '*****//Programa:"COPIA",creado por Berlanga***** '
db 0AH,0DH, '************ (mail) [email protected] *****************************'
db 0AH,0DH,'****COPIA UN FICHERO SOBRE OTRO ,O CREA UN NUEVO FICHERO DE SALIDA****** '
db 0AH,0DH,'*EN DONDE SE ESCRIBE EL CONTENIDO DEL DE ENTRADA, SOBREESCRIBIENDO DATOS*'
db 0AH,0DH,'*ENSAMBLADO CON: Microsoft (R) Macro Assembler Version 6.15.8803. '
db 0AH,0DH, '***********************/-Editado con VASM-*****************************. '
db 0AH,0DH, ' $' ;Esta es una de las muchas formas de dejar espacios en blanco.

;Longitud máxima del nombre de un fichero
Longitud_Nombre_Fichero=40
;
;Tamaño de los bloques de transferencia
Maxima_Longitud_Abrir=4096

;Mensajes que saldran por pantalla para facilitar el desarrollo
;del programa

EscriboMensaje1 db 0AH,0DH,'INTRODUZCA EL FICHERO DE ENTRADA: $'

EscriboMensaje2 db 0AH,0DH,'INTRODUZCA EL NOMBRE DEL FICHERO DE SALIDA: $'

EscriboMensaje3 db 'ERROR:El fichero de destino ya existe'
db 0dh,0ah,'$'

EscriboMensaje4 db 'ERROR: No se puede abrir el fichero de Entrada.'
db 0dh,0ah,'$'

EscriboMensaje5 db 'ERROR: No se puede abrir el fichero de Salida.'
db 0dh,0ah,'$'
EscriboMensaje6 db 'ERROR: de Lectura.', 0dh,0ah,'$'

EscriboMensaje7 db 'ERROR: de Escritura.', 0dh,0ah,'$'

EscriboMensaje8 db '!!!LA COPIA FINALIZO CON EXITO!!!.', 0dh,0ah,'$'

Avanza db 0dh,0ah,'$'

BufferDeEntradaTeclado db Longitud_Nombre_Fichero+1
DB ?
DB Longitud_Nombre_Fichero DUP (?)
;Espacio para las cadenas ASCII con los nombres

FicheroDeEntrada db Longitud_Nombre_Fichero +1 DUP(?)

FicheroDeSalida db Longitud_Nombre_Fichero +1 DUP(?)

;Variables para los Handles de fichero

HandleDeEntrada DW ?

HandleDeSalida DW ?

;Buffer para la copia de Datos

BufferCopiaDeDatos Db Maxima_Longitud_Abrir DUP (?)
;*********************************************************
;En esta parte optenida con debug (DOS) vemos como aparecen los
;datos una vez cargados en parte de la memoria. DESDE 16D6:0020 --> 16D6:0170
;16D6:0020 22 2C 63 72 65 61 64 6F-20 70 6F 72 20 42 65 72 ",creado por Ber
;16D6:0030 6C 61 6E 67 61 5C 5C 2A-2A 2A 2A 2A 20 0A 0D 2A langa***** ..*
;16D6:0040 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 20 28 6D 61 69 *********** (mai
;16D6:0050 6C 29 20 62 65 72 6C 61-6E 67 61 32 32 40 68 6F l) berlanga22@ho
;16D6:0060 74 6D 61 69 6C 2E 63 6F-6D 20 2A 2A 2A 2A 2A 2A tmail.com ******
;16D6:0070 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A ****************
;-d
;16D6:0080 2A 2A 2A 2A 2A 2A 2A 0A-0D 2A 2A 2A 2A 43 4F 50 *******..****COP
;16D6:0090 49 41 20 55 4E 20 46 49-43 48 45 52 4F 20 53 4F IA UN FICHERO SO
;16D6:00A0 42 52 45 20 4F 54 52 4F-20 2C 4F 20 43 52 45 41 BRE OTRO ,O CREA
;16D6:00B0 20 55 4E 20 4E 55 45 56-4F 20 46 49 43 48 45 52 UN NUEVO FICHER
;16D6:00C0 4F 20 44 45 20 53 41 4C-49 44 41 2A 2A 2A 2A 2A O DE SALIDA*****
;16D6:00D0 2A 20 0A 0D 2A 45 4E 20-44 4F 4E 44 45 20 53 45 * ..*EN DONDE SE
;16D6:00E0 20 45 53 43 52 49 42 45-20 45 4C 20 43 4F 4E 54 ESCRIBE EL CONT
;16D6:00F0 45 4E 49 44 4F 20 44 45-4C 20 44 45 20 45 4E 54 ENIDO DEL DE ENT
;-d
;16D6:0100 52 41 44 41 2C 20 53 4F-42 52 45 45 53 43 52 49 RADA, SOBREESCRI
;16D6:0110 42 49 45 4E 44 4F 20 44-41 54 4F 53 2A 0A 0D 2A BIENDO DATOS*..*
;16D6:0120 45 4E 53 41 4D 42 4C 41-44 4F 20 43 4F 4E 3A 20 ENSAMBLADO CON:
;16D6:0130 4D 69 63 72 6F 73 6F 66-74 20 28 52 29 20 4D 61 Microsoft (R) Ma
;16D6:0140 63 72 6F 20 41 73 73 65-6D 62 6C 65 72 20 56 65 cro Assembler Ve
;16D6:0150 72 73 69 6F 6E 20 36 2E-31 35 2E 38 38 30 33 2E rsion 6.15.8803.
;16D6:0160 20 0A 0D 20 20 24 0A 0D-49 4E 54 52 4F 44 55 5A .. $..INTRODUZ
;16D6:0170 43 41 20 45 4C 20 46 49-43 48 45 52 4F 20 44 45 CA EL FICHERO DE
; Aquí vemos las últimas instrucciones y cómo se muestra el contenido en
;pantalla.
;AX=16D6 BX=0000 CX=140A DX=0000 SP=03FE BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16B7 SS=1808 CS=16C7 IP=0006 NV UP EI PL NZ NA PO NC
;16C7:0006 B409 MOV AH,09
;-t

;AX=09D6 BX=0000 CX=140A DX=0000 SP=03FE BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16B7 SS=1808 CS=16C7 IP=0008 NV UP EI PL NZ NA PO NC
;16C7:0008 BA0800 MOV DX,0008
;-t

;AX=09D6 BX=0000 CX=140A DX=0008 SP=03FE BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16B7 SS=1808 CS=16C7 IP=000B NV UP EI PL NZ NA PO NC
;16C7:000B CD21 INT 21
;-p

;*****//Programa:"COPIA",creado por Berlanga*****
;************ (mail) [email protected] *****************************
;****COPIA UN FICHERO SOBRE OTRO ,O CREA UN NUEVO FICHERO DE SALIDA******
;*EN DONDE SE ESCRIBE EL CONTENIDO DEL DE ENTRADA, SOBREESCRIBIENDO DATOS*
;*ENSAMBLADO CON: Microsoft (R) Macro Assembler Version 6.15.8803.






;***********************************************************
.CODE

;CONFIGUARCION DE LAS MACROS

;Generamos esta macro para los mensajes de presentación,
;pasándole un valor a través de: "EscriboMensaje"

EscriboMensajeEntrada MACRO EscriboMensaje
MOV AH,9
MOV DX,OFFSET EscriboMensaje
int 21h
ENDM
;Programamos una Macro para copiar cadenas de entrada a ASCIIZ
CopiarZ MACRO destino

;Una pequeña explicación para entender esta Macro.
;Copia el nombre del fichero del buffer de entrada del Teclado,
;y lo pone en el destino que demos al llamar a la macro.
cld ;Pone a 0 el indicador de dirección DF, por lo que los registros
;SI y/o DI se autoincrementan en las operaciones de cadenas,
; sin afectar al resto de los indicadores. Es NECESARIO colocarlo
;antes de las instrucciones de manejo de cadenas si no se conoce
;con seguridad el valor de DF.
mov cl,[BufferDeEntradaTeclado+1];<--16C7:0026 8A0E9B02 MOV CL,[029B]


xor ch,ch ;Hacemos 0 a ch
mov si,offset BufferDeEntradaTeclado+2 ;<<16C7:002C BE9C02 MOV SI,029C

mov di,offset destino ;<<16C7:002F BFC402 MOV DI,02C4

rep movsb ;Transfiere un byte o una palabra de la cadena origen
;direccionada por DS:SI a la cadena destino direccionada
; por ES:DI, incrementando o decrementando a continuación
;los registros SI y DI según el valor de DF (véanse CLD y STD)
;en una o dos unidades, dependiendo de si se trabaja con bytes
;o con palabras. Cadena origen y cadena destino son dos
;operandos redundantes que sólo indican el tipo del dato
;(byte o palabra) a comparar, es más cómodo colocar MOVSB o MOVSW
;para indicar bytes/palabras. Si se indica un registro de segmento,
;éste sustituirá en la cadena origen al DS ordinario.
;Una vez finalizada la secuencia repetida del MOVSB, tendremos en
;memoria lo siguiente:
;16D6:02C0 00 00 00 00 48 69 6C 61-72 69 6F 2E 74 78 74 00 ....Hilario.txt.

xor al,al ;Ponemos un cero en al, para el NULL
;Y lo transferimos al final de Hilario.txt con stosb
stosb ;Transfiere el operando origen almacenado en AX o AL,
;al destino direccionado por el registro DI sobre el segmento
;extra. Tras la operación, DI se incrementa o decrementa según
;el indicador DF (véanse CLD y STD) para apuntar al siguiente
;elemento de la cadena. Cadena_destino es un operando redundante
;que sólo indica el tipo del dato (byte o palabra) a cargar,
;es más cómodo colocar STOSB o STOSW para indicar bytes/palabras.

ENDM

;Construiremos una macro específica para sacar los EscriboMensajes
;por la Consola.

Input MACRO EscriboMensaje
mov ah,9
mov dx,offset EscriboMensaje
int 21h
mov ah,0ah ;Lee una cadena de la entrada standard en un buffer
;entrada en ah 0ah, en ds:dx, dirección del buffer
;de entrada .El primer byte del buffer contiene la
;entrada del número máximo de caracteres leídos
;La entrada se realiza a partir de la posición actual
;del cursor.
mov dx,offset BufferDeEntradaTeclado
int 21h
mov ah,9
mov dx,offset Avanza
int 21h
ENDM

;Estableceremos esta MACRO para salir del programa
;señalando un error si lo hubiera.

Salir MACRO EscriboMensaje, errorlevel

mov dx,offset EscriboMensaje
mov ah,9
int 21h
mov ax,4c00h+errorlevel
int 21h
ENDM

Entrada PROC
;*******************************
mov ax,@DATA ;Inicializamos el segmento de Datos
mov ds,ax ;y el segmento extra
push ax

EscriboMensajeEntrada Informativo



;*****************************
Programa:
pop ax
mov es,ax


;Leemos el nombre del fichero de entrada
;************************************************************************
;La secuencia siguiente sería llamar a la Macro Input MACRO EscriboMensaje
;pasándole el valor EscriboMensaje1. Realizando la llamada de la siguiente
;forma Input EscriboMensaje1
;En este código analizado con el Debug del DOS, vemos cual sería la secuencia
; en los registros:
;AX=16D6 BX=0000 CX=140A DX=0008 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0010 NV UP EI PL NZ NA PO NC
;16C7:0010 B409 MOV AH,09
;-t

;AX=09D6 BX=0000 CX=140A DX=0008 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0012 NV UP EI PL NZ NA PO NC
;16C7:0012 BA6601 MOV DX,0166
;-t

;AX=09D6 BX=0000 CX=140A DX=0166 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0015 NV UP EI PL NZ NA PO NC
;16C7:0015 CD21 INT 21
;-p

;INTRODUZCA EL FICHERO DE ENTRADA: <<< Mensaje que retorna a pantalla
;AX=0924 BX=0000 CX=140A DX=0166 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0017 NV UP EI PL NZ NA PO NC
;16C7:0017 B40A MOV AH,0A
;-t

;AX=0A24 BX=0000 CX=140A DX=0166 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0019 NV UP EI PL NZ NA PO NC
;16C7:0019 BA9A02 MOV DX,029A
;-
;AX=09D6 BX=0000 CX=140A DX=0166 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0015 NV UP EI PL NZ NA PO NC
;16C7:0015 CD21 INT 21
;-p

;Hilario.txt <<<<Este sería el fichero de Entrada introducido en el buffer
;AX=0A0D BX=0000 CX=140A DX=029A SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=001E NV UP EI PL NZ NA PO NC
;16C7:001E B409 MOV AH,09
;AX=090D BX=0000 CX=140A DX=029A SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0020 NV UP EI PL NZ NA PO NC
;16C7:0020 BA9702 MOV DX,0297
;-p

;AX=090D BX=0000 CX=140A DX=0297 SP=0400 BP=0000 SI=0000 DI=0000
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0023 NV UP EI PL NZ NA PO NC
;16C7:0023 CD21 INT 21
;-p
;No desarrollaremos con el Debug del DOS, más macros, dado que el proceso
;para el resto sería semejante según la secuencia establecida

Input EscriboMensaje1
;*************************
;Copia el nombre al FicheroDeEntrada convirtiéndolo a ASCII
;pasando los valores a FicheroDeEntrada. Deberéis de comprobar
;el proceso secuancial de esta Macro

CopiarZ FicheroDeEntrada
;Lee el nombre del fichero de salida
Input EscriboMensaje2
;************************************************
CopiarZ FicheroDeSalida
;Si esta MACRO es llamada pasándole el fichero de Salida
;nos quedaría ,al final, algo así con del Debug del DOS:

;AX=0900 BX=0000 CX=0000 DX=018B SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=003C NV UP EI PL ZR NA PE NC
;16C7:003C CD21 INT 21
;-p

;INTRODUZCA EL NOMBRE DEL FICHERO DE SALIDA:
;AX=0924 BX=0000 CX=0000 DX=018B SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=003E NV UP EI PL ZR NA PE NC
;16C7:003E B40A MOV AH,0A

;********************************************
;Comprobamos ahora si el fichero de Salida Ya existe
;e intentamos abrirlo
mov ax,3d00h ;Lo abrimos para lectura
mov dx,Offset FicheroDeSalida
int 21h ;Si no existiera el fichero de salida,
;saltaríamos para indicarlo

jc NoExisteFicheroDeSalida
;Cierra el fichero abierto
mov bx,ax ;Copia handle
mov ah,3eh
int 21h
;Mostramos el EscriboMensaje de error y salimos
Salir EscriboMensaje3,1

;Rutina NoExisteSalida

NoExisteFicheroDeSalida:
;Abrimos el fichero de entrada para Lectura
mov ax,3d00h
mov dx,offset FicheroDeEntrada
int 21h
jnc ExisteFicheroDeEntrada
;Sino fuese así, mostramos el fichero de error y salimos
Salir EscriboMensaje4,2

ExisteFicheroDeEntrada:

;Guardamos el handle del fichero de Entrada
mov [HandleDeEntrada],ax
;Creamos el Fichero de salida
mov ah,3ch
xor cx,cx
mov dx,offset FicheroDeSalida
int 21h
jnc CreadoFicheroDeSalida

;Ahora mostramos el EscriboMensaje y salimos
Salir EscriboMensaje5,3
;**************************************************
;En esta parte vemos una de las opciones en las cuales introducimos
;el nombre del fichero :FICHSAL.TXT, por el teclado, cuando el fichero
;de salida no sea uno existente.
; AX=0A24 BX=0000 CX=0000 DX=029A SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0043 NV UP EI PL ZR NA PE NC
;16C7:0043 CD21 INT 21
;-p
;fichsal.txt
;AX=0A0D BX=0000 CX=0000 DX=029A SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0045 NV UP EI PL ZR NA PE NC
;16C7:0045 B409 MOV AH,09
;-t

;AX=090D BX=0000 CX=0000 DX=029A SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=0047 NV UP EI PL ZR NA PE NC
;16C7:0047 BA9702 MOV DX,0297
;-t

;AX=090D BX=0000 CX=0000 DX=0297 SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=004A NV UP EI PL ZR NA PE NC
;16C7:004A CD21 INT 21
;-p


;AX=0924 BX=0000 CX=0000 DX=0297 SP=0400 BP=0000 SI=02A7 DI=02D0
;DS=16D6 ES=16D6 SS=1808 CS=16C7 IP=004C NV UP EI PL ZR NA PE NC
;16C7:004C FC CLD
;***********************************************************************
;Comprobar con el debug del DOS, como queda el fichero de salida en Memoria
;16D6:02E0 00 00 00 00 00 00 00 00-00 00 00 00 00 66 69 63 .............fic
;16D6:02F0 68 73 61 6C 2E 74 78 74-00 00 00 00 00 00 00 00 hsal.txt........
;en el segmento 16D6 y en el desplazamiento 2ED, sino he contado mal, encontramos
;el primer carácter de fichsal.txt
;***********************************************************************
CreadoFicheroDeSalida:
mov [HandleDeSalida ],ax
;Ahora comenzamos el bucle que copia todo el fichero.

Bucle:
;Primero, lee Maxima_Longitud_Abrir bytes
mov ah,3fh
mov bx,[HandleDeEntrada]
mov cx,Maxima_Longitud_Abrir
MOV dx,offset BufferCopiaDeDatos
int 21h
;******************************************************
;Es muy conveniente, pararse en esta parte, y observar
;como actúa MOVSB, basándose en SI y DI, origen y destino de la memoria,
;para ir cambiando secuencialmente letra a letra del fichero HILARIO.TXT,
;para lograr depositar en el buffer de memoria los datos que serán reintegrados
;al fichero de Salida.

; AX=0924 BX=0000 CX=0003 DX=02E3 SP=0400 BP=0000 SI=02F0 DI=0341
;DS=16D6 ES=16D6 SS=180D CS=16C7 IP=0059 NV UP EI PL ZR NA PE NC
;16C7:0059 F3 REPZ
;16C7:005A A4 MOVSB
;-T

;AX=0924 BX=0000 CX=0002 DX=02E3 SP=0400 BP=0000 SI=02F1 DI=0342
;DS=16D6 ES=16D6 SS=180D CS=16C7 IP=0059 NV UP EI PL ZR NA PE NC
;16C7:0059 F3 REPZ
;16C7:005A A4 MOVSB
;-T

;AX=0924 BX=0000 CX=0001 DX=02E3 SP=0400 BP=0000 SI=02F2 DI=0343
;DS=16D6 ES=16D6 SS=180D CS=16C7 IP=0059 NV UP EI PL ZR NA PE NC
;16C7:0059 F3 REPZ
;16C7:005A A4 MOVSB
;-T

;AX=0924 BX=0000 CX=0000 DX=02E3 SP=0400 BP=0000 SI=02F3 DI=0344
;DS=16D6 ES=16D6 SS=180D CS=16C7 IP=005B NV UP EI PL ZR NA PE NC
;16C7:005B 32C0 XOR AL,AL
;


jnc LecturaBien
;Muestra el EscriboMensaje y sale cerrando los ficheros
Salir EscriboMensaje6,4
LecturaBien:
;Guarda el número de bytes leídos
push ax
;Ahora escribe los bytes leídos
mov cx,cx
mov ah,40h
mov bx,[HandleDeSalida]
mov dx,offset BufferCopiaDeDatos
int 21h
jnc EscrituraBien
;Muestra EscriboMensaje y sale
Salir EscriboMensaje7,5
EscrituraBien:
pop ax
cmp ax,Maxima_Longitud_Abrir
jz Bucle
Salir EscriboMensaje8,0

Entrada ENDP
END Entrada
Descargar adjuntos
COMPARTE ESTE TUTORIAL

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
TUTORIAL ANTERIOR

SIGUIENTE TUTORIAL