From 6fbe5f3a623cb9dcd626168e143449b36d76fa3c Mon Sep 17 00:00:00 2001 From: Blau Araujo Date: Wed, 18 Jun 2025 09:53:30 -0300 Subject: [PATCH] =?UTF-8?q?diret=C3=B3rios=208=20e=2013=20de=20exemplos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- curso/exemplos/08/#sint.asm# | 76 +++++++++ curso/exemplos/08/.gdb_history | 193 ++++++++++++++++++++++ curso/exemplos/08/exemplo.c | 14 ++ curso/exemplos/08/limites.c | 27 +++ curso/exemplos/08/sint.asm | 76 +++++++++ curso/exemplos/08/uint.asm | 129 +++++++++++++++ curso/exemplos/08/uint.c | 51 ++++++ curso/exemplos/13/.gdb_history | 107 ++++++++++++ curso/exemplos/13/mensagem.txt | 1 + curso/exemplos/{08 => 13}/salve-pipe.asm | 0 curso/exemplos/{08 => 13}/salve-read.asm | 0 curso/exemplos/{08 => 13}/salve-redir.asm | 0 curso/exemplos/13/teste.asm | 146 ++++++++++++++++ 13 files changed, 820 insertions(+) create mode 100644 curso/exemplos/08/#sint.asm# create mode 100644 curso/exemplos/08/.gdb_history create mode 100644 curso/exemplos/08/exemplo.c create mode 100644 curso/exemplos/08/limites.c create mode 100644 curso/exemplos/08/sint.asm create mode 100644 curso/exemplos/08/uint.asm create mode 100644 curso/exemplos/08/uint.c create mode 100644 curso/exemplos/13/.gdb_history create mode 100644 curso/exemplos/13/mensagem.txt rename curso/exemplos/{08 => 13}/salve-pipe.asm (100%) rename curso/exemplos/{08 => 13}/salve-read.asm (100%) rename curso/exemplos/{08 => 13}/salve-redir.asm (100%) create mode 100644 curso/exemplos/13/teste.asm diff --git a/curso/exemplos/08/#sint.asm# b/curso/exemplos/08/#sint.asm# new file mode 100644 index 0000000..46429b1 --- /dev/null +++ b/curso/exemplos/08/#sint.asm# @@ -0,0 +1,76 @@ +; ---------------------------------------------------------- +str_to_int: +; ---------------------------------------------------------- +; Converte string numérica com sinal em inteiro (int32_t). +; Entradas: +; RSI = Endereço da string (char *str) +; RDX = Endereço para estado de erro (int *err /* nullable */) +; Saída: +; RAX = valor convertido (int32_t) +; Sucesso: *rdx = 1 +; Erro: *rdx = 0 +; ---------------------------------------------------------- + push rbx ; salva rbx + push rcx ; salva rcx + xor rcx, rcx ; rcx = 0 (sinal: 0 = positivo, 1 = negativo) + ; ------------------------------------------------------ + ; Testa ponteiro nulo + ; ------------------------------------------------------ + test rsi, rsi + jz .error + ; ------------------------------------------------------ + ; Verifica o sinal na string + ; ------------------------------------------------------ + mov bl, [rsi] + cmp bl, '-' ; caractere de sinal negativo? + jne .check_plus + inc rcx ; rcx = 1 => negativo + inc rsi ; avança o ponteiro + jmp .convert +stramoecheck_plus: + cmp bl, '+' ; caractere de sinal positivo? + jne .convert + inc rsi ; ignora '+' +.convert: + ; ------------------------------------------------------ + ; Chama _str_to_uint + ; ------------------------------------------------------ + call _str_to_uint ; RSI = str, RDX = err, RAX = resultado (uint32_t) + ; ------------------------------------------------------ + ; Verifica se _str_to_uint retornou erro + ; ------------------------------------------------------ + test rdx, rdx + jz .check_sign + cmp dword [rdx], 0 + je .error +.check_sign: + test rcx, rcx ; se rcx = 1, é número negativo + jz .check_range_pos + ; ------------------------------------------------------ + ; Verifica se valor cabe em int32_t negativo + ; ------------------------------------------------------ + cmp eax, 2147483648 + ja .error ; menor que INT_MIN -> erro + + neg eax ; aplica o sinal negativo + jmp .success +.check_range_pos: + ; ------------------------------------------------------ + ; Verifica se valor cabe em int32_t positivo + ; ------------------------------------------------------ + cmp eax, 2147483647 + ja .error ; maior que INT_MAX -> erro +.success: + test rdx, rdx + jz .done + mov dword [rdx], 1 ; *err = 1 + jmp .done +.error: + xor eax, eax ; valor de erro = 0 + test rdx, rdx + jz .done + mov dword [rdx], 0 ; *err = 0 +.done: + pop rcx + pop rbx + ret diff --git a/curso/exemplos/08/.gdb_history b/curso/exemplos/08/.gdb_history new file mode 100644 index 0000000..ce1ac96 --- /dev/null +++ b/curso/exemplos/08/.gdb_history @@ -0,0 +1,193 @@ +q +break main +run 23 19 +p argv +p argv[1] +x /3bx argv[1] +x /1wx argv[2] +x /1dx argv[2] +x /1dx argv[1] +x /1gx argv[1] +x /5bx argv[1] +x /6bx argv[1] +x /7bx argv[1] +x /7bx argv +x /7bx argv[0] +x /7bx argv[1] +x /3bx argv[1] +x /3bx argv[2] +x /x argv[2] +x /x argv[1] +x /dx argv[1] +x /d2x argv[1] +x /1dx argv[1] +x /wx argv[1] +x /2wx argv[1] +x /3wx argv[1] +x /3bx argv[1] +x /3bx argv[2] +x /6bx argv[1] +x /6dx argv[1] +x /6wx argv[1] +q +break main +run 123 456 +x /8bx argv[1] +x /8cx argv[1] +x /8bc argv[1] +x /8bx argv[1] +x /8bd argv[1] +x /8bx argv[1] +x /1gx argv[1] +x /1wx argv[1] +x /1wx argv[2] +x /1bx argv[1] +x /4bx argv[1] +x /4bx argv[2] +x /1wx argv[1] +x /1wx argv[2] +p (int)argv[1] +p (int)*argv[1] +p (int)*(argv[1]) +p *((int)argv[1]) +p argv[1] +q +break main +run +q +b main +r +p a +n +p a +p b +x /1wx a +x /1wx &a +x /1wx b +q +b main +r +n +x /1wx &a +x /1wx b +x /1wx &c +x /1wx d +x /4bx b +q +break printf +r +q +break main +run +n 4 +x /1wx &a +x /1wx b +x /1wx &c +x /1wx d +x /1w d +x /1wd d +x /1wd &a +x /1wd b +x /1wd &c +x /1wd d +q +break main +run +next 3 +x /1wx &a +x /1wx b +x /1wx c +x /4bx &a +x /4bx b +x /4bx c +q +b _start +layout regs +r +n +q +b _start +r +n +i registers rsi +x /1s &rsi +x /1s rsi +x /1s $rsi +x /1s num_str +x /1s &num_str +n +i registers rax +q +break _start +rr +r +info registers rax rdx +info registers rax rdx rsi +n +info registers rax rdx rsi +x /1s &num_str +x /1s &num +x /1wx &num +x /1wx &status +k +r +n 2 +info registers rax rdx rsi +x /1wx &num +x /1wx &status +n +info registers rax rdx rsi +x /1wx &num +x /1wx &status +n +x /1wx &status +info registers rax rdx rsi +k +q +break _start +run +n 2 +info registers rax rdx rsi +x /1w &num_str +x /1wx &num_str +x /1s &num +x /1wx &num +x /1wx &status +n +info registers rax rdx rsi +x /1wx &num +x /1wx &status +n +k +r +n2 +n 2 +info registers rax rdx rsi +x /1wx &num +x /1wx &status +q +b _start +r +n 4 +x /1wx &status +x /1wx &num +info registers rax rdx rsi +q +break _start +run +n 2 +info registers rax rdx rsi +x /1wx &num_str +x /1s &num_str +x /1wx &num_ +x /1wx &num +x /1wx &status +n +n +info registers rax rdx rsi +x /1wx &num +x /1wx &status +print num +print &num +print (int)num +q diff --git a/curso/exemplos/08/exemplo.c b/curso/exemplos/08/exemplo.c new file mode 100644 index 0000000..0505a2c --- /dev/null +++ b/curso/exemplos/08/exemplo.c @@ -0,0 +1,14 @@ +#include + +int main(void) { + + int a = 123; + char *b = "123"; + int *c = (int *)b; // Casting do valor no endereço 'b' para inteiro + + printf("Inteiro a: %d\n", a); + printf("String b: %s\n", b); + printf("Inteiro c: %d\n", *c); // Imprime o valor no endereço 'c' + + return 0; +} diff --git a/curso/exemplos/08/limites.c b/curso/exemplos/08/limites.c new file mode 100644 index 0000000..da71e08 --- /dev/null +++ b/curso/exemplos/08/limites.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +int main(void) { + + setlocale(LC_NUMERIC, ""); + + puts("Tipo Bytes Limites (x86_64)"); + puts("========================================================================"); + printf("char (%zu) %d a %d\n", sizeof(char), SCHAR_MIN, SCHAR_MAX); + printf("unsigned char (%zu) %d a %d\n", sizeof(unsigned char), 0, UCHAR_MAX); + printf("short (%zu) %'d a %'d\n", sizeof(short), SHRT_MIN, SHRT_MAX); + printf("unsigned short (%zu) %d a %'d\n", sizeof(unsigned short), 0, USHRT_MAX); + printf("int (%zu) %'d a %'d\n", sizeof(int), INT_MIN, INT_MAX); + printf("unsigned int (%zu) %d a %'u\n", sizeof(unsigned int), 0, UINT_MAX); + printf("long int (%zu) %'ld a %'ld\n", sizeof(long int), LONG_MIN, LONG_MAX); + printf("unsigned long int (%zu) %d a %'lu\n", sizeof(long unsigned int), 0, ULONG_MAX); + printf("long long (%zu) %'ld a %'ld\n", sizeof(long long int), LLONG_MIN, LLONG_MAX); + printf("unsigned long long (%zu) %d a %'llu\n", sizeof(unsigned long long int), 0, ULLONG_MAX); + printf("float (%zu) %.2E a %.2E\n", sizeof(float), FLT_MIN, FLT_MAX); + printf("double (%zu) %.2E a %.2E\n", sizeof(double), DBL_MIN, DBL_MAX); + printf("long double (%zu) %.2LE a %.2LE\n", sizeof(long double), LDBL_MIN, LDBL_MAX); + + return 0; +} diff --git a/curso/exemplos/08/sint.asm b/curso/exemplos/08/sint.asm new file mode 100644 index 0000000..9c5ac43 --- /dev/null +++ b/curso/exemplos/08/sint.asm @@ -0,0 +1,76 @@ +; ---------------------------------------------------------- +str_to_int: +; ---------------------------------------------------------- +; Converte string numérica com sinal em inteiro (int32_t). +; Entradas: +; RSI = Endereço da string (char *str) +; RDX = Endereço para estado de erro (int *err /* nullable */) +; Saída: +; RAX = valor convertido (int32_t) +; Sucesso: *rdx = 1 +; Erro: *rdx = 0 +; ---------------------------------------------------------- + push rbx ; salva rbx + push rcx ; salva rcx + xor rcx, rcx ; rcx = 0 (sinal: 0 = positivo, 1 = negativo) + ; ------------------------------------------------------ + ; Testa ponteiro nulo + ; ------------------------------------------------------ + test rsi, rsi + jz .error + ; ------------------------------------------------------ + ; Verifica o sinal na string + ; ------------------------------------------------------ + mov bl, [rsi] + cmp bl, '-' ; caractere de sinal negativo? + jne .check_plus + inc rcx ; rcx = 1 => negativo + inc rsi ; avança o ponteiro + jmp .convert +.check_plus: + cmp bl, '+' ; caractere de sinal positivo? + jne .convert + inc rsi ; ignora '+' +.convert: + ; ------------------------------------------------------ + ; Chama _str_to_uint + ; ------------------------------------------------------ + call _str_to_uint ; RSI = str, RDX = err, RAX = resultado (uint32_t) + ; ------------------------------------------------------ + ; Verifica se _str_to_uint retornou erro + ; ------------------------------------------------------ + test rdx, rdx + jz .check_sign + cmp dword [rdx], 0 + je .error +.check_sign: + test rcx, rcx ; se rcx = 1, é número negativo + jz .check_range_pos + ; ------------------------------------------------------ + ; Verifica se valor cabe em int32_t negativo + ; ------------------------------------------------------ + cmp eax, 2147483648 + ja .error ; menor que INT_MIN -> erro + + neg eax ; aplica o sinal negativo + jmp .success +.check_range_pos: + ; ------------------------------------------------------ + ; Verifica se valor cabe em int32_t positivo + ; ------------------------------------------------------ + cmp eax, 2147483647 + ja .error ; maior que INT_MAX -> erro +.success: + test rdx, rdx + jz .done + mov dword [rdx], 1 ; *err = 1 + jmp .done +.error: + xor eax, eax ; valor de erro = 0 + test rdx, rdx + jz .done + mov dword [rdx], 0 ; *err = 0 +.done: + pop rcx + pop rbx + ret diff --git a/curso/exemplos/08/uint.asm b/curso/exemplos/08/uint.asm new file mode 100644 index 0000000..00fe262 --- /dev/null +++ b/curso/exemplos/08/uint.asm @@ -0,0 +1,129 @@ +; ---------------------------------------------------------- +; Arquivo : uint.asm +; Montagem: nasm -g -f elf64 uint.asm +; Ligação : ls uint.o -o uint +; ---------------------------------------------------------- +section .data +; ---------------------------------------------------------- + num_str db "123", 0 ; string numérica +; ---------------------------------------------------------- +section .bss +; ---------------------------------------------------------- + num resd 1 ; 4 bytes para o valor UINT32 + status resd 1 ; 4 bytes para o estado de término +; ---------------------------------------------------------- +section .text +global _start +; ---------------------------------------------------------- +_start: +; ---------------------------------------------------------- +; Teste de chamada (verificar com o GDB)... +; ---------------------------------------------------------- + mov rsi, num_str ; copia endereço da string em rsi + mov rdx, status ; copia o endereço do estado de erro em rdx + call _str_to_uint ; chama a sub-rotina de conversão + mov dword [num], eax ; copia o resultado como int para [num] +; ---------------------------------------------------------- +_exit: +; ---------------------------------------------------------- + mov rax, 60 + mov rdi, 0 + syscall +; ---------------------------------------------------------- +; Sub-rotinas... +; ---------------------------------------------------------- +_str_to_uint: +; ---------------------------------------------------------- +; Converte string numérica em inteiro sem sinal (uint32_t). +; Entradas: +; RSI = Endereço da string (char *str) +; RDX = Endereço para estado de erro (int *err /* nullable */) +; Saída: +; RAX = valor convertido (uint32_t) ou 0, no caso de erro +; Sucesso: *rdx = 1 +; Erro: *rdx = 0 +; ---------------------------------------------------------- + ; Definição condicional do estado inicial de erro... + ; ------------------------------------------------------ + test rdx, rdx ; Se *err = NULL, rdx = 0 + jz .skip_error ; Se for 0, pula a definição do erro + mov dword [rdx], 0 ; *err = 0 => estado inicial é de erro (falso) + ; ------------------------------------------------------ +.skip_error: + ; ------------------------------------------------------ + ; Teste de ponteiro nulo... + ; ------------------------------------------------------ + test rsi, rsi ; verifica se enderçeo é nulo (0) + jz .error ; se for, termina retornando -1 (erro) + ; ------------------------------------------------------ + ; Preparação... + ; ------------------------------------------------------ + push rbx ; salva rbx na pilha + xor rax, rax ; rax = 0 (acumula o resultado) + xor rbx, rbx ; rbx = 0 (recebe os caracteres no loop) + mov bl, [rsi] ; lê o primeiro byte + ; ------------------------------------------------------ + ; Validação do primeiro byte... + ; ------------------------------------------------------ + cmp bl, 0x30 ; compara com menor byte válido + jl .error ; se menor, termina retornando -1 + cmp bl, 0x39 ; compara com maior byte válido + jg .error ; se maior, termina retornando -1 +.conv_loop: + ; ------------------------------------------------------ + ; Condições de término da conversão ... + ; ------------------------------------------------------ + test bl, bl ; verifica se o byte é o terminador 0x00 + je .success ; se for, termina com sucesso + cmp bl, 0x30 ; compara o byte em rbx com o menor dígito + jl .success ; se for menor, termina com sucesso + cmp bl, 0x39 ; compara o byte em rbx com o maior dígito + jg .success ; se for maior, termina com sucesso + ; ------------------------------------------------------ + ; Conversão do dígito corrente... + ; ------------------------------------------------------ + sub rbx, 0x30 ; converte o dígito para seu valor numérico + ; ------------------------------------------------------ + ; Limite válido: conv < (UINT_MAX - dígito) / 10 + ; ------------------------------------------------------ + mov r8, rax ; Salva parcial da conversão em r8 + mov r10, rdx ; Salva ponteiro de erro em r10 + + mov eax, -1 ; eax = 0xffffffff (UINT_MAX - 32 bits) + sub eax, ebx ; rax = UINT_MAX - dígito (dividendo) + + xor rdx, rdx ; prepara rdx para receber o resto da divisão + mov r9, 10 ; divisor + div r9 ; limite(rax) = (UINT_MAX - dígito) / 10 + + cmp r8, rax ; se parcial > limite, teremos um estouro + jg .error ; se maior, termina com erro + + mov rdx, r10 ; restaura rdx (pontiero para erros) + mov rax, r8 ; restaura rax (parcial da conversão) + ; ------------------------------------------------------ + ; Processa a parcial da conversão... + ; ------------------------------------------------------ + imul rax, rax, 10 ; rax *= 10 (deslocamento do peso posicional) + add rax, rbx ; rax += novo algarismo + inc rsi ; avança para o próximo byte + mov bl, [rsi] ; carrega o dígito corrente em rbx + jmp .conv_loop + ; ------------------------------------------------------ +.error: + ; ------------------------------------------------------ + xor rax, rax ; Retorna 0 em caso de erro + jmp .done + ; ------------------------------------------------------ +.success: + ; ------------------------------------------------------ + ; Redefinição condicional do estado final de sucesso... + ; ------------------------------------------------------ + test rdx, rdx ; Se *err = NULL, rdx = 0 + jz .done ; Se for 0, pula a definição de sucesso + mov dword [rdx], 1 ; *err = 1 => estado final é de sucesso (verdadeiro) + ; ------------------------------------------------------ +.done: + ; ------------------------------------------------------ + pop rbx ; Restaura rbx + ret diff --git a/curso/exemplos/08/uint.c b/curso/exemplos/08/uint.c new file mode 100644 index 0000000..15f05dc --- /dev/null +++ b/curso/exemplos/08/uint.c @@ -0,0 +1,51 @@ +/* + * Arquivo : uint.c + * Compilação: gcc -Wall uint.c -o uintc + */ +#include +#include // Requerido para obter UINT_MAX da plataforma + +unsigned int str_to_uint(char *str, int *err /* nullable */); + +int main(int argc, char **argv) { + if (argc == 1) { + fprintf(stderr, "Uso: %s NÚMERO\n", argv[0]); + return 1; + } + + int status; + unsigned int num = str_to_uint(argv[1], &status); + + if (status) { + printf("String: %s\nNúmero: %u\n", argv[1], num); + } else { + fprintf(stderr, "Erro de conversão!\n"); + return 1; + } + + return 0; +} + +unsigned int str_to_uint(char *str, int *err /* nullable */) { + if (err) *err = 0; // Estado padrão é de erro (0 = falso)! + + // Termina com erro e valor 0 se str==NULL ou se '0'>str[0]>'9'... + if (str == NULL || str[0] < '0' || str[0] > '9') return 0; + + int dig; // Recebe o dígito convertido + unsigned int conv = 0; // Recebe a parcial da conversão + + for (int i = 0; str[i] != '\0'; i++) { + // Se o caractere não for um dígito, termina a conversão... + if (str[i] < '0' || str[i] > '9') break; + // Converte o dígito corrente... + dig = str[i] - '0'; + // Termina com erro e valor 0 se a próxima conversão exceder UINT_MAX... + if (conv > (UINT_MAX - dig) / 10) return 0; + // Processa a parcial da conversão... + conv = (conv * 10) + dig; + } + + if (err) *err = 1; // Altera estado para sucesso (1 = verdadeiro) + return conv; +} diff --git a/curso/exemplos/13/.gdb_history b/curso/exemplos/13/.gdb_history new file mode 100644 index 0000000..67edf1d --- /dev/null +++ b/curso/exemplos/13/.gdb_history @@ -0,0 +1,107 @@ +dir +l +l +b 70 +r +i proc +q +b _start +r +n +x /1gx pipe_fds +x /1gx &pipe_fds +k +b 46 +r +c +x /1gx &pipe_fds +n +n +k +q +b clone +r +x /1dx pipe_fds +x /1dx &pipe_fds +x /1dx &pipe_fds+8 +x /1dx &pipe_fds + 8 +x /1dx &(pipe_fds + 8 ) +x /2dx &pipe_fds +i registers r13 r14 +q +b clone +r +i registers r13 r14 +q +b clone +r +i registers r13 r14 +q +b clone +r +i registers r13 r14 +q +b clone +r +i registers r13 r14 +x /1dx &read_end +x /1dx &write_end +q +b _start.parada +r +q +b _start.parada +r +x /1dx &write_end +x /1dx &read_end +q +b _start.parada +r +k +q +b _start.parada +r +k +q +b _start.parada +r +c +q +b _start.parada +r +k +q +b _start.parada +r +c +q +b _start.parada1 +b _start.parada2 +r +x /1gx &read_end +x /1dx &read_end +x /1dx &write_end +x /1x &read_end +x /1dx &read_end +p read_end +p (int *)read_end +x /4bx &read_end +x /1bx &read_end +x /1bx &write_end +x /1wx &write_end +x /1wx &read_end +x /1gx &read_end +c +c +b _start.parada1 +b _start.parada2 +r +x /1wx &read_end +x /1wx &write_end +x /1gx &read_end +x /1wx &read_end +x /1wx &write_end +i proc +c +c +q diff --git a/curso/exemplos/13/mensagem.txt b/curso/exemplos/13/mensagem.txt new file mode 100644 index 0000000..a608f9e --- /dev/null +++ b/curso/exemplos/13/mensagem.txt @@ -0,0 +1 @@ +Salve, simpatia! diff --git a/curso/exemplos/08/salve-pipe.asm b/curso/exemplos/13/salve-pipe.asm similarity index 100% rename from curso/exemplos/08/salve-pipe.asm rename to curso/exemplos/13/salve-pipe.asm diff --git a/curso/exemplos/08/salve-read.asm b/curso/exemplos/13/salve-read.asm similarity index 100% rename from curso/exemplos/08/salve-read.asm rename to curso/exemplos/13/salve-read.asm diff --git a/curso/exemplos/08/salve-redir.asm b/curso/exemplos/13/salve-redir.asm similarity index 100% rename from curso/exemplos/08/salve-redir.asm rename to curso/exemplos/13/salve-redir.asm diff --git a/curso/exemplos/13/teste.asm b/curso/exemplos/13/teste.asm new file mode 100644 index 0000000..86fd97d --- /dev/null +++ b/curso/exemplos/13/teste.asm @@ -0,0 +1,146 @@ +; Arquivo: pipe_ls_cat.asm +; Montar com: nasm -felf64 pipe_ls_cat.asm && ld -o pipe_ls_cat pipe_ls_cat.o + +%define SYS_READ 0 +%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_WAITPID 61 + +%define STDIN_FD 0 +%define STDOUT_FD 1 +%define STDERR_FD 2 + +%define EXIT_SUCCESS 0 +%define EXIT_FAILURE 1 + +section .rodata + cmd_ls db "/bin/ls", 0 + arg0_ls dq cmd_ls + arg1_ls db "-l", 0 + arg2_ls db "/proc/self/fd", 0 + argv_ls dq arg0_ls, arg1_ls, arg2_ls, 0 + + cmd_cat db "/bin/cat", 0 + arg0_cat dq cmd_cat + argv_cat dq arg0_cat, 0 + + envp_null dq 0 + +section .bss + pipefds resq 2 ; 2 x 8 bytes (r/w) + +section .text +global _start + +_start: + ; Cria pipe + mov rax, SYS_PIPE + mov rdi, pipefds + syscall + + mov r12, [pipefds] ; leitura (pipefds[0]) + mov r13, [pipefds + 8] ; escrita (pipefds[1]) + + ; Fork para ls + mov rax, SYS_FORK + syscall + test rax, rax + jz .ls_child + + ; Fork para cat + mov rax, SYS_FORK + syscall + test rax, rax + jz .cat_child + + ; Pai: fecha descritores do pipe + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + + mov rax, SYS_CLOSE + mov rdi, r13 + syscall + + ; Espera dois filhos + xor rdi, rdi + xor rsi, rsi + xor rdx, rdx + mov rax, SYS_WAITPID + syscall + + xor rdi, rdi + xor rsi, rsi + xor rdx, rdx + mov rax, SYS_WAITPID + syscall + + ; Finaliza + mov rax, SYS_EXIT + xor rdi, rdi + syscall + +; ----------------------------------------- +; Processo filho: ls -l /proc/self/fd +; ----------------------------------------- +.ls_child: + ; Redireciona stdout → pipe[1] + mov rax, SYS_DUP2 + mov rdi, r13 ; escrita + mov rsi, STDOUT_FD + syscall + + ; Fecha descritores + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + mov rax, SYS_CLOSE + mov rdi, r13 + syscall + + ; execve("/bin/ls", ["ls", "-l", "/proc/self/fd"], NULL) + mov rax, SYS_EXECVE + mov rdi, cmd_ls + mov rsi, argv_ls + mov rdx, envp_null + syscall + + ; Se execve falhar + mov rax, SYS_EXIT + mov rdi, EXIT_FAILURE + syscall + +; ----------------------------------------- +; Processo filho: cat +; ----------------------------------------- +.cat_child: + ; Redireciona stdin ← pipe[0] + mov rax, SYS_DUP2 + mov rdi, r12 ; leitura + mov rsi, STDIN_FD + syscall + + ; Fecha descritores + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + mov rax, SYS_CLOSE + mov rdi, r13 + syscall + + ; execve("/bin/cat", ["cat"], NULL) + mov rax, SYS_EXECVE + mov rdi, cmd_cat + mov rsi, argv_cat + mov rdx, envp_null + syscall + + ; Se execve falhar + mov rax, SYS_EXIT + mov rdi, EXIT_FAILURE + syscall