VERIFY para DOS

Desde 2017 con UPTIME 2 para DOS que no había vuelto a estos frikismos de retro-programación. En el ejemplo de hoy, una tontería bastante grande, pero bastante interesante.

FreeDOS distribuye con su software base VERIFY.COM, una herramienta que reproduce el comando interno VERIFY de DOS, y que aunque muchos no conoceréis, sigue implementado incluso en las consolas de comandos de Windows 11.

VERIFY para DOS

El caso es que ese VERIFY.COM creado por Peter Mikalajunas en 1995 estaba escrito en C, algo que no tiene mucho sentido debido a la simplicidad de su función, esencialmente invocar a los servicios de DOS. No es de extrañar, que incluyendo dependencias variadas (librerías y runtimes), el ejecutable resultante fuera 5.444 bytes.

Como entretenimiento decidí reimplementarlo en ensamblador, como es mi costumbre últimamente usando el macro-ensamblador UASM. Mientras que el original eran unas 70 líneas de código sin contar comentarios, no es de extrañar que mi implementación en ensamblador requiriera algunas más, unas 110. Sin embargo, el tamaño del ejecutable .COM resultante pasó a solamente 653 bytes, es decir, casi 10 veces menos.

A destacar que el original no era 100% compatible con el comando interno de DOS, que espera como argumentos ON u OFF, mientras que el código de esa versión entendía solamente /ON y /OFF. El mío es fiel al VERIFY de siempre, aceptando ON u OFF, sino también 0 o 1.

Por lo demás, no tiene mucho misterio a comentar, así que sin más te dejo aquí el enlace para descargar el código fuente y compilado (2 KB. en formato ZIP) (también disponible en Sourceforge), y como referencia, pego el código original de VERIFY.C, así como mi implementación de VERIFY.ASM.

/* VERIFY     Copyright (c) 1995 Peter Mikalajunas
 *
 * VERIFY:  command that tells DOS to verify if files are written
 *          correctly to disk.
 * 
 * Author:  Peter Mikalajunas
 *          kd9fb@xnet.com
 * 
 * Date:    01/30/95
 * 
 * Version: 1.0
 * 
 * NOTE:    This implementation relies on the intdos() function in dos.h.
 *           As such, it is not strictly ANSI C. intdos() is available
 *           in Borland and Microsoft C.
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include     /* for intdos() */
#include   /* for puts */
#include  /* for strcmp */

/*
 * 0 = Verify off
 * 1 = Verify on
 */
int get_verify_state (void)
{
   union REGS regs;

   regs.h.ah = 0x54;
   intdos (®s, ®s);
   return regs.h.al;
}

void set_verify_state (int flag)
{
   union REGS regs;

   regs.h.ah = 0x2e;
   regs.h.al = flag;
   regs.h.dl = 0;
   intdos (®s, ®s);
}

int main (int argc, char *argv[])
{
    int vflag;

   if (argc < 2)		/* no command line arguments */
   {
      if (get_verify_state () == 0)
       {
        puts ("VERIFICATION IS CURRENTLY OFF");
       }
      else if (get_verify_state () == 1)
       {
        puts ("VERIFICATION IS CURRENTLY ON");
       }
   }
   if (argc > 1)		/* handle on/off command line arguments */
   {
    if (strcmp (argv[1], "/on") == 0 || strcmp (argv[1], "/ON") == 0)
       {
        vflag=1;
        set_verify_state (vflag);
        puts ("VERIFICATION IS NOW SET ON");
       }
    if (strcmp (argv[1], "/off") == 0 || strcmp (argv[1], "/OFF") == 0)
       {
        vflag=0;
        set_verify_state (vflag);
        puts ("VERIFICATION IS NOW SET OFF");
       }
    if (strcmp (argv[1], "/?") == 0)
      {
       puts ("USAGE: VERIFY sets file copy verification ON or OFF.");
       puts(" ");
       puts ("       VERIFY used alone returns the current setting.");
       puts ("       VERIFY /on to turn verification on.");
       puts ("       VERIFY /off to turn verification off.");
      }
   }
   return 0;
}
;--------------------------------------------------------------------------------------------------------------------------------------------------------------
.model tiny
.stack 64
.code
org 100h


;--------------------------------------------------------------------------------------------------------------------------------------------------------------
.startup

;Parse command-line options
mov al, byte ptr ds:[80h]
;We have arguments
.if al > 0
	mov ax, word ptr ds:[82h]
	;One digit 0/1
	.if al == '1'
		mov al, 1
		call Doit
	.elseif al == '0'
		xor al, al
		call Doit
	.else
		;Two digits on/off
		.switch ax
			.case 'no', 'NO', 'No', 'nO'
				mov al, 1
				call Doit
			.endc
			.case 'fo', 'FO', 'Fo', 'fO'
				xor al, al
				call Doit
			.endc
			.default
				call ShowHelp
			.endc
		.endsw
	.endif
.else
	call ShowStatus
.endif
.exit



;--------------------------------------------------------------------------------------------------------------------------------------------------------------
;Enable/Disable in AL
DoIt proc
   mov ah, 2eh
   xor dl, dl
   int 21h
   
   call ShowStatus
   ret
DoIt endp


;--------------------------------------------------------------------------------------------------------------------------------------------------------------
;Show status
ShowStatus proc
	mov dx, offset acStatus
	call PrintText
	
	mov ah, 54h
	xor dl, dl
	int 21h
	.if (al == 0)
   		mov dx, offset acOff
	.else
		mov dx, offset acOn
   .endif
   call PrintText
   ret
ShowStatus endp


;--------------------------------------------------------------------------------------------------------------------------------------------------------------
ShowHelp proc
	mov dx, offset acCopyright
	call PrintText
	
	mov dx, offset acCrLf
	call PrintText
	
	;Return
	mov al, -1
	ret
ShowHelp endp


	
;--------------------------------------------------------------------------------------------------------------------------------------------------------------
;Text in DX
PrintText proc uses ax
	mov ah, 9
	int 21h
	ret
PrintText endp

;--------------------------------------------------------------------------------------------------------------------------------------------------------------
.data
acCopyright		db 13, 10
				db "VERIFY R1.00                       (c) 2022 by Javier Gutierrez Chamorro (Guti)", 13, 10
				db "Controls whether to verify files are written correctly to a disk.", 13, 10, 10
acHelp			db "Syntax is: VERIFY [-h|on|1|off|0]", 13, 10, 10
				db "Examples:", 13, 10, 10
				db "	VERIFY -h", 13, 10
				db "	Shows this help screen.", 13, 10
				db "	VERIFY ON", 13, 10
				db "	Enable verification flag", 13, 10
				db "	VERIFY", 13, 10
				db "	Display verification flag", 13, 10, 10
				db "Type VERIFY without a parameter to display the current VERIFY setting.", 13, 10, 10
				db "More information at:", 13, 10
				db "	http://nikkhokkho.sourceforge.net/static.php?page=VERIFY", 13, 10
acCrLf			db 13, 10, '

acStatus		db 'VERIFY is 

acOn			db "ON$"
acOff			db "OFF$"
end

4 comentarios en “VERIFY para DOS”

  1. Muy interesante, deberían incorporarlo por defecto en FreeDOS en lugar de la versión en C, la verdad es que entre una y otra no hay color, buen trabajo Guti.

    En mi caso utilizo mucho Verify para la copia de archivos, porque me funciona mejor que la copia «en alto nivel» mediante la GUI de Windows y no te da tanto error. Lo que hecho en falta es una animación de estado, pero claro, viniendo de tiempos en los que la multitarea era una rareza, no me extraña que no se la pusieran.

  2. Me ha gustado el artículo, como curiosidad, el VERIFY lo uso cuando trasteo con el emulador del C64 vice, para ver si se ha escrito correctamente el programita basic en el «diskette», (VERIFY «program»,8).

    Interesante el código ensamblador y que manera de tenerlo «fresco». Un buen reto intelectual, retro; valga el juego de palabras. Tiene mérito.

  3. Javier Gutiérrez Chamorro (Guti)

    Gracias Torsan. Son de esas cosas que tienen una utilidad muy reducida, casi como hacer un crucigrama o un sudoku, pero lo disfruté.

Deja un comentario