rewrite int_to_str
This commit is contained in:
parent
6a6af53667
commit
15c2aea16a
|
|
@ -1,5 +1,72 @@
|
||||||
section .text
|
section .text
|
||||||
global int_to_str
|
global int_to_str
|
||||||
|
global int_to_str2
|
||||||
|
|
||||||
|
;; rdi: input integer
|
||||||
|
;; rsi: pointer to output buffer (at least 21 bytes)
|
||||||
|
;; rdx: length of buffer
|
||||||
|
;; fn int_to_str2(value: i64, buffer: *mut u8, len: usize) -> (*mut u8, usize)
|
||||||
|
int_to_str2:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
push r12
|
||||||
|
push r13
|
||||||
|
xor r12, r12 ; r12 = index
|
||||||
|
mov r13, rdx ; r13 = buffer length
|
||||||
|
|
||||||
|
test r13, r13
|
||||||
|
jz .epilogue ; if length is 0, return
|
||||||
|
|
||||||
|
mov rcx, rdi
|
||||||
|
sar rcx, 63 ; check sign
|
||||||
|
cmp rcx, 0
|
||||||
|
je .convert
|
||||||
|
.negative:
|
||||||
|
mov byte [rsi], '-' ; write minus sign
|
||||||
|
inc r12
|
||||||
|
|
||||||
|
.convert:
|
||||||
|
test rdi, rdi
|
||||||
|
jnz .convert_loop
|
||||||
|
mov byte [rsi + r12], '0'
|
||||||
|
jmp .epilogue
|
||||||
|
|
||||||
|
.convert_loop:
|
||||||
|
cmp r12, r13
|
||||||
|
jge .epilogue ; prevent buffer overflow
|
||||||
|
|
||||||
|
mov rax, rdi
|
||||||
|
xor rdx, rdx
|
||||||
|
mov rcx, 10 ; base 10
|
||||||
|
div rcx ; rax = rdi / 10, rdx = rdi % 10
|
||||||
|
add rdx, '0' ; convert digit to ASCII
|
||||||
|
mov byte [rsi + r12], dl
|
||||||
|
inc r12
|
||||||
|
mov rdi, rax
|
||||||
|
test rdi, rdi
|
||||||
|
jnz .convert_loop
|
||||||
|
|
||||||
|
; Reverse the digits
|
||||||
|
xor r13, r13
|
||||||
|
mov rdx, r12
|
||||||
|
dec r12 ; last digit index
|
||||||
|
.reverse_loop:
|
||||||
|
cmp r13, r12
|
||||||
|
jae .done_reverse
|
||||||
|
mov al, [rsi + r13]
|
||||||
|
mov bl, [rsi + r12]
|
||||||
|
mov [rsi + r13], bl
|
||||||
|
mov [rsi + r12], al
|
||||||
|
inc r13
|
||||||
|
dec r12
|
||||||
|
jmp .reverse_loop
|
||||||
|
.done_reverse:
|
||||||
|
mov rax, rsi
|
||||||
|
.epilogue:
|
||||||
|
pop r13
|
||||||
|
pop r12
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
;; Converts integer in rcx to string at rdx
|
;; Converts integer in rcx to string at rdx
|
||||||
;; rcx: input integer
|
;; rcx: input integer
|
||||||
|
|
|
||||||
34
lang/tests/int_to_str.rs
Normal file
34
lang/tests/int_to_str.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn panic() -> ! {
|
||||||
|
panic!("Called panic from external code.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct FFISlice {
|
||||||
|
ptr: *const u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FFISlice {
|
||||||
|
fn as_slice(&self) -> &[u8] {
|
||||||
|
unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
|
||||||
|
}
|
||||||
|
fn as_str(&self) -> &str {
|
||||||
|
unsafe { core::str::from_utf8_unchecked(self.as_slice()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
unsafe fn int_to_str2(value: usize, buffer: *mut u8, buffer_len: usize) -> FFISlice;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let value = 1234567890usize;
|
||||||
|
let mut buffer = [0u8; 32];
|
||||||
|
unsafe {
|
||||||
|
let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len());
|
||||||
|
let s = slice.as_str();
|
||||||
|
println!("Integer: {}, String: {}", value, s);
|
||||||
|
assert_eq!(s, value.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue