Enviar arquivos para "codigo"
Arquivo com código fonte em assembly, padrão elf64 (GNU/Linux) Arquivo para estudo, use por sua conta e risco, o mesmo não deve ser usado em produção, pois precisa de diversos tratamentos, que não estão cobertos neste código. Você pode usar, distribuir, modificar do jeito que achar melhor, desde que dê crédito ao ao seu criador.Sugestões são bem vindas e críticas também, desde que construtivas.
This commit is contained in:
parent
3c59ee4da9
commit
77e847a478
1 changed files with 252 additions and 0 deletions
252
codigo/advinha.asm
Normal file
252
codigo/advinha.asm
Normal file
|
@ -0,0 +1,252 @@
|
|||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Programação em Baixo Nível (PBN)
|
||||
;------------------------------------------------------------------------------
|
||||
; Projeto final de curso: advinha.asm
|
||||
; Data: 23/08/2025
|
||||
; Autor: Daniel Ramos Gonçalves
|
||||
; E-mail: daniel@drginfo.com.br
|
||||
; Professor/Instrutor/Mentor: Blau Araujo (MUITO FERA)
|
||||
;
|
||||
; Proposta: Criar um programa em Assembly, jogo de advinhação.
|
||||
; O programa deve gerar um número aleatório, e você deve advinhar.
|
||||
; Entrar com um número inteiro entre 1 e 100. Deve ter críticas
|
||||
; de Maior / Menor / Igual. Deve aceitar somente números, e qualquer
|
||||
; entrada diferente deve ser decartada e encerrar o programa com
|
||||
; uma mensagem de erro.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; difinições de pré-processamento padronizadas
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
%define SYS_READ 0
|
||||
%define SYS_STDIN 0
|
||||
%define SYS_WRITE 1
|
||||
%define SYS_STDOUT 1
|
||||
%define SYS_TIME 201
|
||||
%define SYS_EXIT 60
|
||||
%define SYS_OK 0
|
||||
%define SYS_ERR 1
|
||||
%define BUF_SIZE 2048
|
||||
%define BUF_COUNT 5
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
section .rodata
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
; mensagens que serão exibidas na tela...
|
||||
|
||||
msg_ini db "Digite um número entre 1 e 100: ", 0
|
||||
len_msg_ini equ $-msg_ini
|
||||
|
||||
; com a mensagem entre crases, ela aceita caracteres de controle como '\n'
|
||||
|
||||
msg_maior db `Muito acima! Tente novamente...\n`, 0
|
||||
len_msg_maior equ $-msg_maior
|
||||
|
||||
msg_menor db `Muito abaixo! Tente novamente...\n`, 0
|
||||
len_msg_menor equ $-msg_menor
|
||||
|
||||
msg_ok_ini db "Você acertou com: ", 0
|
||||
len_msg_ok_ini equ $-msg_ok_ini
|
||||
msg_ok_end db " Tentativas!", 10, 0
|
||||
len_msg_ok_end equ $-msg_ok_end
|
||||
|
||||
; mensagem de uso...caso não digite nada ou digitação inválida...
|
||||
|
||||
msg_uso db "Você deve digitar um numero inteiro entre 1 e 100.", 10, 0
|
||||
len_msg_uso equ $-msg_uso
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
section .bss
|
||||
buffer resb BUF_SIZE
|
||||
tentativas resb BUF_COUNT
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; seção do codigo em si...
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
section .text
|
||||
|
||||
global _start
|
||||
_start:
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; gera um número inteiro randômico de 0..100 e salva resultado em r9
|
||||
; registradores: eax, edx, ebx, r9
|
||||
; resultado: r9
|
||||
;------------------------------------------------------------------------------
|
||||
_num_rand:
|
||||
mov eax, SYS_TIME
|
||||
mov edx, 0
|
||||
syscall
|
||||
mov ebx, 100
|
||||
div ebx
|
||||
add edx, 1
|
||||
mov r9d, edx
|
||||
|
||||
;--------------------------------------------------------
|
||||
; rdi rsi rdx
|
||||
; | | |
|
||||
; syscall: i64 read(int fd, void *buf[.count], u64 size)
|
||||
; |
|
||||
; rax -> quantidade de bytes lidos (-1 = erro)
|
||||
;--------------------------------------------------------
|
||||
_msg_ini:
|
||||
mov rax, SYS_WRITE ; sys_write = 1
|
||||
mov rdi, SYS_STDOUT ; fd=1 (stdout)
|
||||
mov rsi, msg_ini ; Mensagem Inicial
|
||||
mov rdx, len_msg_ini ; Tamanho da mensagem
|
||||
syscall
|
||||
|
||||
mov rax, SYS_READ ; sys_read = 0
|
||||
mov rdi, SYS_STDIN ; fd=0 (stdin)
|
||||
mov rsi, buffer ; buffer da leitura (armazenamento)
|
||||
mov rdx, BUF_SIZE ; máximo caracteres a ler
|
||||
syscall ; retorna quantidade de bytes lidos em rax
|
||||
|
||||
;--------------------------------------------------------
|
||||
; conversão de string para inteiro...
|
||||
; registradores: rax, rbx, rcx, r8
|
||||
;--------------------------------------------------------
|
||||
_convert_strtoint:
|
||||
dec rax
|
||||
mov byte [buffer + rax], 0 ; garante terminador nulo '\0'
|
||||
mov rbx, 10 ; multiplicador (x10)
|
||||
xor rcx, rcx ; contador = 0
|
||||
xor rax, rax ; resultados da conversão
|
||||
|
||||
.digit_loop:
|
||||
mov r8b, byte [buffer + rcx] ; caractere em buf[rcx]
|
||||
cmp r8b, '0' ; caractere < 0x30?
|
||||
jl _done ; se menor, termina
|
||||
cmp r8b, '9' ; caractere > 0x39?
|
||||
jg _done ; se maior, termina
|
||||
sub r8b, 0x30 ; converte de ASCII para numero
|
||||
mul rbx ; rdx:rax = rax * 10 (rbx = 10)
|
||||
add rax, r8 ; armazena dígito em rax
|
||||
inc rcx ; incrementa para receber o próximo byte
|
||||
jmp .digit_loop
|
||||
|
||||
;--------------------------------------------------------
|
||||
; conversão de inteiro para string...
|
||||
; registradores: rax(int), rbx, rcx, r12, r15
|
||||
;--------------------------------------------------------
|
||||
_convert_inttostr:
|
||||
mov rcx, tentativas ; buffer para receber o inteiro
|
||||
mov rbx, 10 ; divisor
|
||||
mov r12, 0 ; contador de dígitos
|
||||
|
||||
.proximo_digito:
|
||||
xor rdx, rdx ; limpa rdx para divisão
|
||||
div rbx ; divide rdx:rax/rbx = rax / 10, resto em rdx
|
||||
add rdx, '0' ; converte o resto(digito) para seu caracter ASCII
|
||||
push rdx ; salva rdx na pilha
|
||||
inc r12 ; incrementa contador de dígitos
|
||||
|
||||
cmp rax, 0 ; verifica se o quociente é zero
|
||||
jnz .proximo_digito ; se não, continua o loop
|
||||
|
||||
.print_str:
|
||||
cmp r12, 0 ; verifica se ainda há digitos para desempilhar
|
||||
jz _str_final ; se não, pula para o final
|
||||
|
||||
pop rax ; desempilha o caractere do dígito em rax
|
||||
mov [rcx], al
|
||||
inc rcx
|
||||
dec r12
|
||||
jmp .print_str
|
||||
|
||||
_str_final:
|
||||
mov rsi, tentativas ; Endereço do buffer com a string
|
||||
mov rdx, rcx ; Endereço do final da string
|
||||
sub rdx, rsi ; Calcula o tamanho da string (final - início)
|
||||
ret
|
||||
|
||||
;--------------------------------------------------------------------
|
||||
; compara o numero digitado que está em 'rax' com o numero gerado
|
||||
; pelo systema 'random' 'r9' ( rax < r9 ?)
|
||||
;--------------------------------------------------------------------
|
||||
_compara:
|
||||
cmp rax, 0 ; se rax == 0, erro
|
||||
je _exit_err ; pula para saida de erro
|
||||
cmp rax, 0x64 ; se maior que 100, erro
|
||||
ja _exit_err ; pula para saida de erro
|
||||
cmp rax, r9 ; compara os numeros
|
||||
je .igual ; se for igual, pula para '.igual'
|
||||
jb .menor ; se for menor pula para '.menor'
|
||||
ja .maior ; se for mais alto pula para '.maior'
|
||||
|
||||
.menor:
|
||||
mov rsi, msg_menor
|
||||
mov rdx, len_msg_menor
|
||||
call _print
|
||||
call _msg_ini
|
||||
|
||||
.maior:
|
||||
mov rsi, msg_maior
|
||||
mov rdx, len_msg_maior
|
||||
call _print
|
||||
call _msg_ini
|
||||
|
||||
.igual:
|
||||
; primeira parte da mensagem...
|
||||
mov rsi, msg_ok_ini
|
||||
mov rdx, len_msg_ok_ini
|
||||
call _print
|
||||
|
||||
; quantidade de tentativas...
|
||||
mov rax, r15 ; copia qtd tentativas para rax
|
||||
mov rsi, tentativas ; buffer de tentativas
|
||||
call _convert_inttostr
|
||||
call _print
|
||||
|
||||
; final da mensagem...
|
||||
mov rsi, msg_ok_end
|
||||
mov rdx, len_msg_ok_end
|
||||
call _print
|
||||
call _exit_ok
|
||||
|
||||
_done:
|
||||
inc r15 ; incrementa contador
|
||||
jmp _compara
|
||||
|
||||
;----------------------------------------------------
|
||||
; Imprime a mensagem na saída padrão STD_OUT FD = 1
|
||||
;----------------------------------------------------
|
||||
_print:
|
||||
mov rax, SYS_WRITE
|
||||
mov rdi, SYS_STDOUT
|
||||
syscall
|
||||
ret
|
||||
|
||||
;----------------------------------------------------
|
||||
; Imprime a mensagem na saída padrão se acertou
|
||||
;----------------------------------------------------
|
||||
;_print_ok:
|
||||
; mov rax, SYS_WRITE
|
||||
; mov rdi, r15
|
||||
; syscall
|
||||
;jmp _exit_ok
|
||||
|
||||
;--------------------------------------------------------
|
||||
; saída em caso de erro...
|
||||
;--------------------------------------------------------
|
||||
_exit_err:
|
||||
mov rsi, msg_uso
|
||||
mov rdx, len_msg_uso
|
||||
call _print
|
||||
mov rax, SYS_EXIT
|
||||
mov rdi, SYS_ERR
|
||||
syscall
|
||||
|
||||
;--------------------------------------------------------
|
||||
; saída em caso de sucesso...
|
||||
;--------------------------------------------------------
|
||||
_exit_ok:
|
||||
mov rax, SYS_EXIT
|
||||
mov rdi, SYS_OK
|
||||
syscall
|
Loading…
Add table
Add a link
Reference in a new issue