exemplos da aula 6

This commit is contained in:
Blau Araujo 2025-05-25 12:27:43 -03:00
parent ee62511898
commit 4d701d4461
5 changed files with 304 additions and 0 deletions

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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