mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
168 lines
2.5 KiB
Plaintext
168 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)
|
|
;
|
|
; eax = integer extracted from str
|
|
; edx = pointer to first invalid byte
|
|
;
|
|
strtol:
|
|
mov ax2, 1
|
|
jmp strtoq
|
|
|
|
;
|
|
; int strtoul(const char *str, int base)
|
|
;
|
|
; eax = integer extracted from str
|
|
; edx = pointer to first invalid byte
|
|
;
|
|
strtoul:
|
|
nul ax2
|
|
jmp strtoq
|
|
|
|
;
|
|
; int strtoq(const char *str, int base, bool signed)
|
|
;
|
|
; guesses base when 'base'=0
|
|
;
|
|
strtoq:
|
|
nul eax, esi
|
|
mov edx, ax0
|
|
|
|
; make sure base is in [2, 32]
|
|
beq ax1, 1, .bad
|
|
bltu 36, ax1, .bad
|
|
|
|
; empty string?
|
|
bzr b[edx], .done
|
|
|
|
.skip_spc:
|
|
bne b[edx], ' ', .no_spc
|
|
inc edx
|
|
jmp .skip_spc
|
|
|
|
.no_spc:
|
|
; skip +
|
|
bne b[edx], '+', .no_plus
|
|
inc edx
|
|
|
|
.no_plus:
|
|
; unsigned?
|
|
bzr ax2, .unsigned
|
|
|
|
; parse '-'
|
|
bne b[edx], '-', .unsigned
|
|
inc edx
|
|
mov esi, 1
|
|
|
|
.unsigned:
|
|
; base 0
|
|
bzr ax1, .base_0
|
|
|
|
; base prefix?
|
|
bne b[edx], '0', .main_loop
|
|
|
|
inc edx
|
|
movzx ecx, b[edx]
|
|
|
|
; "0x"/"0b" prefix
|
|
jecxz .done ; "0"
|
|
beq ecx, 'x', .parsed_0x
|
|
beq ecx, 'b', .parsed_0b
|
|
|
|
; may be octal, but we don't care
|
|
; we accept "0110101010" (despite base=2) for instance
|
|
jmp .main_loop
|
|
|
|
.parsed_0x:
|
|
; are we in base 16?
|
|
; if not, leave eax = 0 and *edx = 'x'
|
|
bne ax1, 16, .done
|
|
; else
|
|
inc edx
|
|
jmp .main_loop
|
|
|
|
.parsed_0b:
|
|
; are we in base 2?
|
|
; if not, leave eax = 0 and *edx = 'b'
|
|
bne ax1, 2, .done
|
|
; else
|
|
inc edx
|
|
jmp .main_loop
|
|
|
|
.base_0:
|
|
; guess base
|
|
|
|
beq b[edx], '0', .b0_not10
|
|
|
|
; must be base 10
|
|
mov ax1, 10
|
|
jmp .main_loop
|
|
|
|
.b0_not10:
|
|
inc edx
|
|
|
|
bne b[edx], 'x', .b0_not16
|
|
inc edx
|
|
mov ax1, 16
|
|
jmp .main_loop
|
|
|
|
.b0_not16:
|
|
bne b[edx], 'b', .b0_not2
|
|
inc edx
|
|
mov ax1, 2
|
|
jmp .main_loop
|
|
|
|
.b0_not2:
|
|
; take octal by default
|
|
mov ax1, 8
|
|
|
|
.main_loop:
|
|
movzx ecx, b[edx]
|
|
inc edx
|
|
|
|
; between 0 and 9?
|
|
bltu ecx, '0', .done
|
|
bltu '9', ecx, .not_digit10
|
|
|
|
; yes
|
|
sub ecx, '0'
|
|
jmp .next
|
|
|
|
.not_digit10:
|
|
bltu ecx, 'A', .done
|
|
bltu 'Z', ecx, .not_digitAZ
|
|
|
|
sub ecx, 55 ; 'A' - 10
|
|
jmp .next
|
|
|
|
.not_digitAZ:
|
|
bltu ecx, 'a', .done
|
|
bltu 'z', ecx, .done
|
|
|
|
sub ecx, 87 ; 'a' - 10
|
|
jmp .next
|
|
|
|
.next:
|
|
; too large for base?
|
|
blteu ax1, ecx, .done
|
|
|
|
mul eax, ax1
|
|
add eax, ecx
|
|
jmp .main_loop
|
|
|
|
.done:
|
|
; negative?
|
|
bzr esi, .r
|
|
|
|
; yes
|
|
neg eax
|
|
|
|
.r:
|
|
ret
|
|
|
|
.bad:
|
|
ret
|
|
|