As Peter Cordes mentioned in the comments, you can always add a null terminator (0
) into the existing string's buffer to right truncate; if you don't mind modifying the original string data.
The example below will retrieve a substring without modifying the original string.
If you have the address of a variable, and you know where you want to truncate it, you can take the address of the starting position of the data, and add an offset to left truncate. To right truncate you can just read as many characters as you need from the new offset.
For example in x86
:
msg db '29ak49' ; create a string (1 byte per char)
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
movzx eax, byte [esi] ; get the value of the next character
;; do something with the character in eax
inc esi
dec edi
jnz .loop
;; end loop
EDIT:
The following is a runable test implementation as a 32-bit Linux application that prints out the substring selected based on OFFSET_INTO_DATA
and NUM_CHARS
(note: the algorithm is the same, but the registers have changed):
section .text
global _start
_start:
;; left truncate
mov esi, msg ; get the address of the start of the string
add esi, OFFSET_INTO_DATA ; offset into the string (1 byte per char)
;; right truncate
mov edi, NUM_CHARS ; number of characters to take
.loop:
mov ecx, esi ; get the address of the next character
call print_char_32
inc esi
dec edi
jnz .loop
jmp halt
;;; input: ecx -> character to display
print_char_32:
mov edx, 1 ; PRINT
mov ebx, 1 ;
mov eax, 4 ;
int 0x80 ;
ret
halt:
mov eax, 1 ; EXIT
int 0x80 ;
jmp halt
section .data
msg db '29ak49' ; create a string (1 byte per char)
OFFSET_INTO_DATA EQU 1
NUM_CHARS EQU 3
Compiled with:
nasm -f elf substring.asm ; ld -m elf_i386 -s -o substring substring.o