mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
171 lines
2.5 KiB
Plaintext
171 lines
2.5 KiB
Plaintext
; The OS/K Team licenses this file to you under the MIT license.
|
|
; See the LICENSE file in the project root for more information.
|
|
|
|
;
|
|
; int strtol(const char *str, int base)
|
|
;
|
|
; rax = integer extracted from str
|
|
; rdx = pointer to first invalid byte
|
|
;
|
|
strtol:
|
|
mov ax2, 1
|
|
jmp strtoq
|
|
|
|
;
|
|
; int strtoul(const char *str, int base)
|
|
;
|
|
; rax = integer extracted from str
|
|
; rdx = pointer to first invalid byte
|
|
;
|
|
strtoul:
|
|
sub ax2, ax2
|
|
jmp strtoq
|
|
|
|
;
|
|
; int strtoq(const char *str, int base, bool signed)
|
|
;
|
|
; guesses base when 'base'=0
|
|
;
|
|
strtoq:
|
|
xor rax, rax
|
|
mov rdx, ax0
|
|
|
|
; make sure base is in [2, 32]
|
|
cmp ax1, 1
|
|
j.z .bad
|
|
cmp ax1, 36
|
|
j.a .bad
|
|
|
|
; empty string?
|
|
cmp b[rdx], 0
|
|
jmp.z .done
|
|
|
|
.skip_spc:
|
|
cmp b[rdx], ' '
|
|
inc.z rdx
|
|
jmp.z .skip_spc
|
|
|
|
; skip +
|
|
cmp b[rdx], '+'
|
|
inc.z rdx
|
|
|
|
; signed?
|
|
test ax2, ax2
|
|
sub.z lx1, lx1
|
|
jmp.z .unsigned
|
|
|
|
; parse '-'
|
|
cmp b[rdx], '-'
|
|
inc.z rdx
|
|
mov.z lx1, 1
|
|
sub.nz lx1, lx1
|
|
|
|
.unsigned:
|
|
; base 0
|
|
test ax1, ax1
|
|
jmp.z .base_0
|
|
|
|
; base prefix?
|
|
cmp b[rdx], '0'
|
|
jmp.nz .main_loop
|
|
|
|
inc rdx
|
|
|
|
; string is "0"
|
|
cmp b[rdx], 0
|
|
jmp.z .done
|
|
|
|
; "0x" prefix
|
|
cmp b[rdx], 'x'
|
|
jmp.z .parsed_0x
|
|
|
|
; "0b" prefix
|
|
cmp b[rdx], 'b'
|
|
jmp.z .parsed_0b
|
|
|
|
; may be octal, but we don't care
|
|
; we accept "0110101010" (binary) for instance
|
|
jmp .main_loop
|
|
|
|
.parsed_0x:
|
|
; are we in base 16?
|
|
; if not, leave rax = 0 and *rdx = 'x'
|
|
cmp ax1, 16
|
|
jmp.nz .done
|
|
; else
|
|
inc rdx
|
|
jmp .main_loop
|
|
|
|
.parsed_0b:
|
|
; are we in base 2?
|
|
; if not, leave rax = 0 and *rdx = 'b'
|
|
cmp ax1, 2
|
|
jmp.nz .done
|
|
; else
|
|
inc rdx
|
|
jmp .main_loop
|
|
|
|
.base_0:
|
|
; guess base
|
|
|
|
cmp b[rdx], '0'
|
|
mov.nz ax1, 10
|
|
jmp.nz .main_loop
|
|
inc rdx
|
|
|
|
cmp b[rdx], 'x'
|
|
inc.z rdx
|
|
mov.z ax1, 16
|
|
jmp.z .main_loop
|
|
|
|
cmp b[rdx], 'b'
|
|
inc.z rdx
|
|
mov.z ax1, 2
|
|
jmp.z .main_loop
|
|
|
|
mov ax1, 8
|
|
|
|
.main_loop:
|
|
mov lx0, b[rdx]
|
|
inc rdx
|
|
|
|
cmp lx0, '0'
|
|
jmp.b .done
|
|
cmp.ae lx0, '9'
|
|
sub.be lx0, '0'
|
|
jmp.be .next
|
|
|
|
cmp lx0, 'A'
|
|
cmp.ae lx0, 'Z'
|
|
sub.be lx0, 55 ; 'A' - 10
|
|
jmp.be .next
|
|
|
|
cmp lx0, 'a'
|
|
jmp.b .next
|
|
cmp.ae lx0, 'z'
|
|
sub.be lx0, 87 ; 'a' - 10
|
|
jmp.be .next
|
|
|
|
.next:
|
|
; too large for base?
|
|
cmp lx0, ax1
|
|
jmp.ae .done
|
|
|
|
mul rax, ax1
|
|
add rax, lx0
|
|
jmp .main_loop
|
|
|
|
.done:
|
|
; negative?
|
|
test lx1, lx1
|
|
ret.z
|
|
|
|
; yes
|
|
neg rax
|
|
ret
|
|
|
|
.bad:
|
|
mov q[errno], EINVAL
|
|
ret
|
|
|