diretórios 8 e 13 de exemplos

This commit is contained in:
Blau Araujo 2025-06-18 09:53:30 -03:00
parent 62338a8185
commit 6fbe5f3a62
13 changed files with 820 additions and 0 deletions

View file

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

View file

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

View file

@ -0,0 +1,14 @@
#include <stdio.h>
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;
}

View file

@ -0,0 +1,27 @@
#include <stdio.h>
#include <limits.h>
#include <float.h>
#include <locale.h>
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;
}

View file

@ -1,141 +0,0 @@
; ----------------------------------------------------------
; Arquivo : salve-pipe.asm
; Reproduz: echo 'Salve, simpatia!' | cat
; Montagem: nasm -f elf64 salve-pipe.asm
; Ligação : ld -o salve-pipe salve-pipe.o
; ----------------------------------------------------------
; Chamadas de sistema...
; ----------------------------------------------------------
%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_WAIT 61
; ----------------------------------------------------------
; Parâmetros de SYS_WAIT...
; ----------------------------------------------------------
%define W_CHILD -1 ; filho de qualquer PID
%define W_STATUS 0 ; ignorar o estado de término (NULL)
%define W_OPTIONS 0 ; sem opções
; ----------------------------------------------------------
; Descritores de arquivos padrão...
; ----------------------------------------------------------
%define STDIN_FD 0
%define STDOUT_FD 1
; ----------------------------------------------------------
; Estados de término...
; ----------------------------------------------------------
%define EXIT_SUCCESS 0
%define EXIT_ERROR 1
; ----------------------------------------------------------
section .rodata
; ----------------------------------------------------------
; Mensagem...
msg db "Salve, simpatia!", 10
len equ $ - msg
; Argumentos de execve...
comm db "/bin/cat", 0
argv dq comm, 0
envp dq 0
; ----------------------------------------------------------
section .bss
; ----------------------------------------------------------
read_end resd 1 ; Descritor da ponta de leitura do pipe
write_end resd 1 ; Descritor da ponta de escrita do pipe
; ----------------------------------------------------------
section .text
; ----------------------------------------------------------
global _start
_start:
; pipe(int pipefd[])
; retorna: pipefd[0] => read_end; pipefd[1] => write_end
mov rax, SYS_PIPE
mov rdi, read_end ; Retorno vai avançar em write_end
syscall
.parada1: ; examinar FDs retornados!
; fork()
mov rax, SYS_FORK
syscall
test rax, rax ; rax = 0 -> processo filho
jz .filho ; pula a execução do código do pai
; ----------------------------------------------------------
; Código executado apenas no processo pai...
; ----------------------------------------------------------
.pai:
; ----------------------------------------------------------
; dup2(write_end, STDOUT)
mov rax, SYS_DUP2
mov edi, [write_end] ; FD original: write_end
mov rsi, STDOUT_FD ; novo descritor de escrita
syscall
; Fechar write_end e read_end...
call _close_all
.parada2: ;examinar /proc/<pid>/fd!
; write(STDOUT, msg, len)
mov rax, SYS_WRITE
mov rdi, STDOUT_FD
mov rsi, msg
mov rdx, len
syscall
; wait4(-1, NULL, 0)
mov rax, SYS_WAIT
mov rdi, W_CHILD
mov rsi, W_STATUS
mov rdx, W_OPTIONS
; exit(0)
mov rax, SYS_EXIT
mov rdi, EXIT_SUCCESS ; sai com sucesso se chegar aqui
syscall
; ----------------------------------------------------------
; Código executado apenas no processo filho...
; ----------------------------------------------------------
.filho:
; ----------------------------------------------------------
; dup2(read_end, STDIN)
mov rax, SYS_DUP2
mov edi, [read_end] ; descritor de leitura no pipe
mov rsi, STDIN_FD ; novo descritor de leitura
syscall
; Fechar write_end e read_end...
call _close_all
; execve("/bin/cat", ["/bin/cat", NULL], [NULL])
mov rax, SYS_EXECVE
mov rdi, comm
mov rsi, argv
mov rdx, envp
syscall
; exit(1)
mov rax, SYS_EXIT
mov rdi, EXIT_ERROR ; sai com erro se execve falhar
syscall
; ----------------------------------------------------------
; Sub de fechamento dos descritores originais do pipe...
; ----------------------------------------------------------
_close_all:
; ----------------------------------------------------------
; close(read_end)
mov rax, SYS_CLOSE
mov rdi, [read_end]
syscall
; close(write_end)
mov rax, SYS_CLOSE
mov rdi, [write_end]
syscall
ret

View file

@ -1,83 +0,0 @@
; ----------------------------------------------------------
; Chamadas de sistema
; ----------------------------------------------------------
%define SYS_READ 0
%define SYS_WRITE 1
%define SYS_EXIT 60
; ----------------------------------------------------------
; Descritores de arquivos padrão
; ----------------------------------------------------------
%define STDIN_FD 0
%define STDOUT_FD 1
; ----------------------------------------------------------
; Estados de término
; ----------------------------------------------------------
%define EXIT_SUCCESS 0
; ----------------------------------------------------------
; Constantes simbólicas
; ----------------------------------------------------------
%define BUF_SIZE 256
; ----------------------------------------------------------
section .rodata
; ----------------------------------------------------------
msg db `Salve, simpatia!\nQual é a sua graça?\n`
msg_len equ $ - msg
resp db "Falaê, "
resp_len equ $ - resp
tail db `!\n`
; ----------------------------------------------------------
section .bss
; ----------------------------------------------------------
buf resb BUF_SIZE ; Buffer de leitura
count resd 1 ; retorno de read (int)
; ----------------------------------------------------------
section .text
; ----------------------------------------------------------
global _start
_start:
; Imprime a mensagem inicial
mov rsi, msg
mov rdx, msg_len
call _print
; Aguarda os dados da entrada padrão
mov rax, SYS_READ
mov rdi, STDIN_FD
mov rsi, buf
mov rdx, BUF_SIZE
syscall
; Salva retorno da chamada (bytes lidos)
mov [count], eax
; Imprime prefixo da resposta
mov rsi, resp
mov rdx, resp_len
call _print
; Imprime resposta
mov rsi, buf
mov rdx, [count] ; total de bytes lidos
dec rdx ; desconta \n
call _print
; Imprime final da resposta
mov rsi, tail
mov rdx, 2 ; !\n = 2 bytes
call _print
; Termina o programa
mov rax, SYS_EXIT
mov rdi, EXIT_SUCCESS
syscall
; ----------------------------------------------------------
; Sub-rotinas...
; ----------------------------------------------------------
_print:
; ----------------------------------------------------------
mov rax, SYS_WRITE
mov rdi, STDOUT_FD
syscall
ret

View file

@ -1,58 +0,0 @@
; Chamadas de sistema...
%define SYS_WRITE 1
%define SYS_OPEN 2
%define SYS_CLOSE 3
%define SYS_DUP2 33
%define SYS_EXIT 60
; Flags da chamada SYS_OPEN...
%define O_WRONLY 0x1 ; apenas para escrita
%define O_CREAT 0x40 ; cria se não existir
%define O_TRUNC 0x200 ; trunca conteúdo existente
; Permissões do arquivo criado...
%define F_MODE 0o644
; Descritores de arquivos...
%define STDOUT 1
section .rodata
file db "mensagem.txt", 0 ; arquivo de destino
msg db "Salve, simpatia!", 10 ; Mensagem
len equ $ - msg ; Tamanho da mensagem
section .text
global _start
_start:
; open (ARQUIVO, FLAGS, MODO)
mov rax, SYS_OPEN
mov rdi, file
mov rsi, O_WRONLY | O_CREAT | O_TRUNC
mov rdx, F_MODE
syscall
mov r12, rax ; salvar descritor de arquivo retornado
; dup2(ANTIGO_FD, NOVO_FD)
mov rax, SYS_DUP2
mov rdi, r12
mov rsi, STDOUT
syscall
; write(FD, STRING, SIZE)
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rsi, msg
mov rdx, len
syscall
; close(FD)
mov rax, SYS_CLOSE
mov rdi, r12
syscall
; exit(STATUS)
mov rax, SYS_EXIT
xor rdi, rdi
syscall

View file

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

129
curso/exemplos/08/uint.asm Normal file
View file

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

51
curso/exemplos/08/uint.c Normal file
View file

@ -0,0 +1,51 @@
/*
* Arquivo : uint.c
* Compilação: gcc -Wall uint.c -o uintc
*/
#include <stdio.h>
#include <limits.h> // 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;
}