Pelles C forum
Assembly language => Assembly discussions => Topic started by: Vortex on April 28, 2019, 11:50:39 AM
-
RightTrim function to remove the trailing TAB and SPACE characters from a string :
.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
-
And the same for X64?
-
Hi Grincheux,
Here is the 64-bit version :
.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 :
.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
-
Thank You Vortex. I take, it is better than mine. ;)
-
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]) ;
-
Hi Grincheux,
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.
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 :
#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 :
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.
-
Thank You Professor. :)