parsing numbers
This commit is contained in:
parent
f60573c06f
commit
edc4f4e576
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue