diff --git a/curso/exemplos/08/salve-pipe.asm b/curso/exemplos/08/salve-pipe.asm new file mode 100644 index 0000000..758a012 --- /dev/null +++ b/curso/exemplos/08/salve-pipe.asm @@ -0,0 +1,141 @@ +; ---------------------------------------------------------- +; Arquivo : salve-pipe.asm +; Reproduz: echo 'Salve, simpatia!' | cat +; Montagem: nasm -f elf64 salve-pipe.asm +; Ligação : ld -o salve-pipe salve-pipe.o +; ---------------------------------------------------------- +; Chamadas de sistema... +; ---------------------------------------------------------- +%define SYS_WRITE 1 +%define SYS_CLOSE 3 +%define SYS_PIPE 22 +%define SYS_DUP2 33 +%define SYS_FORK 57 +%define SYS_EXECVE 59 +%define SYS_EXIT 60 +%define SYS_WAIT 61 +; ---------------------------------------------------------- +; Parâmetros de SYS_WAIT... +; ---------------------------------------------------------- +%define W_CHILD -1 ; filho de qualquer PID +%define W_STATUS 0 ; ignorar o estado de término (NULL) +%define W_OPTIONS 0 ; sem opções +; ---------------------------------------------------------- +; Descritores de arquivos padrão... +; ---------------------------------------------------------- +%define STDIN_FD 0 +%define STDOUT_FD 1 +; ---------------------------------------------------------- +; Estados de término... +; ---------------------------------------------------------- +%define EXIT_SUCCESS 0 +%define EXIT_ERROR 1 +; ---------------------------------------------------------- +section .rodata +; ---------------------------------------------------------- + ; Mensagem... + msg db "Salve, simpatia!", 10 + len equ $ - msg + + ; Argumentos de execve... + comm db "/bin/cat", 0 + argv dq comm, 0 + envp dq 0 +; ---------------------------------------------------------- +section .bss +; ---------------------------------------------------------- + read_end resd 1 ; Descritor da ponta de leitura do pipe + write_end resd 1 ; Descritor da ponta de escrita do pipe +; ---------------------------------------------------------- +section .text +; ---------------------------------------------------------- +global _start + +_start: + ; pipe(int pipefd[]) + ; retorna: pipefd[0] => read_end; pipefd[1] => write_end + mov rax, SYS_PIPE + mov rdi, read_end ; Retorno vai avançar em write_end + syscall + +.parada1: ; examinar FDs retornados! + + ; fork() + mov rax, SYS_FORK + syscall + + test rax, rax ; rax = 0 -> processo filho + jz .filho ; pula a execução do código do pai +; ---------------------------------------------------------- +; Código executado apenas no processo pai... +; ---------------------------------------------------------- +.pai: +; ---------------------------------------------------------- + ; dup2(write_end, STDOUT) + mov rax, SYS_DUP2 + mov edi, [write_end] ; FD original: write_end + mov rsi, STDOUT_FD ; novo descritor de escrita + syscall + + ; Fechar write_end e read_end... + call _close_all + +.parada2: ;examinar /proc//fd! + + ; write(STDOUT, msg, len) + mov rax, SYS_WRITE + mov rdi, STDOUT_FD + mov rsi, msg + mov rdx, len + syscall + + ; wait4(-1, NULL, 0) + mov rax, SYS_WAIT + mov rdi, W_CHILD + mov rsi, W_STATUS + mov rdx, W_OPTIONS + + ; exit(0) + mov rax, SYS_EXIT + mov rdi, EXIT_SUCCESS ; sai com sucesso se chegar aqui + syscall +; ---------------------------------------------------------- +; Código executado apenas no processo filho... +; ---------------------------------------------------------- +.filho: +; ---------------------------------------------------------- + ; dup2(read_end, STDIN) + mov rax, SYS_DUP2 + mov edi, [read_end] ; descritor de leitura no pipe + mov rsi, STDIN_FD ; novo descritor de leitura + syscall + + ; Fechar write_end e read_end... + call _close_all + + ; execve("/bin/cat", ["/bin/cat", NULL], [NULL]) + mov rax, SYS_EXECVE + mov rdi, comm + mov rsi, argv + mov rdx, envp + syscall + + ; exit(1) + mov rax, SYS_EXIT + mov rdi, EXIT_ERROR ; sai com erro se execve falhar + syscall +; ---------------------------------------------------------- +; Sub de fechamento dos descritores originais do pipe... +; ---------------------------------------------------------- +_close_all: +; ---------------------------------------------------------- + ; close(read_end) + mov rax, SYS_CLOSE + mov rdi, [read_end] + syscall + ; close(write_end) + mov rax, SYS_CLOSE + mov rdi, [write_end] + syscall + ret + diff --git a/curso/exemplos/08/salve-read.asm b/curso/exemplos/08/salve-read.asm new file mode 100644 index 0000000..439360e --- /dev/null +++ b/curso/exemplos/08/salve-read.asm @@ -0,0 +1,83 @@ +; ---------------------------------------------------------- +; Chamadas de sistema +; ---------------------------------------------------------- +%define SYS_READ 0 +%define SYS_WRITE 1 +%define SYS_EXIT 60 +; ---------------------------------------------------------- +; Descritores de arquivos padrão +; ---------------------------------------------------------- +%define STDIN_FD 0 +%define STDOUT_FD 1 +; ---------------------------------------------------------- +; Estados de término +; ---------------------------------------------------------- +%define EXIT_SUCCESS 0 +; ---------------------------------------------------------- +; Constantes simbólicas +; ---------------------------------------------------------- +%define BUF_SIZE 256 +; ---------------------------------------------------------- +section .rodata +; ---------------------------------------------------------- + msg db `Salve, simpatia!\nQual é a sua graça?\n` + msg_len equ $ - msg + + resp db "Falaê, " + resp_len equ $ - resp + + tail db `!\n` +; ---------------------------------------------------------- +section .bss +; ---------------------------------------------------------- + buf resb BUF_SIZE ; Buffer de leitura + count resd 1 ; retorno de read (int) +; ---------------------------------------------------------- +section .text +; ---------------------------------------------------------- +global _start +_start: + ; Imprime a mensagem inicial + mov rsi, msg + mov rdx, msg_len + call _print + + ; Aguarda os dados da entrada padrão + mov rax, SYS_READ + mov rdi, STDIN_FD + mov rsi, buf + mov rdx, BUF_SIZE + syscall + + ; Salva retorno da chamada (bytes lidos) + mov [count], eax + + ; Imprime prefixo da resposta + mov rsi, resp + mov rdx, resp_len + call _print + + ; Imprime resposta + mov rsi, buf + mov rdx, [count] ; total de bytes lidos + dec rdx ; desconta \n + call _print + + ; Imprime final da resposta + mov rsi, tail + mov rdx, 2 ; !\n = 2 bytes + call _print + + ; Termina o programa + mov rax, SYS_EXIT + mov rdi, EXIT_SUCCESS + syscall +; ---------------------------------------------------------- +; Sub-rotinas... +; ---------------------------------------------------------- +_print: +; ---------------------------------------------------------- + mov rax, SYS_WRITE + mov rdi, STDOUT_FD + syscall + ret diff --git a/curso/exemplos/08/salve-redir.asm b/curso/exemplos/08/salve-redir.asm new file mode 100644 index 0000000..e92b3a1 --- /dev/null +++ b/curso/exemplos/08/salve-redir.asm @@ -0,0 +1,58 @@ +; Chamadas de sistema... +%define SYS_WRITE 1 +%define SYS_OPEN 2 +%define SYS_CLOSE 3 +%define SYS_DUP2 33 +%define SYS_EXIT 60 + +; Flags da chamada SYS_OPEN... +%define O_WRONLY 0x1 ; apenas para escrita +%define O_CREAT 0x40 ; cria se não existir +%define O_TRUNC 0x200 ; trunca conteúdo existente + +; Permissões do arquivo criado... +%define F_MODE 0o644 + +; Descritores de arquivos... +%define STDOUT 1 + +section .rodata + file db "mensagem.txt", 0 ; arquivo de destino + msg db "Salve, simpatia!", 10 ; Mensagem + len equ $ - msg ; Tamanho da mensagem + +section .text + global _start + +_start: + ; open (ARQUIVO, FLAGS, MODO) + mov rax, SYS_OPEN + mov rdi, file + mov rsi, O_WRONLY | O_CREAT | O_TRUNC + mov rdx, F_MODE + syscall + + mov r12, rax ; salvar descritor de arquivo retornado + + ; dup2(ANTIGO_FD, NOVO_FD) + mov rax, SYS_DUP2 + mov rdi, r12 + mov rsi, STDOUT + syscall + + ; write(FD, STRING, SIZE) + mov rax, SYS_WRITE + mov rdi, STDOUT + mov rsi, msg + mov rdx, len + syscall + + ; close(FD) + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + + ; exit(STATUS) + mov rax, SYS_EXIT + xor rdi, rdi + syscall