Working with environment variables aren't that much harder than working with command line arguments. Here is a short program that displays the environment variables in an HTML table. I tried to comment the relevant parts and use macros to obscure the parts that don't really matter to what you are trying to figure out.
BITS 32
STDOUT_FILENO EQU 1
SYS_EXIT EQU 1
SYS_WRITE EQU 4
%define @ARG Ebp + 8
%define @VAR Ebp - 8
%macro CCall 1-*
%push _CCall_
%define %%proc %1
%assign %$ii 0
%rep %0-1
%rotate -1
Push DWORD %1
%assign %$ii %$ii + 1
%endrep
Call %%proc
Add Esp, (4 * %$ii)
%pop
%endm
%macro StdCall 1-*
%push _StdCall_
%define %%proc %1
%rep %0-1
%rotate -1
Push DWORD %1
%endrep
Call %%proc
%pop
%endm
SECTION .data
strHeader DB "Content-type: text-html",10,10
DB "<HTML><HEAD><TITLE>ENVIRONMENT</TITLE></HEAD><BODY>",10
DB "<H1>Environment Variables</H1>",10
DB "<TABLE width='100%' cellspacing='0' cellpadding='0' border='1'>",10
strHeader_size EQU ($-strHeader)
strFooter DB "</TABLE></BODY></HTML>",10
strFooter_size EQU ($-strFooter)
strRowOpen DB "<TR><TD>"
strRowOpen_size EQU ($-strRowOpen)
strRowMid DB "</TD><TD>"
strRowMid_size EQU ($-strRowMid)
strRowClose DB "</TD></TR>", 10
strRowClose_size EQU ($-strRowClose)
SECTION .text
StringLength:
STRUC SLA
.string RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
Push Ecx
Push Edi
Xor Ecx, Ecx
Not Ecx
Xor Eax, Eax
Mov Edi, [@ARG + SLA.string]
Repne Scasb
Not Ecx
Dec Ecx
Mov Eax, Ecx
Pop Edi
Pop Ecx
Leave
Ret SLA_size
MakeKeyVal:
STRUC MKVA
.addr RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
Cld
Mov Edi, [@ARG + MKVA.addr]
Mov Al, '='
Repne Scasb
Dec Edi
Mov BYTE [Edi], 0
Mov Eax, [@ARG + MKVA.addr]
Mov Edx, Edi
Inc Edx
Leave
Ret MKVA_size
PrintRow:
STRUC PRA
.key RESD 1
.value RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
;; --[ Row Open ]--
Mov Edx, strRowOpen_size
Mov Ecx, strRowOpen
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
;; --[ ROW_ARGS.key ]--
StdCall StringLength, [@ARG + PRA.key]
Mov Edx, Eax
Mov Ecx, [@ARG + PRA.key]
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
;; --[ Row Mid ]--
Mov Edx, strRowMid_size
Mov Ecx, strRowMid
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
;; --[ ROW_ARGS.value ]--
StdCall StringLength, [@ARG + PRA.value]
Mov Edx, Eax
Mov Ecx, [@ARG + PRA.value]
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
;; --[ Row Close ]--
Mov Edx, strRowClose_size
Mov Ecx, strRowClose
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
Leave
Ret PRA_size
Main:
STRUC MA
.argc RESD 1
.argv RESD 1
.envp RESD 1
ENDSTRUC
Push Ebp
Mov Ebp, Esp
;; --[ Print CGI Header ]--
Mov Edx, strHeader_size
Mov Ecx, strHeader
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
;; --[ Count Environment Vars ]--
Mov Esi, [@ARG + MA.envp]
Xor Ecx, Ecx
Xor Eax, Eax
.scan_env:
Mov Ebx, [Esi + Ecx]
Or Ebx, Ebx
Jz .done
Add Ecx, 4
Inc Eax
Jmp .scan_env
.done:
;; --[ Print Each Variable ]--
Mov Ecx, Eax
.for_each:
Push Ecx
Push Esi
StdCall MakeKeyVal, [Esi]
StdCall PrintRow, Eax, Edx
Pop Esi
Pop Ecx
Add Esi, 4
Loop .for_each
.end_for:
;; --[ Print CGI Footer ]--
Mov Edx, strFooter_size
Mov Ecx, strFooter
Mov Ebx, STDOUT_FILENO
Mov Eax, SYS_WRITE
Int 80h
Xor Eax, Eax
Leave
Ret MA_size
GLOBAL _start
_start:
Pop Ecx
Mov Esi, Esp
Push Ecx
Lea Eax, [(Esi + 4) + (Ecx * 4)]
;; --[ Explanation ]--
; We pop the argument count off the stack into Ecx
; and save the argument list in Esi (via Esp). Next,
; we restore the argument count to the stack and
; load Eax with the environment list.
; The environment variables are located just after
; the last command line argument, we can find this
; by multiplying 4 by our argument count and adding
; that to the sum of 4 and the address of the base of
; our argument list (we add for to the argument list
; to compensate for a null separator). This results
; in the following layout:
;
; Ecx - int argc
; Esi - char * argv[]
; Eax - char * envp[]
;; --
StdCall Main, Ecx, Esi, Eax
Mov Ebx, Eax
Mov Eax, SYS_EXIT
Int 80h
Hope this helps.
Regards,
Bryant Keller