Primarily I designed this because I need consoles metrics (width and height), but can be used for anything in applications list.
Testbed. There is no variable called LOGNME, it is what I used to test end of list condition.
extern GetEnv
global _start
section .const
Match db 'LINES', 0, 'LOGNME', 0, 'COLUMNS', 0, 'DISPLAY', 0, 0
section .text
_start push rbp
mov rbp, rsp
mov eax, [rsp + 8] ; Get number of args passed to app.
add eax, 3
lea rsi, [rsp + rax * 8] ; Get address of pointer to array of pointers.
mov edi, Match
.L0 call GetEnv
jz $ + 3
push rax
cmp byte [rdi], 0 ; Test is list is empty
jnz .L0
.Done leave
xor edi, edi
mov rax, rdi
mov al, 60
syscall
Procedure
global GetEnv
section .text
; ============================================================================================
; Scan applications environment variables for match and return a pointer its value.
; ENTRY: RSI = Pointer to array of pointers to environment strings.
; RDI = Pointer to NULL terminated match string.
; LEAVE: RSI = Unchanged
; RDI = Pointer to next string to find.
; RAX = Pointer to variables value or NULL if not found.
; FLAGS: ZF = 1 Match was found
; ZF = 0 No match
; NOTE: Comparison string is case sensitive and must be exact up to '=' sign in env string.
; --------------------------------------------------------------------------------------------
GetEnv push rsi ; Save pointer to array of pointers
; Scan ahead to next matching string
or ecx, -1
push rdi
mov al, 0
repnz scasb
xchg [rsp], rdi
; Scan each environment entry until exhausted denoted by NULL pointer.
.Next lodsq ; Get address of environment text
push rax
dec rax
pop rax
js .Done
; Setup source register for inner loop
push rsi ; Save ordinal position in array of pointers.
mov rsi, rax ; Base of environment string.
push rdi ; Save base pointer for next iteration.
; Scan entry up to equal sign and tread as entries terminator.
.L0 lodsb ; Get byte from environment string
cmp al, '='
jnz $ + 4
mov al, 0 ; If equal sign, treat as terminus.
mov ah, [rdi]
inc rdi ; Point to next position in match string
or ax, 0
jnz .L1
; Strings match, waste values on stack as they are not required anymore.
mov rax, rsi ; Pointer to entries value
add rsp, 16
jmp .Done ; Exit process
.L1 cmp ah, al
jz .L0 ; Carry on if bytes still match
; Re-establish pointers and check next entry in table.
pop rdi
pop rsi
jmp .Next
; Restore pointers incase procedure is called again.
.Done pop rdi
pop rsi ; Restore pointer to array of pointers
or rax, rax ; Set or reset ZF flag.
ret