NASM - The Netwide Assembler

NASM Forum => Example Code => Topic started by: TightCoderEx on December 24, 2012, 08:59:27 AM

Title: Scan applications environment variables
Post by: TightCoderEx on December 24, 2012, 08:59:27 AM
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.

Code: [Select]
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

Code: [Select]
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.