flat assembler
Message board for the users of flat assembler.

Index > Main > best/fast way to insert a char

Author
Thread Post new topic Reply to topic
Teehee



Joined: 05 Aug 2009
Posts: 568
Location: Brazil
Teehee
i have a text buffer and i need to insert a char in the current offset.

Code:
the book is on the table.000000000000000000000000000000    


whats the better/faster way to do that?

_________________
Sorry if bad english.
Post 07 Jul 2010, 23:23
View user's profile Send private message Reply with quote
b1528932



Joined: 21 May 2010
Posts: 287
b1528932
mov r/m32,imm8
Post 07 Jul 2010, 23:43
View user's profile Send private message Reply with quote
Tyler



Joined: 19 Nov 2009
Posts: 1216
Location: NC, USA
Tyler
Shift everything after the current offset 1 to the right, then insert the character. The shift could be done by starting at the end and moving blocks of 4. Make sure to access memory on aligned boundaries. I don't know if Windows uses it, but there's an exception for when memory is accessed unaligned.
Post 07 Jul 2010, 23:46
View user's profile Send private message Reply with quote
Teehee



Joined: 05 Aug 2009
Posts: 568
Location: Brazil
Teehee
yep, i'm doing that, here my routine:
Code:
    .insertChar:
        cmp     [cbi.textLength],0 ; if (len == 0 ) do not need to shift
        je      .e

        mov     edi,[cbi.textBase]      ; fist address
        add     edi,[cbi.textLength]    ; go to last address
        mov     esi,edi         
     @@:dec     esi            ; esi = last - 1
        mov     bl, byte[esi]  ; get char (in last - 1)
        mov     byte[edi],bl   ; put char (in last)
        dec     edi            ; dec last
        cmp     esi,[cbi.textOffset]    ; if (is not current offset) loop
        jne     @b
     .e:
        inc     [cbi.textLength]
        mov     edi,[cbi.textOffset]   ; current offset
        stosb                          ; insert
        inc     [cbi.textOffset]    

but it seems too dumb.
Post 07 Jul 2010, 23:51
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Code:
    .insertChar: ; textOffset <= textLength assumed
        mov     ecx, [cbi.textLength]
        mov     edi, [cbi.textOffset]
        sub     ecx, edi
        add     edi, [cbi.textBase]

        test    ecx, ecx
        je      .e

     @@:
        mov     bl, [edi + ecx - 1]
        mov     [edi + ecx], bl
        loop    @b ; or dec ecx/jnz @b for possibly better execution speed

     .e:
        inc     [cbi.textLength]
        stos    byte [edi]

        inc     [cbi.textOffset]    
Or:
Code:
    .insertChar:
        mov     esi, [cbi.textLength]
        mov     ecx, esi
        add     esi, [cbi.textBase]
        lea     edi, [esi + 1]
        sub     ecx, [cbi.textOffset]

        std
rep     movs    byte[edi], byte[esi]
        cld

        inc     [cbi.textLength]
        stos    byte [edi]

        inc     [cbi.textOffset]    
Neither of both is time efficient though.

[edit]Previously I wrongly assumed that the goal was to insert **always** at the beginning of the string. Now I corrected to make the code compatible to original Teehee's code (I hope). The second code, besides of being having the same problem it was not initializing ESI.[/edit]


Last edited by LocoDelAssembly on 08 Jul 2010, 06:20; edited 1 time in total
Post 08 Jul 2010, 01:45
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17348
Location: In your JS exploiting you and your system
revolution
If your buffer is purely linear then you don't have any choice in the matter. You have to move as shown above. Either move the tail up or move the head down.

But if you are prepared to use a different buffer format then you have a myriad of options based upon what operations you need to perform on the buffer.

I expect your question about inserting is just one of the operations you want to perform on the buffer. Perhaps best if you list for yourself all the operations you want to do and then choose a buffer format that would better suits the set of operations you are doing.
Post 08 Jul 2010, 02:50
View user's profile Send private message Visit poster's website Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
That's redundant in our context:
Quote:

Code:
        cld 

        inc     [cbi.textLength] 
        stos    byte [edi] 

        inc     [cbi.textOffset] ;;; What is this for?
    

Post 08 Jul 2010, 05:30
View user's profile Send private message Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
.insertChar can be called with char in AL: STOSB in enough then
Post 08 Jul 2010, 05:32
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
I've fixed my code since I missed somehow what was the real goal (insert in any place of the text, not just the beginning). I haven't tested anything though so it could still be wrong.

edemko, I'm not sure what is redundant, you mean the "byte [edi]" part instead of using plain stosb? I did that for readability reasons (note that stosb and "stos byte[edi]" are both assembled as 0xAA so I'm not incurring in some performance penalty for the "extra" operand).
Post 08 Jul 2010, 06:28
View user's profile Send private message Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
quoted code can be skipped at all, i did not test it too
Post 08 Jul 2010, 09:27
View user's profile Send private message Reply with quote
Teehee



Joined: 05 Aug 2009
Posts: 568
Location: Brazil
Teehee
@LocoDelAssembly: those codes tips are appreciated, thanks.

Revolution wrote:
I expect your question about inserting is just one of the operations you want to perform on the buffer. Perhaps best if you list for yourself all the operations you want to do and then choose a buffer format that would better suits the set of operations you are doing.

What do you mean by buffer format? if it will be linear or arrayed?

in fact, im just trying to develop a code editor (like fasmw, just with some more features). So i need to build a all-text-functionalities component.

@edemko:
Code:
inc     [cbi.textOffset] ;;; What is this for?     

that update the offset to next position, so i insert there the next char. Or all chars will be put in the same position.
Post 08 Jul 2010, 12:34
View user's profile Send private message Reply with quote
edemko



Joined: 18 Jul 2009
Posts: 549
edemko
Code:
format pe gui 4.0
include 'win32ax.inc'
rw equ readable writable

section '' code executable import rw
library kernel32,'kernel32.dll',\
        user32,'user32.dll'
include 'api\kernel32.inc'
include 'api\user32.inc'






        buf      db 255 dup 0
entry $
        mov      edi,buf

        stdcall  loco_wide,edi,00,1,4
        mov      dword[edi],'CDEF'
        invoke   MessageBoxA,0,edi,0,0

        stdcall  loco_wide,edi,04,1,4
        mov      dword[edi],'89AB'
        invoke   MessageBoxA,0,edi,0,0

        stdcall  loco_wide,edi,08,1,4
        mov      dword[edi],'4567'
        invoke   MessageBoxA,0,edi,0,0

        stdcall  loco_wide,edi,12,1,4
        mov      dword[edi],'0123'
        invoke   MessageBoxA,0,edi,0,0


        stdcall  loco_wide,edi,16,2,4
        mov      dword[edi+1],'Loco'
        invoke   MessageBoxA,0,edi,0,0

        stdcall  loco_wide,edi,20,7,3
        mov      word[edi+6],'De'
        mov      byte[edi+8],'l'
        invoke   MessageBoxA,0,edi,0,0

        stdcall  loco_wide,edi,23,11,8
        mov      dword[edi+10],'Asse'
        mov      dword[edi+14],'mbly'
        invoke   MessageBoxA,0,edi,0,0

        ret


proc loco_wide ;src(0..) ,lsrc(0..) ,start(1..) ,count(1..)
        enter   0,0
        pushfd

        push    edi
        mov     edi,[ebp+20]
        sub     edi,1
        jc      .edi        ;count = 0

        push    esi
        mov     esi,[ebp+16]
        sub     esi,1
        jc      .esi        ;start = 0

        push    ecx
        mov     ecx,[ebp+12]
        cmp     esi,ecx
        jae     .ecx        ;start > lsrc

        add     edi,ecx     ;lsrc + count -1
        neg     esi
        xadd    ecx,esi     ;edit: lsrc +1
        dec     esi         ;edit: lsrc -1
        add     edi,[ebp+8] ;extend to src
        add     esi,[ebp+8] ;extend ro src

        std                 ;optimize for...
        rep     movsb       ;...long buffers

.ecx:   pop     ecx
.esi:   pop     esi
.edi:   pop     edi

        popfd
        leave
        ret     16          ;it seems so easy but took 1 hour!
endp
    


Last edited by edemko on 08 Jul 2010, 14:02; edited 1 time in total
Post 08 Jul 2010, 13:47
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17348
Location: In your JS exploiting you and your system
revolution
Teehee wrote:
What do you mean by buffer format? if it will be linear or arrayed?
There are lots of ways to define text buffers. Linear is the simplest to understand but it is slow to work with for many operations.

If searching is a high priority then you can store the text in a simple word based database.

If sorting is a high priority then you can store it in a line-indexed table.

If insertion/deletion is a high priority then you can store it as partial fixed sized chunks (and index those also for some extra speed).

If highlighting/colouring is a high priority then you can store it in a multi-byte layout, or as a shadowed buffer. Maybe even as a run length encoded meta data buffer.

Lots of other choices also. Don't forget to use Google. Wink

Up to you what best suits your purpose.
Post 08 Jul 2010, 13:53
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4240
Location: 2018
edfed
a choise for fast insertion is to provide modificators.

for exemple:
Code:
db 'string where text have to be inserted'
    


if you want to edit text in a continuous way, just create a pointer to a new string.
this pointer to identify the location where to insert the string.

Code:
db 'string where text have to be inserted'
dd 10
db 'THE WORDS TO INSERT'
    

after concatenation of the two strings, you will have the text
Code:
db 'string wheTHE WORDS TO INSERTre text have to be inserted'
    


but combinaison of strings will be made only when an action validate the insertion, for exemple, move the cursor with arrows, clic anywhere else...
loose the focus...
it is a sort of linked list, but very different
Post 08 Jul 2010, 18:19
View user's profile Send private message Visit poster's website Reply with quote
snify



Joined: 02 Dec 2004
Posts: 39
snify
That's my way of doing it

Code:
format PE GUI 4.0
include 'c:\program files\fasm\include\win32a.inc'

start:
        mov edx, STRING
        lea ebx, [edx+POSITION] ;; edx = beginning, ebx = end position
@@:
        inc edx
        cmp byte [edx], 0
        jne @b                  ;; edx = end of string
@@:
        mov al, [edx]
        mov [edx+1], al
        dec edx
        cmp edx, ebx
        jne @b                  ;; loop backwards until it gets end pos

        mov byte [ebx+1], CHAR  ;; replace the char

        invoke  MessageBoxA,0,STRING,0,0
        invoke  ExitProcess,0

        ;; test values
        POSITION = 3
        CHAR = ' '
        STRING db 'ABCDEFG',0,0,0


data import
 library kernel32,'KERNEL32.DLL',\
         user32,'USER32.DLL'

 import kernel32,\
        ExitProcess,'ExitProcess'

 import user32,\
        MessageBoxA,'MessageBoxA'
end data
    
Post 14 Jul 2010, 01:10
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.