130 lines
6.1 KiB
NASM
130 lines
6.1 KiB
NASM
|
; ----------------------------------------------------------
|
||
|
; 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
|