From 4d701d4461c15394c1f05e2978f3915f79df1da3 Mon Sep 17 00:00:00 2001 From: Blau Araujo Date: Sun, 25 May 2025 12:27:43 -0300 Subject: [PATCH] exemplos da aula 6 --- curso/exemplos/06/args.asm | 66 +++++++++++++ curso/exemplos/06/cargs.asm | 50 ++++++++++ curso/exemplos/06/exit42.asm | 9 ++ curso/exemplos/06/print_utils.asm | 159 ++++++++++++++++++++++++++++++ curso/exemplos/06/prog.asm | 20 ++++ 5 files changed, 304 insertions(+) create mode 100644 curso/exemplos/06/args.asm create mode 100644 curso/exemplos/06/cargs.asm create mode 100644 curso/exemplos/06/exit42.asm create mode 100644 curso/exemplos/06/print_utils.asm create mode 100644 curso/exemplos/06/prog.asm diff --git a/curso/exemplos/06/args.asm b/curso/exemplos/06/args.asm new file mode 100644 index 0000000..2071e29 --- /dev/null +++ b/curso/exemplos/06/args.asm @@ -0,0 +1,66 @@ +; ---------------------------------------------------------- +; Arquivo : args.asm +; Descrição : Imprime argc e argv[0 .. (argc-1)] +; Montar com: nasm -f elf64 args.asm +; Ligar com : ls -o args args.o print_utils.o +; ---------------------------------------------------------- +section .rodata + pref_argc db "argc : ", 0 + pref_argv db "argv[", 0 + posf_argv db "]: ", 0 + +; sub-rotinas do módulo print_utils.o +extern print_int +extern print_str +extern print_char + +section .text +global _start + +_start: +; ---------------------------------------------------------- +; Impressão de argc +; ---------------------------------------------------------- + mov rdi, pref_argc ; endereço de pref_argc + call print_str ; imprime pref_argc + + mov rax, [rsp] ; rax = argc + call print_int ; imprime argc + + mov rdi, 10 ; rdi = \n + call print_char ; imprime \n +; ---------------------------------------------------------- +; Impressão de argv +; ---------------------------------------------------------- + mov rcx, 0 ; índice i = 0 + lea rbx, [rsp + 8] ; rbx = endereço de argv[0] + +.print_argv_loop: + cmp rcx, [rsp] ; enquanto i < argc + jge .done_argv + + mov rdi, pref_argv ; imprime prefixo "argv[" + call print_str + + mov rax, rcx ; rax = i + call print_int ; imprime índice + + mov rdi, posf_argv ; imprime sufixo "]: " + call print_str + + mov rdi, [rbx + rcx*8] ; rdi = argv[i] + call print_str + + mov rdi, 10 ; imprime \n + call print_char + + inc rcx + jmp .print_argv_loop + +.done_argv: +; ---------------------------------------------------------- +; Termina o programa com exit(0) +; ---------------------------------------------------------- + mov rax, 60 ; syscall: exit + xor rdi, rdi ; status = 0 + syscall diff --git a/curso/exemplos/06/cargs.asm b/curso/exemplos/06/cargs.asm new file mode 100644 index 0000000..70e8af7 --- /dev/null +++ b/curso/exemplos/06/cargs.asm @@ -0,0 +1,50 @@ +section .bss + argc: resq 1 ; 8 bytes para armazenar argc + argv: resq 1 ; 8 bytes para armazenar ponteiro para argv[0] + +section .data + fmt_argc db "argc : %ld", 10, 0 + fmt_argv db "argv[%d]: %s", 10, 0 + +global main +extern printf + +section .text +main: + ; rdi = argc + ; rsi = argv + mov [argc], rdi ; salvar argc + mov [argv], rsi ; salvar argv[0] + + ; Imprimir com: printf("argc : %ld", argc); + mov rdi, fmt_argc ; primeiro argumento: formato + mov rsi, [argc] ; segundo argumento: argc (qword = long) + xor rax, rax ; terminação de argumentos + call printf + + ; preparar o laço: i = 0 + xor rcx, rcx ; i = 0 + mov rbx, [argv] ; rbx = argv base + mov r8, [argc] ; r8 = argc + +.loop: + cmp rcx, r8 ; compara i com argc + jge .done ; se i >= argc, fim + + ; Imprimir com: printf("argv[%d]: %s\n", i, argv[i]); + mov rdi, fmt_argv ; primeiro argumento: formato + mov rsi, rcx ; segundo argumento: i + mov rdx, [rbx + rcx*8] ; terceiro argumento: argv[i] + xor rax, rax ; terminação de argumentos + push rcx ; salvar rcx (caller saved) na pilha + push r8 ; salvar r8 (caller saved) na pilha + call printf + pop r8 ; restaurar rcx + pop rcx ; restaurar rcx + + inc rcx + jmp .loop + +.done: + xor eax, eax ; retorno de main: (int)0 + ret diff --git a/curso/exemplos/06/exit42.asm b/curso/exemplos/06/exit42.asm new file mode 100644 index 0000000..f7a7152 --- /dev/null +++ b/curso/exemplos/06/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/06/print_utils.asm b/curso/exemplos/06/print_utils.asm new file mode 100644 index 0000000..ac6132a --- /dev/null +++ b/curso/exemplos/06/print_utils.asm @@ -0,0 +1,159 @@ +; ------------------------------------------------------------ +; print_utils.asm +; Sub-rotinas: +; - print_char(rdi = caractere) +; - print_str(rdi = ptr string \0-terminated) +; - print_int(rax = inteiro, sem newline) +; Macros: +; - SAVE_REGS: salva registradores voláteis +; - RESTORE_REGS: restaura registradores salvos +; ------------------------------------------------------------ + +%macro SAVE_REGS 0 + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push r8 + push r9 + push r10 + push r11 +%endmacro + +%macro RESTORE_REGS 0 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax +%endmacro + +section .bss + int_buf resb 22 ; buffer para int e char + +section .text +global print_char +global print_str +global print_int + +; ------------------------------------------------------------ +; void print_char(rdi = caractere) +; ------------------------------------------------------------ +print_char: + push rbp + mov rbp, rsp + + SAVE_REGS + + mov al, dil ; coloca o caractere em al (parte baixa de rax) + mov byte [int_buf], al ; usa o mesmo buffer global + + mov rax, 1 ; syscall write + mov rdi, 1 ; stdout + lea rsi, [int_buf] + mov rdx, 1 + syscall + + RESTORE_REGS + + mov rsp, rbp + pop rbp + ret + +; ------------------------------------------------------------ +; void print_str(rdi = ptr string \0-terminated) +; ------------------------------------------------------------ +print_str: + push rbp + mov rbp, rsp + + SAVE_REGS + + mov rsi, rdi ; ponteiro string + xor rcx, rcx + +.count_loop: + cmp byte [rsi + rcx], 0 + je .write + inc rcx + jmp .count_loop + +.write: + mov rax, 1 ; syscall write + mov rdi, 1 ; stdout + mov rdx, rcx ; tamanho string + syscall + + RESTORE_REGS + + mov rsp, rbp + pop rbp + ret + +; ------------------------------------------------------------ +; void print_int(rax = inteiro, sem newline) +; ------------------------------------------------------------ +print_int: + push rbp + mov rbp, rsp + + SAVE_REGS + + mov rdi, rax + lea rsi, [int_buf + 21] ; aponta para o fim do buffer + mov byte [rsi], 0 ; opcional: zero-termina + + cmp rdi, 0 + jne .convert + + ; zero + dec rsi + mov byte [rsi], '0' + jmp .write + +.convert: + mov rax, rdi + mov rbx, 10 + xor rcx, rcx + + cmp rdi, 0 + jge .conv_loop + + neg rax + mov rcx, 1 ; sinal negativo + +.conv_loop: + xor rdx, rdx + div rbx + add dl, '0' + dec rsi + mov [rsi], dl + test rax, rax + jnz .conv_loop + + test rcx, rcx + jz .write + + dec rsi + mov byte [rsi], '-' + +.write: + mov rax, 1 ; syscall write + mov rdi, 1 ; stdout + mov rdx, int_buf + 21 + sub rdx, rsi + syscall + + RESTORE_REGS + + mov rsp, rbp + pop rbp + ret + diff --git a/curso/exemplos/06/prog.asm b/curso/exemplos/06/prog.asm new file mode 100644 index 0000000..fb08f80 --- /dev/null +++ b/curso/exemplos/06/prog.asm @@ -0,0 +1,20 @@ +section .data + fmt db "Programa: %s", 10, 0 + +global main ; símbolo chamado por _start de crt0.o +extern printf ; (opcional) usar funções da libc + +section .text +main: + ; argc → rdi + ; argv → rsi + ; envp → rdx (não obrigatório) + + ; Exemplo: imprimir argv[0] + mov rdi, fmt + mov rsi, [rsi] ; argv[0] + xor rax, rax ; terminação de argumentos (printf é variádica) + call printf + + mov eax, 0 ; retorno de 'main' = (int)0 + ret