home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 12 / duncan.dec < prev    next >
Text File  |  1986-12-31  |  18KB  |  646 lines

  1. Listing One
  2. ;
  3. ; General string comparison routine for 8086
  4. ; by Ray Duncan, June 1986
  5. ;
  6. ; Call with:    DS:SI = address of string1
  7. ;               DX    = length of string1
  8. ;               ES:DI = address of string2
  9. ;               BX    = length of string2
  10. ;
  11. ; Returns:      Z and S flags set appropriately:
  12. ;               Z     = True  if strings are equal
  13. ;               or
  14. ;               Z     = False if strings are not equal, and
  15. ;               S     = True  if string1 < string2
  16. ;               S     = False if string1 > string2
  17. ;
  18. strcmp  proc    near
  19.         mov     cx,bx                   ; set length to compare
  20.         cmp     dx,bx                   ; use shorter of two lengths
  21.         ja      scmp1
  22.         mov     cx,dx
  23. scmp1:  repz cmpsb                      ; now compare strings
  24.         jz      scmp2                   ; jump, strings equal so far
  25.         ret                             ; return, strings not equal, Z=False
  26. scmp2:  sub     dx,bx                   ; compare original string lengths
  27.         ret                             ; return with S and Z flags set 
  28. strcmp  endp
  29.  
  30.  
  31.  
  32. Listing Two
  33. ;
  34. ; General string comparison routine for 68000
  35. ; by Rick Wilton, June 1986
  36. ;
  37. ; Call with:    A0    = address of string1
  38. ;               D0    = length of string1
  39. ;               A1    = address of string2
  40. ;               D1    = length of string2
  41. ;
  42. ; Returns:      D3    = flag (-1,0,1)
  43. ;                       -1 if string1 < string2
  44. ;                        0 if string1 = string2 
  45. ;                        1 if string1 > string2
  46. ;
  47. strcmp                                  ; set d2 = shorter length 
  48.         move.b  d1,d2                   ; d2 := length2
  49.         cmp.b   d0,d1
  50.         blt.s   strcmp1                 ; branch if length2 < length1
  51.         move.b  d0,d2                   ; d2 := length1
  52.  
  53. strcmp1 subq.w  #1,d2
  54.         bmi.s   strcmp3                 ; branch if string length=0
  55.  
  56. strcmp2 cmpm.b  (a0)+,(a1)+             ; compare strings
  57.         dbne    d2,strcmp2
  58.         bne.s   strcmp4                 ; branch if strings unequal
  59.  
  60. strcmp3 cmp.b   d0,d1
  61.         bne.s   strcmp4                 ; branch if lengths unequal
  62.         moveq   #0,d3                   ; string1 = string2, return 0 
  63.         rts
  64.  
  65. strcmp4 bmi.s   strcmp5                 ; branch if d1 < d0
  66.         moveq   #-1,d3                  ; string1 < string2, return -1
  67.         rts
  68.  
  69. strcmp5 moveq   #1,d3                   ; string1 > string2, return 1
  70.         rts
  71.  
  72.  
  73.  
  74. Listing Three
  75. Title EXEC program using undocumented MS-DOS Interrupt 2EH
  76.  
  77. ;
  78. ; This little demonstration program illustrates the undocumented
  79. ; MS-DOS Int 2EH route to the command interpreter in COMMAND.COM.
  80. ; In this example we just pass the command tail of the line that
  81. ; loaded the EXEC2E program.
  82. ;
  83. ; by David Gwillim - 20 June 1986
  84. ; Appears to work on all current versions of MS-DOS (2.x-3.1)
  85. ; Adapted from Turbo Pascal program written by Russ Nelson, Potsdam, NY.
  86. ;
  87.  
  88. cseg    segment
  89.  
  90.         org  100H
  91.  
  92.         assume cs:cseg,ds:nothing       ; force assembler to provide
  93.                                         ; CS overrides in the right places
  94.  
  95. begin:  jmp     start
  96.  
  97.         db      20 dup ('STACK ')     
  98. stack   equ     $
  99.  
  100. stkseg  dw      0                       ; save SS register
  101. stkptr  dw      0                       ; save SP register
  102.  
  103. msg1    db      'Beginning DOS Int 2Eh Exec',13,10,'$'
  104.  
  105. msg2    db      'Terminating DOS Int 2Eh Exec',13,10,'$'
  106.  
  107. start:  push    cs                      ;make our local data addressable
  108.         pop     ds
  109.  
  110.         mov     dx,offset msg1          ;display sign-on message
  111.         mov     ah,9
  112.         int     21h
  113.  
  114.         mov     sp,offset stack         ;reset SP to our own internal stack
  115.  
  116.         mov     bx,offset cs:endcode    ;Get the offset of the end of our code
  117.         shr     bx,1                    ;divide by 16 to get paragraphs
  118.         shr     bx,1
  119.         shr     bx,1
  120.         shr     bx,1
  121.         inc     bx                      ;round paragraphs up
  122.         mov     ah,4ah                  ;shrink down this COM program's
  123.         int     21h                     ;memory allocation to what's needed
  124.  
  125.         mov     stkseg,ss               ;save our current SS reg
  126.         mov     stkptr,sp               ; and SP reg values
  127.  
  128.         mov     si,80h                  ;let DS:SI point to the command
  129.                                         ;to be executed 
  130.  
  131.         int     2eh                     ;undocumented DOS exec interrupt
  132.                                         ; any error code is now in AX             
  133.  
  134.         mov     ss,stkseg               ;Restore SS and SP registers
  135.         mov     sp,stkptr
  136.  
  137.         push    cs                      ;restore local addressing
  138.         pop     ds
  139.  
  140.         mov     dx,offset msg2          ;say we're done
  141.         mov     ah,9
  142.         int     21h
  143.  
  144.         mov     ax,4c00h                ;exit to DOS
  145.         int     21h
  146.  
  147. endcode equ     $
  148.  
  149. cseg    ends
  150.  
  151.         end   begin
  152.  
  153.  
  154.  
  155. Listing Four
  156.  
  157. /*
  158.         The following little program can set an environment variable
  159.         whose name is the first command line argument, and whose new
  160.         value is the second command line argument.  For example, to
  161.         set environment variable XYZ to a value of HELLO, you would
  162.         run this program using the command SETVAR XYZ HELLO.
  163.  
  164.         The *PURPOSE* of this piece of code is to illustrate an un-
  165.         documented DOS interrupt entry point (2Eh) that will execute
  166.         *ANY* DOS command *WITHOUT* having to load another copy of
  167.         COMMAND.COM.  Not only is it faster, but it is the ONLY way
  168.         to set an environment variable (short of peeking and poking
  169.         around into memory).  You *CAN'T* set an environment variable
  170.         with the command exec("COMMAND.COM", "/CSETXYZ=HELLO") because
  171.         when the second copy of COMMAND.COM is loaded, it gets its
  172.         very own environment (a duplicate of the parent's).  Although
  173.         the SET command WILL modify that duplicate copy, it won't
  174.         modify the parent's!
  175.  
  176.         When I said that interrupt 2Eh can be used to execute *ANY*
  177.         DOS command, I meant just that!  You can leave off the filename
  178.         extension (as you normally do at the command line), and it will
  179.         perform the normal search for COM, EXE, and BAT files to execute,
  180.         or even execute built-in commands as we've seen above.
  181.  
  182.         Enjoy!
  183.  
  184.         Dan Lewis, owner
  185.         Key Software Products
  186.         440 Ninth Avenue
  187.         Menlo Park, CA 94025
  188.         (415) 364-9847
  189.  
  190.         P.S.- This *IS* an undocumented "feature" of DOS 2.xx.  I have 
  191.         NO idea if 3.xx etc support it!
  192.  
  193. */
  194.  
  195. #include <stdio.h>
  196.  
  197. main(argc, argv)
  198. int argc ;
  199. char *argv[] ;
  200.         {
  201.         Set_Var(argv[1], argv[2]) ;
  202.         }
  203.  
  204.  
  205.  
  206. Set_Var(variable, value)
  207. char *variable, *value ;
  208.         {
  209.         char setbfr[100] ;
  210.  
  211.  
  212.         /* Build the command line: "SET <var>=<value>" */
  213.  
  214.         strcpy(setbfr, "SET ") ;
  215.         strcat(setbfr, variable) ;
  216.         strcat(setbfr, "=") ;
  217.         strcat(setbfr, value) ;
  218.  
  219.         /* Now use INT 2Eh to execute it! */
  220.  
  221.         Execute_String(setbfr) ;
  222.         }
  223.  
  224.  
  225.        /* -------------------------------------------- */
  226.        /* The really interesting stuff starts here.... */
  227.        /* -------------------------------------------- */
  228.  
  229.  
  230. Execute_String(s)
  231. char *s;
  232.         {
  233.         long vec22, vec23, vec24 ;
  234.         long Get_Vec(vector) ;
  235.         static char bfr[81];
  236.  
  237.  
  238.         /* Concatenate a carriage return onto end of command line */
  239.  
  240.         strcpy(bfr + 1,s) ;
  241.         *bfr = strlen(bfr + 1) ;
  242.         strcat(bfr + 1,"\r") ;
  243.  
  244.         /* preserve cntrl-break, terminate, and critical error vectors */
  245.         vec22 = Get_Vec(0x22) ;
  246.         vec23 = Get_Vec(0x23) ;
  247.         vec24 = Get_Vec(0x24) ;
  248.  
  249.         Release_Memory() ;      /* necessary! */
  250.         Exec(bfr) ;             /* execute command */
  251.  
  252.         /* reset cntrl-break, terminate, and critical error vectors */
  253.         Set_Vec(0x22,vec22) ;
  254.         Set_Vec(0x23,vec23) ;
  255.         Set_Vec(0x24,vec24) ;
  256.         }
  257.  
  258.  
  259. Exec(s)
  260. char *s ;
  261.         {
  262. #asm
  263.         ; preserve ds, bp, ss, & sp
  264.  
  265.         push    ds
  266.         push    bp
  267.         mov     cs:WORD save_ss,ss
  268.         mov     cs:WORD save_sp,sp
  269.  
  270.         ; ds:si ->CR/NULL-terminated command line string
  271.  
  272.         mov     si,[bp+4]
  273.         int     2Eh
  274.  
  275.         ; restore preserved registers
  276.  
  277.         mov     ss,cs:WORD save_ss
  278.         mov     sp,cs:WORD save_sp
  279.         pop     bp
  280.         pop     ds
  281.  
  282.         jmp     Rtn
  283.  
  284. save_ss:dw      0
  285. save_sp:dw      0
  286. save_ds:dw      0
  287. save_bp:dw      0
  288.  
  289. Rtn:
  290. #end
  291.         }
  292.  
  293.  
  294. Release_Memory()
  295.         {
  296.         if (Release())
  297.                 {
  298.                 puts("Release Memory Failure\n") ;
  299.                 exit(1) ;
  300.                 }
  301.         }
  302.  
  303.  
  304. Release()
  305.         {
  306. #asm
  307.         mov     ax,cs
  308.         sub     ax,0010h
  309.         mov     es,ax
  310.         mov     bx,ds
  311.         add     bx,1000h
  312.         sub     bx,ax
  313.         mov     ah,4Ah
  314.         int     21h
  315.         mov     ax,0
  316.         jnc     R_Rtn
  317.         inc     ax
  318. R_Rtn:
  319. #end
  320.         }
  321.  
  322.  
  323. long Get_Vec(vector)    /* Uses DOS function 35h to fetch an interrupt vctr */
  324. unsigned vector ;
  325.         {
  326. #asm
  327.         mov     ah,35h
  328.         mov     al,BYTE [bp+4]
  329.         int     21h
  330.         mov     ax,bx
  331.         mov     dx,es
  332. #end
  333.         }
  334.  
  335.  
  336. Set_Vec(vector,addr)    /* Uses DOS function 25h to set an interrupt vctr */
  337. unsigned vector ;
  338. long addr ;
  339.         {
  340. #asm
  341.         mov     ah,25h
  342.         mov     al,BYTE [bp+4]
  343.         mov     bx,WORD [bp+6]
  344.         mov     es,WORD [bp+8]
  345.         int     21h
  346. #end
  347.         }
  348.  
  349.  
  350.  
  351.  
  352. Listing Five
  353. /*
  354.  *  SYSDEF.H   
  355.  *      Standard system definitions  
  356.  *      Ross P. Nelson
  357.  */
  358.  
  359. /* Expanded public/external syntax */
  360. #define FORWARD extern
  361. #define IMPORT  extern
  362. #define PUBLIC
  363.  
  364. #ifdef DEBUG  /* Generate symbols if debugging, else don't export */
  365. #define LOCAL
  366. #else
  367. #define LOCAL  static
  368. #endif
  369.  
  370. /* System constants and data types */
  371. #define TRUE  1
  372. #define FALSE  0
  373.  
  374. typedef unsigned char  byte;
  375. typedef byte    boolean;
  376. typedef unsigned short  word;
  377. typedef unsigned short  selector;
  378.  
  379.  
  380.  
  381. /*
  382.  *  STD.C    Copyright (C) 1985 Ross P. Nelson
  383.  *
  384.  *      Redirect stdin/stdout.  Usually called before performing an
  385.  *      EXEC, so that the child task will read or write via a file.
  386.  *      Sample usage is in the MAIN routine below.
  387.  */
  388.  
  389. #include <stdio.h>
  390. #include <dos.h>
  391. #include <ios1.h>
  392. #include <sysdef.h>
  393.  
  394. IMPORT  word  _PSP[2];  /* offset, segment */
  395. IMPORT  struct UFB _ufbs[];
  396.  
  397. /*
  398.  *  SETSTDIO
  399.  *      Set stdin or stdout to the file.  Caller is responisble for
  400.  *      having opened the file in the corrent mode and positioning it
  401.  *      as necessary.  Returns a value to be used when reseting stdio
  402.  *      to original value.
  403.  */
  404. PUBLIC int setstdio (stdfp, newfp)
  405. FILE *stdfp, *newfp;
  406. {
  407. byte reset, save;
  408. int handle, redir;
  409.  
  410.   handle = _ufbs[fileno (newfp)].ufbfh;
  411.   redir = _ufbs[fileno (stdfp)].ufbfh;
  412.   save = 0xFF;
  413.   peek (_PSP[1], 0x18 + handle, &reset, 1);
  414.   poke (_PSP[1], 0x18 + handle, &save, 1);
  415.   peek (_PSP[1], 0x18 + redir, &save, 1);
  416.   poke (_PSP[1], 0x18 + redir, &reset, 1);
  417.   return (int) save;
  418. }
  419.  
  420. /*
  421.  *  RESTDIO
  422.  *      Must be called to reset stdio values to original.  Caller is
  423.  *      responsible for closing file after restdio.
  424.  */
  425. PUBLIC void restdio (stdfp, newfp, reset)
  426. FILE *stdfp, *newfp;
  427. int reset;
  428. {
  429. byte direct, old;
  430. int handle, redir;
  431.  
  432.   handle = _ufbs[fileno (newfp)].ufbfh;
  433.   redir = _ufbs[fileno (stdfp)].ufbfh;
  434.   old = (byte) reset;
  435.   peek (_PSP[1], 0x18 + redir, &direct, 1);
  436.   poke (_PSP[1], 0x18 + redir, &old, 1);
  437.   poke (_PSP[1], 0x18 + handle, &direct, 1);
  438. }
  439.  
  440. #if (PROTOTYPE)
  441. abort (s)
  442. char *s;
  443. {
  444.   fprintf (stderr, s);
  445.   exit (4);
  446. }
  447.  
  448. main ()
  449. {
  450. FILE *f;
  451. int reset;
  452.  
  453.   puts ("Begin test - opening file TEST.XX");
  454.   f = fopen ("test.xx", "w");
  455.   if (f == NULL)
  456.     abort ("open failed");
  457.   reset = setstdio (stdout, f);    /* stdout <- f */
  458.   fprintf (stderr, "invoking LS\n");      /* can't write to stdout */
  459.   if (forklp ("ls.exe", "ls", NULL)) {    /* run LS */
  460.     restdio (stdout, f, reset);  /* clean up if cant exec */
  461.     abort ("exec failed");
  462.     }
  463.   (void) wait ();       /* wait til LS done */
  464.   restdio (stdout, f, reset);    /* stdout <- original value */
  465.   fclose (f);
  466.   puts ("Test completed - LS results in TEST.XX");
  467. }
  468. #endif
  469.  
  470.  
  471. Listing 6 December  86 16-Bit Column in DDJ
  472. -----------------------------------------------
  473.  
  474. ;****************************************************************
  475. ;*                                                              *
  476. ;* Wildcard filename expansion for MS-DOS 2.00 and later.       *
  477. ;*                                                              *
  478. ;* By: Randy Langer, MicroSphere Technology                     *
  479. ;*                                                              *
  480. ;****************************************************************
  481.  
  482. ifndef  model                   ; if default model (both small)
  483.  
  484. model   equ     0               ; 0 = small code, small data
  485.                                 ; 1 = large code, small data
  486.                                 ; 2 = small code, large data
  487. endif                           ; 3 = large code, large data
  488.  
  489. codeseg segment byte public 'code'
  490.         assume  cs:codeseg
  491.  
  492.         public  wildcard_
  493.  
  494. if      model and 1
  495.  
  496. wildcard_       proc    far
  497.  
  498. else
  499.  
  500. wildcard_       proc    near
  501.  
  502. endif
  503.  
  504.         push    bp              ; save frame pointer
  505.         mov     bp,sp           ; point to our stack
  506.  
  507. if      model and 2
  508.  
  509.         push    ds              ; save DS if large data
  510.         mov     ds,[bp+6]       ; and get segment of struct ptr
  511.  
  512. endif
  513.  
  514.         mov     bx,[bp+4]       ; get offset of struct ptr
  515.         mov     al,[bx]         ; get flag byte
  516.         or      al,al           ; see if high bit set
  517.         js      rtn_null        ; if so, no more to find
  518.         push    es              ; save reg used by DOS call
  519.         mov     ah,47           ; get current DTA addr
  520.         int     21h             ; do it
  521.         mov     ax,es           ; save DTA segment
  522.         pop     es              ; restore ES
  523.         push    ds              ; save for later restoration
  524.         push    ax              ; save addr of old DTA
  525.         push    bx
  526.         mov     dx,[bp+4]       ; get ptr to user's struct
  527.         add     dx,2            ; point past flag bytes
  528.         mov     ah,26           ; set "new" DTA addr
  529.         int     21h
  530.         mov     bx,[bp+4]       ; get entry pointer again
  531.         mov     cl,[bx+1]       ; set search attributes
  532.         mov     ah,79           ; set token for search next
  533.         test    byte ptr [bx],1 ; if this is really search next
  534.         jnz     not_1st         ;  branch
  535.         inc     byte ptr [bx]   ; else, set flag
  536.         dec     ah              ; and set token for search first
  537. not_1st:
  538.         mov     dx,[bx+45]      ; get offset to filespec
  539.  
  540. if      model and 2
  541.  
  542.         mov     ds,[bx+47]
  543.  
  544. endif
  545.  
  546.         int     21h             ; do the search
  547.         pop     dx              ; get addr of old DTA
  548.         pop     ds
  549.         push    ax              ; save return code from search
  550.         mov     ah,26           ; restore DTA ptr
  551.         int     21h
  552.         pop     ax              ; restore return code
  553.         pop     ds              ; get back segment of user struct
  554.         mov     bx,[bp+4]       ; and its offest
  555.         or      ax,ax           ; see if search successful
  556.         jz      rtn_name        ; branch if so
  557.         mov     byte ptr [bx],128 ; else, say no more
  558. rtn_null:
  559.         xor     ax,ax           ; return null ptr
  560.         mov     dx,ax           ; in case of large data
  561. wild_end:
  562.         
  563. if      model and 2
  564.  
  565.         pop     ds
  566.  
  567. endif
  568.  
  569.         pop     bp              ; restore frame pointer
  570.         ret                     ; and return
  571. rtn_name:
  572.         mov     dx,ds           ; in case of large data model
  573.         mov     ax,32           ; offset to file name
  574.         add     ax,bx           ; add to struct base
  575.         jmp     wild_end        ; and exit
  576.  
  577. wildcard_       endp
  578. codeseg ends
  579.  
  580.         end
  581.  
  582.  
  583.  
  584.  
  585. Listing 7 December 86 16-Bit Column in DDJ:
  586. -----------------------------------------------
  587.  
  588. /* 
  589.  
  590.      WILDCARD.H  for use with  WILDCARD.ASM
  591.      by Randy Langer, Microsphere Technology
  592.  
  593. */
  594.  
  595. typedef struct
  596.         {
  597.                 char    flag;
  598.                 char    att_sel;
  599.                 char    tempdata[21];           /* don't mess with this */
  600.                 char    f_atts;
  601.                 long    datetime;
  602.                 long    filesize;
  603.                 char    filename[13];
  604.                 char    *filespec;
  605.  
  606.         } W_CARD;
  607.  
  608. char    *wildcard();
  609.  
  610.  
  611.  
  612. Listing 8 December 1986 16-Bit Column in DDJ
  613. ------------------------------------------------
  614.  
  615. /* 
  616.  *  WILDTEST.C  Program to demonstrate use of WILDCARD.ASM
  617.  *  by Randy Langer, MicroSphere Technology.
  618.  *
  619.  */
  620.  
  621. #include        "stdio.h"
  622. #include        "wildcard.h"
  623.  
  624. main(argc, argv)
  625.  
  626. int             argc;
  627. STR             argv[];
  628. {
  629.  
  630. W_CARD  y;
  631. STR     s;
  632.  
  633.         while(--argc)
  634.         {
  635.                 y.filespec = *++argv;
  636.                 y.att_sel = 0x10;
  637.                 y.flag = 0;
  638.                 while(s = wildcard(&y))
  639.                         printf("%s\n", s);
  640.         }
  641. }
  642.  
  643.  
  644.                                 [EOF]
  645.  
  646.