pbn/curso/exemplos/08/#sint.asm#

76 lines
2.6 KiB
Text

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