parsing numbers

This commit is contained in:
janis 2025-10-28 21:43:23 +01:00
parent f60573c06f
commit edc4f4e576
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
2 changed files with 92 additions and 0 deletions

View file

@ -1,6 +1,73 @@
section .text section .text
global int_to_str global int_to_str
global int_to_str2 global int_to_str2
global str_to_int
;; rdi: pointer to input string
;; rsi: length of input string
;; dl: radix
;; fn str_to_int(s: *const u8, len: usize, radix: u8) -> i64
str_to_int:
push rbp
mov rbp, rsp
push r12
push r13
sub rsp, 0x10
mov qword [rsp], 0 ; result = 0
mov [rsp + 8], dl ; multiplier = radix
xor r12, r12 ; r12 = index
.loop:
cmp r12, rsi
jge .epilogue
mov rax, [rsp]
movzx rcx, byte [rsp + 8]
xor rdx, rdx
imul rcx
jo .overflow ; overflow
mov [rsp], rax
mov al, byte [rdi + r12]
cmp al, '_'
je .skip_underscore
cmp al, '9'
ja .check_alpha
cmp al, '0'
jb .not_a_digit
sub al, '0'
jmp .digit_parsed
.check_alpha:
cmp al, 'a'
jb .not_a_digit
cmp al, 'f'
ja .not_a_digit
sub al, 'a' - 10
jmp .digit_parsed
.digit_parsed:
cmp al, byte [rsp + 8]
ja .not_a_digit
movzx rax, al
add [rsp], rax
.skip_underscore:
inc r12
jmp .loop
.not_a_digit:
mov qword [rsp], 0
jmp .epilogue
.overflow:
mov rax, -1
shr rax, 1
mov qword [rsp], rax
.epilogue:
mov rax, [rsp]
add rsp, 0x10
pop r13
pop r12
pop rbp
ret
;; rdi: input integer ;; rdi: input integer
;; rsi: pointer to output buffer (at least 21 bytes) ;; rsi: pointer to output buffer (at least 21 bytes)

View file

@ -20,6 +20,7 @@ impl FFISlice {
unsafe extern "C" { unsafe extern "C" {
unsafe fn int_to_str2(value: isize, buffer: *mut u8, buffer_len: usize, radix: u8) -> FFISlice; unsafe fn int_to_str2(value: isize, buffer: *mut u8, buffer_len: usize, radix: u8) -> FFISlice;
unsafe fn str_to_int(s: *const u8, len: usize, radix: u8) -> isize;
} }
fn main() { fn main() {
@ -51,5 +52,29 @@ fn main() {
let s = slice.as_str(); let s = slice.as_str();
println!("Integer: {:b}, String: {}", value, s); println!("Integer: {:b}, String: {}", value, s);
assert_eq!(s, format!("{value:b}")); assert_eq!(s, format!("{value:b}"));
let s = "1234567890";
let parsed = str_to_int(s.as_ptr(), s.len(), 10);
println!("String: {}, Integer: {}", s, parsed);
assert_eq!(parsed, 1234567890isize);
let s = "499602d2";
let parsed = str_to_int(s.as_ptr(), s.len(), 16);
println!("String: {}, Integer: {}", s, parsed);
assert_eq!(parsed, 1234567890isize);
let s = "11145401322";
let parsed = str_to_int(s.as_ptr(), s.len(), 8);
println!("String: {}, Integer: {}", s, parsed);
assert_eq!(parsed, 1234567890isize);
let s = "11101011";
let parsed = str_to_int(s.as_ptr(), s.len(), 2);
println!("String: {}, Integer: {}", s, parsed);
assert_eq!(parsed, 235isize);
let s = "9999999999999999999999999999999999999999";
let parsed = str_to_int(s.as_ptr(), s.len(), 10);
println!("String: {}, Integer: {}", s, parsed);
assert_eq!(parsed, isize::MAX);
} }
} }