Listing 4 ; Procedure DoEnviron ; Purpose Convert a string to an environment variable ; Input String in "string" ; Output String in "WHAT" environment variable; ; AX has 0 for success, nonzero for failure DoEnviron PROC call GetEnv ; Get environment size, length, address mov dx,ax ; Save size and length mov bx,cx ; Find "WHAT=" sub di,di ;Point to start sub al,al ;Search for zero mov si, OFFSET what ; Point source at "WHAT=" 11 findwh: repne scasb ; Search cmp BYTE PTR es:[di],) ; If double null, end of environment je gotend jcxz noroom ; Error if not found push di ; Save push cx mov si,OFFSET what ;Load address and length of "what" mov cx, lwhat ; for comparison repe cmpsb ; Compare mov si,di ; Make copy pop cx ; Restore pop di jnz findwh ; Find end of "WHAT" variable xchg di,si repne scasb ; Find end of environment variable xchg si,di ; Point source to next variable ; Calculate characters left to write mov cx,bx ; Load total characters sub cx,si ; Subtract finished to get left ; Move everything back to overwrite "WHAT=" movenv: push ds : Save DS mov ax,es ; Copy to ES mov ds,ax rep movsb ; Copy mov BYTE PTR es:[di],0 ; Put null at end in case of error pop ds ; Restore ; Check environment space gotend: mov al,actual ; Load length of string sub ah,ah ; Clear top add ax,lwhat ; Add length of name add ax,di ; Add position to get final length cmp ax,dx ; Is it longer than environment? jge noroom ; Yes? Quit : Put WHAT= at end mov si,OFFSET what ; Load address and length of what mov cx,lwhat rep movsb ; Put new string at end mov si,OFFSET string ; Load address and length of string mov cl,actual rep movsb mov WORD PTR es:[di],0 ; Put double null at end 12 sub ax,ax ; Return 0 for success ret noroom: inc ax ; Return nonzero for fail ret DoEnviron ENDP ; Procedure GetEnv ; Purpose Find and measure the environment ; Input None ; Output Segment of environment in ES, size in AX, length in CX GetEnv PROC mov dx,es:10h ; Load segment of COMMAND.COM mov es,dx ; into ES mov ax,es:2Ch ; Load COMMAND.Com's environment or ax,ax ; Is it 0? jnz secondry ; No? This is a secondary command ; and we have its environment in AX dec dx ; Yes? This is original COMMAND.COM mov es,dx ; so point ES to paragraph before PSP add dx,es:03 ; Offset of environment is 3 bytes in add dx,2 ; Adjust it back to PSP mov ax,dx ; Put it in AX secondry: ; Note: ; CodeView cannot debug the previous section of code, because the PSP ; addresses checked by the code are those passed from DOS to CodeView, ; not addresses passed from DOS to the program. To debug with CodeView, ; find the actual address of the environment: ; S 500:0 L FFFF "COMSPEC=" ; When you find the actual address, hard code it into your program: ; mov ax,110Ch ; Debug line ; Comment the line out for final assembly after debugging. mov si,ax ; Save a copy sub dx,dx ; Clear DX for multiply dec ax ; Get paragraph before environment mov es,ax ; Load into DS mov ax,es:03 ; Size in paragraphs is at byte 4 mov cx, 16 ; Multiply by 16 mul cx mov es,si ; Restore environment address sub di,di ; Point to start mov cx,ax ; Load maximum count (size of mov bx,ax : environment) and save a copy sub ax,ax : Search for double null null2: repne scasb ; Look for null jz noerr ; If not out of space, continue sub ax,ax ; else error (return 0) 13 jmp error2 noerr: cmp BYTE PTR es: [di],0 ; Is it double null? jne null2 ; No? Look again mov cx,di ; Yes? Save length in CX mov ax,bx ; Reload size to AX ret GetEnv ENDP