; ---------------------------------------------------------- ; Montagem: nasm -f elf64 -o getenv.o getenv_v2.asm ; Ligação : ld -o getenv getenv.o ; Uso : ./getenv NOME_VARIAVEL ; ---------------------------------------------------------- section .rodata ; ---------------------------------------------------------- newline db 10, 0 ; caractere de nova linha msg_nf db "Not found", 10, 0 ; mensagem de erro msg_usage db "Usage: ./getenv VAR", 10, 0 ; mensagem de uso incorreto ; ---------------------------------------------------------- section .bss ; ---------------------------------------------------------- argc resq 1 ; quantidade de argumentos (argc) argv resq 1 ; endereço do vetor de argumentos (argv) envp resq 1 ; endereço do vetor de ambiente (envp) ; ---------------------------------------------------------- section .text ; ---------------------------------------------------------- global _start _start: ; ---------------------------------------------------------- ; Carregar e salvar argc, argv e envp ; ---------------------------------------------------------- mov rax, [rsp] ; argc está no topo da pilha mov [argc], rax ; salva argc em argc lea rax, [rsp + 8] ; argv começa logo após argc mov [argv], rax ; salva ponteiro de argv mov rbx, [argc] lea rax, [rsp + rbx*8 + 16] ; envp vem após argc + argv[] + ponteiro nulo mov [envp], rax ; salva ponteiro de envp ; ---------------------------------------------------------- ; Verificar se argc == 2 ; ---------------------------------------------------------- cmp qword [argc], 2 jl show_usage ; se argc < 2, mostrar uso correto ; ---------------------------------------------------------- ; Obter endereço do nome da variável: argv[1] ; ---------------------------------------------------------- mov rax, [argv] mov rsi, [rax + 8] ; rsi = argv[1] ; ------------------------------------------ ; Iterar sobre envp para buscar a variável ; ------------------------------------------ mov rcx, [envp] ; rcx recebe endereço de envp[0] .next_env: mov rdx, [rcx] ; rdx recebe endereço da string "VAR=valor" test rdx, rdx ; verifica se rdx = 0 jz not_found ; se rdx = 0, termina com erro (não encontrada) ; ------------------------------------------ ; Comparar caractere a caractere: se argv[1] é prefixo de rdx ; e é seguido por '=' → variável encontrada ; ------------------------------------------ mov r8, rsi ; r8 = nome buscado (argv[1]) mov r9, rdx ; r9 = string atual do envp .cmp_loop: mov al, [r8] ; próximo char do nome buscado mov bl, [r9] ; próximo char da string do envp cmp al, 0 je .check_equals ; se al = 0, chegou ao fim do nome buscado: checar '=' cmp al, bl jne .next ; se al != bl, não bateu, próxima variável inc r8 inc r9 jmp .cmp_loop ; ------------------------------------------ ; Comparar se o caractere no endereço é '=' ; ------------------------------------------ .check_equals: cmp byte [r9], '=' ; verifica se o caractere em envp é '=' jne .next ; não era uma '=': próximo elemento em envp inc r9 ; avança para o início do valor mov rsi, r9 ; rsi = endereço do primeiro byte do valor mov rdi, 1 ; stdout call print_string ; imprime valor mov rsi, newline ; carrega endereço de '\n' em rsi call print_string ; imprime \n mov rdi, 0 ; estado de término 0 (sucesso) call exit_program ; termina o programa .next: add rcx, 8 ; avança para próximo emdereço em envp jmp .next_env ; ---------------------------------------------------------- ; Caso variável não seja encontrada ; ---------------------------------------------------------- not_found: lea rsi, [rel msg_nf] mov rdi, 2 ; stderr call print_string mov rdi, 1 ; código de erro call exit_program ; ---------------------------------------------------------- ; Caso uso incorreto (menos de 2 argumentos) ; ---------------------------------------------------------- show_usage: lea rsi, [rel msg_usage] ; endereço da mensagem de uso mov rdi, 2 ; fd 2 = stderr call print_string ; imprime a mensagem mov rdi, 1 ; estado de término 1 (erro) call exit_program ; termina o programa ; ---------------------------------------------------------- ; SUB-ROTINAS ; ---------------------------------------------------------- print_string: ; ---------------------------------------------------------- ; Imprime string terminada em '\0' no descritor indicado ; Entrada: ; rdi = file descriptor (1 = stdout, 2 = stderr) ; rsi = ponteiro para string terminada em '\0' ; ---------------------------------------------------------- push rdi ; salva rdi (fd) mov rax, rsi xor rcx, rcx ; contador = 0 .count: cmp byte [rax + rcx], 0 ; fim da string? je .write inc rcx jmp .count .write: mov rdx, rcx ; número de bytes a escrever pop rax ; restaura fd original mov rdi, rax mov rax, 1 ; syscall: write syscall ret ; ---------------------------------------------------------- exit_program: ; ---------------------------------------------------------- ; Encerra o programa com código em rdi ; Entrada: ; rdi = código de saída (0 = sucesso, 1 = erro) ; ---------------------------------------------------------- mov rax, 60 ; syscall: exit syscall