rewrite int_to_str

This commit is contained in:
janis 2025-10-28 21:05:16 +01:00
parent 6a6af53667
commit 15c2aea16a
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
2 changed files with 101 additions and 0 deletions

View file

@ -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
View 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());
}
}