Metropoli BBS
VIEWER: helo.asm MODE: TEXT (ASCII)
; From M.L. Sparks - ZERO BYTE HELLO PROGRAM!
;
;I have a TSR loaded which will monitor calls to interrupt 21, function 04b
;(exec) and when it sees the right command, it prints the string itself and
;ignores the call to execute.
;
;you will need to create the program yourself
;(use REM > HELLO.COM if your assembler doesn't like null input)
;
;Note that you should not name this hello.asm, as it will be looking for that
;name to be executed.  (doesn't check for multiple loads)
;
; A86 style

    org 0100
    jmp begin

oi21 dd ?
buff2 db 80 dup(0)
search1 db 'HELLO'
foundf db 0
message db 'Hello, World!',0d,0a,'$'

ni21:
    cmp ax,4b00h              ; executing a program
    jne notforus

    call scanfor              ; scan for "hello"

    cs cmp [foundf],0
    je notforus

    push ds,dx,ax

    mov dx,cs
    mov ds,dx
    mov dx,offset message
    mov ah,09
    int 021

    pop ax,dx,ds

    iret

notforus:
    jmp dword ptr cs:[oi21]   ; continue with the int request

scanfor:
    push ax
    push di
    push si
    push es
    push ds
    push cs
    push cs
    pop es
    mov si,dx                 ; command line is in ds:dx on int
    mov di,offset buff2       ; buffer to copy to

moveit:
    lodsb                     ; load a byte
    or al,al                  ; cmp al,0
    pushf
    and al,0dfh               ; make it all caps
    stosb                     ; save it
    popf
    jnz moveit                ; loop if more to do

    pop ds
    mov di,offset buff2       ; restore the pointer to 0

look:
    push di                   ; save the pointer to cmd line
    mov si,offset search1     ; pointer to search string
    mov cx,5                  ; H+E+L+L+O=5
    repe cmpsb                ; compare them
    pop di                    ; restore the pointer to 0
    or cx,cx                  ; is this the end?
    jz foundit                ; yes, we found it
    inc di                    ; no, continue the search
    cmp byte ptr [di+5],0     ; is this the end?
    je not_found              ; yes, quit now
    jmp look                  ; loop

not_found:
    cs mov foundf,0
    jmp short endofsearch

foundit:
    cs mov foundf,0ff

endofsearch:
    pop ds                    ; restore the registers and
    pop es
    pop si
    pop di
    pop ax
    ret                       ; return from the call


begin:
    mov ax,03521              ; get old interrupt 21 vector
    int 021
    mov [offset oi21+0],bx    ; save the address
    mov [offset oi21+2],es

    mov ax,02521              ; set new int 21
    mov dx,offset ni21
    int 021

    mov ax,03100              ; terminate and stay resident
    mov dx,offset begin/16+1
    int 021

[ RETURN TO DIRECTORY ]