radix, negative numbers

This commit is contained in:
janis 2025-10-28 21:18:00 +01:00
parent 15c2aea16a
commit f60573c06f
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
2 changed files with 49 additions and 12 deletions

View file

@ -5,24 +5,32 @@ global int_to_str2
;; rdi: input integer ;; rdi: input integer
;; rsi: pointer to output buffer (at least 21 bytes) ;; rsi: pointer to output buffer (at least 21 bytes)
;; rdx: length of buffer ;; rdx: length of buffer
;; fn int_to_str2(value: i64, buffer: *mut u8, len: usize) -> (*mut u8, usize) ;; cl: radix
;; fn int_to_str2(value: i64, buffer: *mut u8, len: usize, radix: u8) -> (*mut u8, usize)
int_to_str2: int_to_str2:
push rbp push rbp
mov rbp, rsp mov rbp, rsp
push r12 push r12
push r13 push r13
xor r12, r12 ; r12 = index sub rsp, 0x20
mov r13, rdx ; r13 = buffer length mov [rsp], rdi ; save value
mov [rsp + 8], rdx ; save length
mov [rsp + 16], rcx ; save radix
test r13, r13 xor r12, r12 ; r12 = index
test rdx, rdx
jz .epilogue ; if length is 0, return jz .epilogue ; if length is 0, return
xor r13, r13
mov rcx, rdi mov rcx, rdi
sar rcx, 63 ; check sign sar rcx, 63 ; check sign
cmp rcx, 0 cmp rcx, 0
je .convert je .convert
.negative: .negative:
mov byte [rsi], '-' ; write minus sign mov byte [rsi], '-' ; write minus sign
neg rdi
inc r13
inc r12 inc r12
.convert: .convert:
@ -32,14 +40,22 @@ int_to_str2:
jmp .epilogue jmp .epilogue
.convert_loop: .convert_loop:
cmp r12, r13 mov rax, [rsp + 8] ; buffer length
cmp r12, rax
jge .epilogue ; prevent buffer overflow jge .epilogue ; prevent buffer overflow
mov rax, rdi mov rax, rdi
xor rdx, rdx xor rdx, rdx
mov rcx, 10 ; base 10 mov rcx, [rsp + 16] ; base 10
div rcx ; rax = rdi / 10, rdx = rdi % 10 mov cl, cl
div rcx ; rax = rdi / radix, rdx = rdi % radix
cmp rdx, 10
jl .decimal
add rdx, 'a' - 10 ; convert to 'a'-'f'
jmp .phi
.decimal:
add rdx, '0' ; convert digit to ASCII add rdx, '0' ; convert digit to ASCII
.phi:
mov byte [rsi + r12], dl mov byte [rsi + r12], dl
inc r12 inc r12
mov rdi, rax mov rdi, rax
@ -47,7 +63,6 @@ int_to_str2:
jnz .convert_loop jnz .convert_loop
; Reverse the digits ; Reverse the digits
xor r13, r13
mov rdx, r12 mov rdx, r12
dec r12 ; last digit index dec r12 ; last digit index
.reverse_loop: .reverse_loop:
@ -63,6 +78,7 @@ int_to_str2:
.done_reverse: .done_reverse:
mov rax, rsi mov rax, rsi
.epilogue: .epilogue:
add rsp, 0x20
pop r13 pop r13
pop r12 pop r12
pop rbp pop rbp

View file

@ -19,16 +19,37 @@ impl FFISlice {
} }
unsafe extern "C" { unsafe extern "C" {
unsafe fn int_to_str2(value: usize, buffer: *mut u8, buffer_len: usize) -> FFISlice; unsafe fn int_to_str2(value: isize, buffer: *mut u8, buffer_len: usize, radix: u8) -> FFISlice;
} }
fn main() { fn main() {
let value = 1234567890usize; let value = 1234567890isize;
let mut buffer = [0u8; 32]; let mut buffer = [0u8; 32];
unsafe { unsafe {
let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len()); let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len(), 10);
let s = slice.as_str(); let s = slice.as_str();
println!("Integer: {}, String: {}", value, s); println!("Integer: {}, String: {}", value, s);
assert_eq!(s, value.to_string()); assert_eq!(s, format!("{value}"));
let slice = int_to_str2(0 - value, buffer.as_mut_ptr(), buffer.len(), 10);
let s = slice.as_str();
println!("Integer: {}, String: {}", 0 - value, s);
assert_eq!(s, format!("{}", 0 - value));
let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len(), 16);
let s = slice.as_str();
println!("Integer: {:x}, String: {}", value, s);
assert_eq!(s, format!("{value:x}"));
let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len(), 8);
let s = slice.as_str();
println!("Integer: {:o}, String: {}", value, s);
assert_eq!(s, format!("{value:o}"));
let value = 235isize;
let slice = int_to_str2(value, buffer.as_mut_ptr(), buffer.len(), 2);
let s = slice.as_str();
println!("Integer: {:b}, String: {}", value, s);
assert_eq!(s, format!("{value:b}"));
} }
} }