NO

Author Topic: RightTrim function  (Read 757 times)

Offline Vortex

  • Member
  • *
  • Posts: 528
    • http://www.vortex.masmcode.com
RightTrim function
« on: April 28, 2019, 11:50:39 am »
RightTrim function to remove the trailing TAB and SPACE characters from a string :

Code: [Select]
.386
.model flat,stdcall
option casemap:none

StrLen PROTO :DWORD

.data

ltable db 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

.code

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

RightTrim PROC _str:DWORD

    mov     eax,DWORD PTR [esp+4]
    invoke  StrLen,eax
    add     eax,DWORD PTR [esp+4]
    mov     ecx,OFFSET ltable
@@:
    sub     eax,1
    movzx   edx,BYTE PTR [eax]
    cmp     BYTE PTR [ecx+edx],1
    je      @b
@@:
    add     eax,1
    mov     BYTE PTR [eax],0
    mov     eax,DWORD PTR [esp+4]
    retn    4

RightTrim ENDP

OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF

END
Code it... That's all...

Offline Grincheux

  • Member
  • *
  • Posts: 36
  • Never be pleased, always improve
    • Arachne
Re: RightTrim function
« Reply #1 on: January 03, 2020, 09:14:39 am »
And the same for X64?
-------------------------
Kenavo

Offline Vortex

  • Member
  • *
  • Posts: 528
    • http://www.vortex.masmcode.com
Re: RightTrim function
« Reply #2 on: January 04, 2020, 07:36:32 pm »
Hi Grincheux,

Here is the 64-bit version :

Code: [Select]
.model flat,fastcall
option casemap:none

lstrlenA PROTO :QWORD
lstrlen EQU <lstrlenA>

.data

ltable db 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
       db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

.code

RightTrim PROC _str:DWORD PARMAREA=1*QWORD

LOCAL _rcx:QWORD

    mov     _rcx,rcx
    invoke  lstrlen,rcx
    add     rax,_rcx
    mov     r8,1
    mov     rcx,OFFSET ltable
@@:
    sub     rax,r8
    movzx   rdx,BYTE PTR [rax]
    cmp     BYTE PTR [rcx+rdx],r8b
    je      @b
@@:
    add     rax,r8
    mov     BYTE PTR [rax],0
    mov     rax,_rcx
    ret

RightTrim ENDP

Testing the function :

Code: [Select]
.model flat,fastcall
option casemap:none

includelib  kernel32.lib
includelib  user32.lib
includelib  msvcrt.lib

ExitProcess PROTO :QWORD
RightTrim   PROTO :QWORD
printf      PROTO :QWORD,:VARARG
lstrlenA    PROTO :QWORD

lstrlen EQU <lstrlenA>

.data

teststr     db 'This is a test.        ',0
msg         db 'Length of the string = %u',0

.code

start:

    sub     rsp,8+4*8
   
    invoke  RightTrim,ADDR teststr
           
    invoke  lstrlen,rax
    invoke  printf,ADDR msg,rax
   
    invoke  ExitProcess,0

END start
Code it... That's all...

Offline Grincheux

  • Member
  • *
  • Posts: 36
  • Never be pleased, always improve
    • Arachne
Re: RightTrim function
« Reply #3 on: January 05, 2020, 06:35:51 am »
Thank You Vortex. I take, it is better than mine. ;)
-------------------------
Kenavo

Offline Grincheux

  • Member
  • *
  • Posts: 36
  • Never be pleased, always improve
    • Arachne
Re: RightTrim function
« Reply #4 on: January 05, 2020, 06:48:25 am »
Why do you return a pointer on lTable?
lTable could be got by using VirtualAlloc.

The resulting string cannot be longer than the one passed as an argument.
It can only be shorter or the same size.
So why not use lstrcpy?
The string argument is limited to 256 bytes!
If the string is longer than 256 the function must be called like this RightTrim(&_szString[lstrlen(_szString) - 256]) ;
-------------------------
Kenavo

Offline Vortex

  • Member
  • *
  • Posts: 528
    • http://www.vortex.masmcode.com
Re: RightTrim function
« Reply #5 on: January 05, 2020, 02:13:13 pm »
Hi Grincheux,

Quote
Why do you return a pointer on lTable?
lTable could be got by using VirtualAlloc.

ltable is a lookup table and VirtualAlloc would require you to initialize the empty memory buffer : you would need to set the TAB 9 and SPACE 32 characters. A ready string in the .data section can be effective if you call multiple times the same RightTrim function : No need to allocate and deallocate memory portions for every function call. I don't tell that VirtualAlloc is wrong. It's probably a matter of programming choice.

Quote
The resulting string cannot be longer than the one passed as an argument.
It can only be shorter or the same size.
So why not use lstrcpy?
The string argument is limited to 256 bytes!
If the string is longer than 256 the function must be called like this RightTrim(&_szString[lstrlen(_szString) - 256]) ;

The size of the ASCII table ( the lookup table )  is 256 bytes but this should not guide you to the conclusion that the target string to trim should have a maximum size of of 256. It's the range of ASCII codes falling to this limitation, not the size of the string to be trimmed. Here is an example :

Code: [Select]
#include <stdio.h>
#include <windows.h>

extern char* RightTrim(char *);

char teststr[]="This is a long string to test the function RightTrim. The string includes a lot space and TAB characters.                                                                                                                                                           ";

int __cdecl main(int argc,char *argv[])
{
printf("The initial length of the string = %u\n",lstrlen(teststr));

printf("The length of the string after calling RightTrim  = %u\n",lstrlen(RightTrim(teststr)));

return 0;
}

Running the 64-bit test application built with Pelles C V8 :

Code: [Select]
The initial length of the string = 300
The length of the string after calling RightTrim  = 105

Notice that you need to be careful while inserting very long strings to your Pelles C code. My string is declared as global and it's placed directly to the .data section. If the compiler moves the long string to the .const section, the RightTrim function cannot insert the NULL character trimming the string. You can check this by disassembling RightTrimTest.obj with Agner Fog's objconv tool.
« Last Edit: January 05, 2020, 02:20:16 pm by Vortex »
Code it... That's all...

Offline Grincheux

  • Member
  • *
  • Posts: 36
  • Never be pleased, always improve
    • Arachne
Re: RightTrim function
« Reply #6 on: January 05, 2020, 06:37:21 pm »
Thank You Professor. :)
-------------------------
Kenavo