From c142033bf7821dbe9f140a3e27fb9cb54829f176 Mon Sep 17 00:00:00 2001 From: Blau Araujo Date: Mon, 26 May 2025 08:04:03 -0300 Subject: [PATCH] exemplos da aula 7 --- curso/exemplos/07/cgetenv.asm | 89 ++++++++++++++++++++++ curso/exemplos/07/exit42.asm | 9 +++ curso/exemplos/07/getenv.asm | 136 ++++++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+) create mode 100644 curso/exemplos/07/cgetenv.asm create mode 100644 curso/exemplos/07/exit42.asm create mode 100644 curso/exemplos/07/getenv.asm diff --git a/curso/exemplos/07/cgetenv.asm b/curso/exemplos/07/cgetenv.asm new file mode 100644 index 0000000..f792a68 --- /dev/null +++ b/curso/exemplos/07/cgetenv.asm @@ -0,0 +1,89 @@ +; ---------------------------------------------------------- +; Montagem: nasm -f elf64 cgetenv.asm +; Ligação : gcc -no-pie -o cgetenv cgetenv.o +; Uso : ./cgetenv PATH +; ---------------------------------------------------------- +; Funções importadas da glibc... +; ---------------------------------------------------------- +extern getenv +extern puts +extern fprintf +extern exit +extern stderr +; ---------------------------------------------------------- +section .rodata +; ---------------------------------------------------------- + msg_nf db "Not found", 10, 0 + msg_usage db "Usage: ./getenv VAR", 10, 0 +; ---------------------------------------------------------- +section .bss +; ---------------------------------------------------------- + argc resq 1 ; recebe quantidade de argumentos + argv resq 1 ; recebe endereço de argv[0] + envp resq 1 ; recebe endereço de envp[0] +; ---------------------------------------------------------- +section .text +; ---------------------------------------------------------- +global main +main: +; ---------------------------------------------------------- +; Iniciar quadro de pilha para main... +; ---------------------------------------------------------- + push rbp + mov rbp, rsp +; ---------------------------------------------------------- +; Salvar dados de argumentos e ambiente... +; ---------------------------------------------------------- + mov [argc], rdi ; salvar valor de argc + mov [argv], rsi ; salvar endereço de argv[0] + mov [envp], rdx ; salvar endereço de envp[0] +; ---------------------------------------------------------- +; Verificar se argc < 2 +; ---------------------------------------------------------- + cmp rdi, 2 + jl show_usage +; ---------------------------------------------------------- +; getenv(argv[1]); +; ---------------------------------------------------------- + mov rax, [argv] ; endereço de argv[0] + mov rdi, [rax + 8] ; argumento 1: endereço de argv[1] + call getenv ; chamar getenv + test rax, rax ; testar retorno (0 = não encontrada) + jz not_found +; ---------------------------------------------------------- +; Imprimir valor encontrado: puts(char *valor) +; ---------------------------------------------------------- + mov rdi, rax ; argumento 1: endereço do valor em rax + call puts ; chamar puts +; ---------------------------------------------------------- +; Término com sucesso: exit(int status); +; ---------------------------------------------------------- + mov edi, 0 ; argumento 1: (int)0 - sucesso + call exit ; chamar exit +; ---------------------------------------------------------- +; Se o nome da variável não for encontrado... +; ---------------------------------------------------------- +not_found: +; ---------------------------------------------------------- +; Mensagem de erro: fprintf(stderr, "Not found\n"); +; ---------------------------------------------------------- + mov rdi, [stderr] ; argumento 1: stream de saída + lea rsi, [msg_nf] ; argumento 2: string de formato + call fprintf ; chamar fprintf + jmp exit_error ; termina com erro +; ---------------------------------------------------------- +; Quantidade de argumentos incorrerta... +; ---------------------------------------------------------- +show_usage: +; ---------------------------------------------------------- +; Mensagem de erro: fprintf(stderr, "Usage: ./getenv VAR\n"); +; ---------------------------------------------------------- + mov rdi, [stderr] ; argumento 1: stream de saída + lea rsi, [msg_usage] ; argumento 2: string de formato + call fprintf ; chamar fprintf +; ---------------------------------------------------------- +; Término com erro +; ---------------------------------------------------------- +exit_error: + mov edi, 1 ; argumento 1: (int)1 - erro + call exit ; chamar exit diff --git a/curso/exemplos/07/exit42.asm b/curso/exemplos/07/exit42.asm new file mode 100644 index 0000000..f7a7152 --- /dev/null +++ b/curso/exemplos/07/exit42.asm @@ -0,0 +1,9 @@ +; Retorna 42 como estado de término + +section .text + global _start + +_start: + mov rax, 60 ; syscall: exit + mov rdi, 42 ; código de saída + syscall diff --git a/curso/exemplos/07/getenv.asm b/curso/exemplos/07/getenv.asm new file mode 100644 index 0000000..2278969 --- /dev/null +++ b/curso/exemplos/07/getenv.asm @@ -0,0 +1,136 @@ +; ---------------------------------------------------------- +; 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