76 lines
2.6 KiB
Text
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
|