exemplos da aula 7
This commit is contained in:
parent
05ef406060
commit
c142033bf7
3 changed files with 234 additions and 0 deletions
89
curso/exemplos/07/cgetenv.asm
Normal file
89
curso/exemplos/07/cgetenv.asm
Normal file
|
@ -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
|
9
curso/exemplos/07/exit42.asm
Normal file
9
curso/exemplos/07/exit42.asm
Normal file
|
@ -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
|
136
curso/exemplos/07/getenv.asm
Normal file
136
curso/exemplos/07/getenv.asm
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue