Category : Assembly Language Source Code
Archive   : ASM2.ZIP
Filename : NO.ASM

 
Output of file : NO.ASM contained in archive : ASM2.ZIP
; NO.ASM -- Hides specified files from command that follows
; ======

CSEG Segment
Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
Org 002Ch
Environment Label Word ; Segment of Environment is here
Org 0080h
Parameter Label Byte ; Parameter is here
Org 0100h
Entry: Jmp Begin ; Entry Point

; Most Data (some more at end of program)
; ---------------------------------------

db "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
db " Programmed by Charles Petzold ",1Ah
SyntaxMsg db "Syntax: NO filespec command [parameters]$"
DosVersMsg db "NO: Needs DOS 2.0 +$"
FileSpecMsg db "NO: Incorrect File Spec$"
TooManyMsg db "NO: Too many files to hide$"
MemAllocMsg db "NO: Allocation Problem$"
CommandMsg db "NO: COMMAND Problem$"
Delimiters db 9,' ,;='
FileList dw ? ; Storage of found files
FileCount dw 0 ; Count of found files
FileListEnd dw ? ; End of storage of found files
BreakState db ? ; Store original break state here
Comspec db 'COMSPEC=' ; String for Environment search
ParamBlock dw ? ; Parameter block for EXEC call
dw ?, ?
dw 5Ch, ?
dw 6Ch, ?
StackPointer dw ? ; Save SP during EXEC call

; Check DOS Version
; -----------------

Begin: Mov AH, 30h ; Check for DOS Version
Int 21h ; through DOS call
Cmp AL, 2 ; See if it's 2.0 or above
Jae DosVersOK ; If so, continue

Mov DX, Offset DosVersMsg ; Error message
ErrorExit: Mov AH, 9 ; Print String function call
Int 21h ; Do it
Int 20h ; And exit prematurely

; Parse Command Line to get NO File specification
; -----------------------------------------------

ScanParam: Lodsb ; SUBROUTINE: Get byte
Cmp AL, 13 ; See if end of parameter
Je ErrorExit ; If so, exit
Mov DI, Offset Delimiters ; Check if delimiter
Mov CX, 5 ; There are 5 of them
Repne Scasb ; Scan the string
Ret ; And return

DosVersOK: Mov DX, Offset SyntaxMsg ; Possible error msg
Mov SI, 1+Offset Parameter ; NO Parameter string
Cld ; Directions forward

BegSearch: Call ScanParam ; Check byte in subroutine
Je BegSearch ; If delimiter, keep searching
Mov BX, SI ; Save pointer in BX
Dec BX ; BX points to NO file spec

EndSearch: Call ScanParam ; Check byte in subroutine
Jne EndSearch ; If not delimiter, keep going

; Construct full FilePath and save down at end of program
; -------------------------------------------------------

Dec SI ; Points after NO file spec
Xchg SI, BX ; SI points to beg, BX to end
Mov DI, Offset FullPath ; Points to destination
Cmp Byte Ptr [SI + 1], ':' ; See if drive spec included
Jnz GetDrive ; If not, must get the drive
Lodsw ; Otherwise, grab drive spec
And AL, 0DFh ; Capitalize drive letter
Jmp Short SaveDrive ; And skip next section

GetDrive: Mov AH, 19h ; Get current drive
Int 21h ; through DOS
Add AL, 'A' ; Convert to letter
Mov AH, ':' ; Colon after drive letter

SaveDrive: Stosw ; Save drive spec and colon
Mov AL, '\' ; Directory divider byte
Cmp [SI], AL ; See if spec starts at root
Jz HaveFullPath ; If so, no need to get path
Stosb ; Store that character
Push SI ; Save pointer to parameter
Mov SI, DI ; Destination of current path
Mov DL, [SI - 3] ; Drive letter specification
Sub DL, '@' ; Convert to number
Mov AH, 47h ; Get current directory
Int 21h ; through DOS
Mov DX, Offset FileSpecMsg ; Possible error message
Jc ErrorExit ; Exit if error
Sub AL, AL ; Search for terminating zero
Cmp [SI], AL ; Check if Root Directory
Jz RootDir ; If so, don't use it
Mov CX, 64 ; Number of bytes to search
Repnz Scasb ; Do the search
Dec DI ; DI points to last zero
Mov AL, '\' ; Put a backslash in there
Stosb ; So filespec can follow
RootDir: Pop SI ; Get back SI

HaveFullPath: Mov CX, BX ; End of NO file spec
Sub CX, SI ; Number of bytes to transfer
Rep Movsb ; Transfer them
Sub AL, AL ; Terminating zero
Stosb ; Save it
Mov [FileList], DI ; Repository for found files

; Fix up parameter and ParamBlock for eventual COMMAND load
; ---------------------------------------------------------

Sub BX, 4 ; Points to new param begin
Mov AL, [Parameter] ; Old byte count of parameter
Add AL, 80h ; Add beginning of old param
Sub AL, BL ; Subtract beginning of new
Mov AH, ' ' ; Space separator
Mov Word Ptr [BX], AX ; Store it
Mov Word Ptr [BX + 2], 'C/' ; Add /C to beginning of rest
Mov AX, [Environment] ; Get environment segment
Mov [ParamBlock], AX ; Save it
Mov [ParamBlock + 2], BX ; Save parameter pointer
Mov [ParamBlock + 4], CS ; Save segment of ParamBlock
Mov [ParamBlock + 8], CS
Mov [ParamBlock + 10], CS

; Find Files from NO File Specification
; -------------------------------------

Mov DX, Offset DTABuffer ; Set File Find buffer
Mov AH, 1Ah ; by calling DOS
Int 21h

Mov DI, [FileList] ; Address of destination
Mov DX, Offset FullPath ; Search string
Sub CX, CX ; Search Normal files only
Mov AH, 4Eh ; Find first file

FindFile: Int 21h ; Call DOS to find file
Jnc Continue ; If no error continue
Cmp AX, 18 ; If no more files
Jz NoMoreFiles ; get out of the loop
Mov DX, Offset FileSpecMsg ; Error message otherwise
Jmp ErrorExit ; Exit and print message

Continue: Mov AX, DI ; Address of destination
Add AX, 512 ; See if near top of segment
Jc TooManyFiles ; If so, too many files
Cmp AX, SP ; See if getting too many
Jb StillOK ; If not, continue

TooManyFiles: Mov DX, Offset TooManyMsg ; Otherwise error message
Jmp ErrorExit ; And terminate

StillOK: Mov SI, 30+Offset DTABuffer ; Points to filename
Call AsciizTransfer ; Transfer it to list
Inc [FileCount] ; Kick up counter
Mov AH, 4Fh ; Find next file
Jmp FindFile ; By looping around

NoMoreFiles: Mov [FileListEnd], DI ; Points after last file
Mov DI, [FileList] ; Points to end of find string
Mov CX, 64 ; Search up to 64 bytes
Mov AL, '\' ; For the backslash
Std ; Search backwards
Repnz Scasb ; Do the search
Mov Byte Ptr [DI + 2], 0 ; Stick zero in there
Cld ; Fix up direction flag

; Stop Ctrl-Break Exits and Hide the files
; ----------------------------------------

Mov AX,3300h ; Get Break State
Int 21h ; By calling DOS
Mov [BreakState],DL ; Save it
Sub DL,DL ; Set it to OFF
Mov AX,3301h ; Set Break State
Int 21h ; By calling DOS
Mov BL, 0FFh ; Value to AND attribute
Mov BH, 02h ; Value to OR attribute
Call ChangeFileMode ; Hide all the files

; Un-allocate rest of memory
; --------------------------

Mov BX, [FileListEnd] ; Beyond this we don't need
Add BX, 512 ; Allow 512 bytes for stack
Mov SP, BX ; Set new stack pointer
Add BX, 15 ; Prepare for truncation
Mov CL,4 ; Prepare for shift
Shr BX,CL ; Convert to segment form
Mov AH,4Ah ; Shrink allocated memory
Int 21h ; By calling DOS
Mov DX,Offset MemAllocMsg ; Possible Error Message
Jc ErrorExit2 ; Print it and terminate

; Search for Comspec in Environment
; ---------------------------------

Push ES ; We'll be changing this
Mov ES, [Environment] ; Set ES to Environment
Sub DI, DI ; Start at the beginning
Mov SI, Offset ComSpec ; String to search for
Mov DX, Offset CommandMsg ; Possible error message

TryThis: Cmp Byte Ptr ES:[DI], 0 ; See if points to zero
Jz ErrorExit2 ; If so, we can't go on
Push SI ; Temporarily save these
Push DI
Mov CX, 8 ; Search string has 8 chars
Repz Cmpsb ; Do the string compare
Pop DI ; Get back the registers
Pop SI
Jz LoadCommand ; If equals, we've found it
Sub AL, AL ; Otherwise search for zero
Mov CX, -1 ; For 'infinite' bytes
Repnz Scasb ; Do the search
Jmp TryThis ; And try the next string

; Load COMMAND.COM
; -----------------

LoadCommand: Add DI, 8 ; so points after 'COMSPEC='
Push DS ; Switch DS and ES registers
Push ES
Pop DS
Pop ES
Mov [StackPointer],SP ; Save Stack Pointer
Mov DX, DI ; DS:DX = Asciiz of COMMAND
Mov BX, Offset ParamBlock ; ES:BX = parameter block
Mov AX, 4B00h ; EXEC function call
Int 21h ; Load command processor

; Return from COMMAND.COM
; -----------------------

Mov AX, CS ; Current code segment
Mov DS, AX ; Reset DS to this segment
Mov ES, AX ; Reset ES to this segment
Mov SS, AX ; Reset stack segment to it
Mov SP, [StackPointer] ; Reset SP
Pushf ; Save error flag
Sub DL,DL ; Set Ctrl Break to OFF
Mov AX,3301h
Int 21h ; By calling DOS
Popf ; Get back error flag
Mov DX,Offset CommandMsg ; Set up possible error msg
Jnc Terminate ; And print if EXEC error

; Unhide the Files, restore Ctrl-Break state, and exit
; ----------------------------------------------------

ErrorExit2: Mov AH,9 ; Will print the string
Int 21h ; Print it
Terminate: Mov BL, 0FDh ; AND value for change
Mov BH, 00h ; OR value for change
Call ChangeFileMode ; Change file attributes
Mov DL,[BreakState] ; Original break-state
Mov AX,3301h ; Change the break-state
Int 21h ; by calling DOS
Int 20h ; Terminate

; SUBROUTINE: Change File Mode (All files, BL = AND, BH = OR)
; -----------------------------------------------------------

ChangeFileMode: Mov CX, [FileCount] ; Number of files
Jcxz EndOfChange ; If no files, do nothing
Mov SI, [FileList] ; Beginning of list
Mov DX, [FileListEnd] ; End of List
ChangeLoop: Push SI ; Save pointer
Mov SI, Offset FullPath ; Preceeding path string
Mov DI, DX ; Destination of full name
Call AsciizTransfer ; Transfer it
Dec DI ; Back up to end zero
Pop SI ; Get back pointer to filename
Call AsciizTransfer ; Transfer it
Push CX ; Save the counter
Mov AX, 4300h ; Get attribute
Int 21h ; by calling DOS
And CL, BL ; AND with BL
Or CL, BH ; OR with BH
Mov AX, 4301h ; Now set attribute
Int 21h ; by calling DOS
Pop CX ; Get back counter
Loop ChangeLoop ; And do it again if necessary
EndOfChange: Ret ; End of subroutine

; SUBROUTINE: Asciiz String Transfer (SI, DI in, returned incremented)
; --------------------------------------------------------------------

AsciizTransfer: Movsb ; Transfer Byte
Cmp Byte Ptr [DI - 1], 0 ; See if it was end
Jnz AsciizTransfer ; If not, loop
Ret ; Or leave subroutine

; Variable length data stored at end
; ----------------------------------

DTABuffer Label Byte ; For file find calls
FullPath equ DTABuffer + 43 ; For file path and names
CSEG EndS ; End of the segment
End Entry ; Denotes entry point


  3 Responses to “Category : Assembly Language Source Code
Archive   : ASM2.ZIP
Filename : NO.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/