this tutorial was based on a tutorial downloaded from www.alloces.cjb.net
Thanks vit$oft , Donkey , Rotivc , and all the others for helping ! its steel open !

- - - - - - - - - - - - - - - - - - - - -
String ASSEMBLY tutorial
NASM Syntax by Nguga
- - - - - - - - - - - - - - - - - - - - -

Five commands to copy , move and scan strings
=============================================

this for byte
- - - - - - -

LODSB Load Byte string
STOSB Write Byte string
MOVSB Move Byte string
SCASB Scan Byte string for e.g. characters
CMPSB Compare Byte two strings with each other

this for word
- - - - - - -

LODSW Load Word string
STOSW Write Word string
MOVSW Move Word string
SCASW Scan Word string for e.g. characters
CMPSW Compare Word two strings with each other


this for dword
- - - - - - -

LODSD Load Dword string
STOSD Write Dword string
MOVSD Move Dword string
SCASD Scan Dword string for e.g. characters
CMPSD Compare Dword two strings with each other


Rules
=============================================

- Source String must be loaded on ESI register

- Destination String is loaded on EDI register

- Registers ESI and EDI are incremented or
decremented automatically during execution
of string commands

- When we repeat string commands , then the
ECX register is used as a counter


- If we want to go from right to left on the String

we have to set the direction flag to 1 ( DF=1 )
and the assembler instruction to do that is:

STD ;===> set direction flag to 1 (DF=1)




- if we want to go from left to right of the String

we must set the direction flag to 0 ( DF=0 )
and the assembler instruction to do that is:

CLD ;===> set direction flag to 0 (DF=0)




- REP INSx/OUTSx does not change DX register (data go repeatedly from/to the same I/O port)

- When a string instruction is used without REPx prex, (E)CX register does not change.

- Even when REPx prefix is not used, (E)SI,(E)DI registers are changed.

- LODSX, STOSx, MOVSx, INSx, OUTSx never change flags.

- SCASx, CMPSx do set flags corresponding to the last B/W/D scanned, compared.

- LODSx may be used with REPx prefix but it is useless.










LOADSB or LOADSW or LOADSD ( loads in EAX )
===============================================

- loads EAX with the String in ESI

- then after this instruction The ESI register is incremented
or decremented depending of the state of the direction flag.
is incremented or decremented by Byte or Word depending on
the instruction we use LOADSB ( byte ) or LOADSW ( word )


Litle Example
- - - - - - - -

A string will be scaned until there is a ","
or the end of string is reached.




%include "\lab\vasm\inc\nagoa.inc"




..start:

section data
String db "K2?34",0
String_lenght equ $-String ; lenght of string
section code

mov ecx,String_lenght ; lenght of the string to to ecx (counter)
mov esi,String ; ESI points to first element ("K") in the string
cld ; lets go from left to right :)

stringloop:
LODSB ; load EAX with the first element of the String
cmp al,"?" ; since we used a byte we compare with lower part of eax ( al )
loopne stringloop ; loop if not equal limit of the loop is = ecx
cmp al,"?"
jne .out_
call MessageBoxA ,NULL,"works !","msg",MB_OK
xor eax,eax
ret
.out_
call MessageBoxA ,NULL,"no bad !","msg",MB_OK
xor eax,eax
ret












STOSB or STOSW or STOSD ( loads in EDI )
===============================================

- copy the content of EAX to EDI
a byte STOSB or a word STOSW


mov ecx , String_lenght ; will loop String_lenght times

mov esi ,String ; ESI is pointing to first element of the string

lodsb ;take one character from the source on esi to eax
stosb ;and copy it from eax to edi
loop ourloop ;loop until ecx > 0

















MOVSB or MOVSW or MOVSD ( move string )
=========================================

- move the contents of ESI to EDI




Litle Example
- - - - - - - -

- A string is copied bitwise


%include "\lab\vasm\inc\nagoa.inc"




..start:
section data

Quelle db "The string that will be copied!",0
Quelle_1 equ $-Quelle
Ziel resb Quelle_1 ;the destination buffer

section code

mov esi,Quelle ;save the address of Quelle in esi
mov edi,Ziel ;save the address of Ziel in edi
mov ecx,Quelle_1
cld ;from left to right

copy:
movsb ;Quelle ---> Ziel
loop copy

cmp esi,Ziel
jne .out_
call MessageBoxA , NULL,esi,"ESI -> Ziel !",MB_OK
xor eax,eax
ret

.out_
call MessageBoxA , NULL,esi,"ESI not Ziel :( ...",MB_OK
xor eax,eax
ret








REP instruction ( Similar to LOOP )
==============================================

- with REP command the instruction is repeated
until the counter ECX is zero .
(the loop is not executed when ECX=0 )

- after every execution of REP the ecx register is
decremented by 1

- REP variants
-----------
- REPE repeat while Equal
- REPNE repeat while Not Equal

( REP commands works more quickly than the LOOP command )



Example
-------


mov ecx,String_Lenght ; will loop String_Lenght times = ecx
rep movsb ; movsb will be executed until ecx=0







- several variants for REP



SCASB or SCASW or SCASD ( scan strings )
===============================================


- compare the content of EAX with the content of EDI

- Internally the content of EAX is subtratcted from the content
of EDI but the result isn't saved.

- The EDI register is incremented or decremented after every SCAS command




Litle Example
--------------

- The content of a string is scaned until there is
a "z" or the end of the string is reached.



%include "\lab\vasm\inc\nagoa.inc"



code32

..start:

section data

string1 db "abczdef",0
string1_1 equ $-string1 ;length of string1
caracter db "z",0

section code

mov edi,string1 ; edi is pointing to "a"
mov al,"z"
mov ecx,string1_1 ; number of loops to do in ecx
cld ; go from from left to right
repne scasb ; scan string in edi if not equal
je caracter_found ; is caracter "z" ? if so stop if not go if ecx not 0


call MessageBoxA , NULL,"caracter ?z? NOT found ! ",edi,MB_OK
xor eax,eax
ret

caracter_found:
call MessageBoxA , NULL," caracter ?z? found !",edi,MB_OK
xor eax,eax
ret






CMPSB or CMPSW or CMPSD ( COMPARE STRING )
======================================

- compare the content of ESI with EDI

- The result of the comparison is saved in the
status register .





Litle Example
--------------

- Two strings are compared to equality




%include "\lab\vasm\inc\nagoa.inc"





..start:

section data

String1 db "ola meu",0
String2 db "ola meu",0
StringSize equ $-String2 ;length of String

section code

mov esi,String1
mov edi,String2
mov ecx,StringSize+1
cld ; from left to right ...
repe cmpsb
or ecx,ecx
jnz notcorrect
call MessageBoxA , NULL,"yes string are equal !","msg",MB_OK
xor eax,eax
ret

notcorrect:
call MessageBoxA , NULL,"string are NOT equal !","msg",MB_OK
xor eax,eax
ret













=============================================



just an example not using this INSTRUCTIONS :)



%include "\lab\vasm\inc\nagoa.inc"



..start:


section data
password db "ola amigo",0
user_pass db "ola amigo",0
user_pass_1 equ $ - user_pass -1 ; lenght user_pass
section code


cmpString:
push ecx
push ebx
push edi
push esi

mov ecx,user_pass_1
mov eax,password
mov ebx,user_pass

.good_caracter_go_next
xor edi,edi
xor esi,esi
mov edi,
mov esi,
cmp di,si
je .increment_decrement_stuff
jmp .BadBoy
.increment_decrement_stuff
inc eax
inc ebx
dec ecx
cmp ecx,0
je .GoodBoy
jmp .good_caracter_go_next



.BadBoy
call MessageBoxA , NULL,"BAD BOY !!! ","INFO",MB_OK
jmp .out_

.GoodBoy

call MessageBoxA , NULL,"GOOD BOY !!! ","INFO",MB_OK

.out_
pop esi
pop edi
pop ebx
pop ecx
xor eax,eax
ret

=============================================
Posted on 2004-02-24 07:25:07 by Nguga
please feel free to improve this tutorial in case any errors or to add more info :)
Posted on 2004-02-24 07:26:57 by Nguga
Take a look at http://www.asmcommunity.net/board/phpwiki/index.php/AllAboutStrings

Ye,s Alloces tutorial was the tutorial that got me into understanding the string opcodes.
Posted on 2004-02-24 07:45:55 by roticv
Nice work, Nguga. A few typos:
LOADSB should read LODSB etc., STOSSD should read STOSD.
Sometimes a picture or ASCII-Art will tell more then a bunch of lines.

Some more rules which may not seem obvious to beginners:

    [*] REP INSx/OUTSx does not change DX register (data go repeatedly from/to the same I/O port)
    [*] When a string instruction is used without REPx prefix, (E)CX register does not change.
    [*] Even when REPx prefix is not used, (E)SI,(E)DI registers are changed.
    [*] LODSX, STOSx, MOVSx, INSx, OUTSx never change flags.
    [*] SCASx, CMPSx do set flags corresponding to the last B/W/D scanned, compared.
    [*] LODSx may be used with REPx prefix but it is useless.


    Interresting things happen when strings moved with MOVSx overlap partially
    in memory. Four combination may arise depending on DF and ESI<>EDI relation:

    
    
    **** "shift" string to the left (ESI>EDI, DF=0)
    before EDI ESI ECX=5 DF=0
    | |
    |00|11|22|33|44|55|66|77|88|99|

    after EDI ESI ECX=0
    REP MOVSB | |
    |00|33|44|55|66|77|66|77|88|99|


    **** "multiply" string from the left (ESI<EDI, DF=0)
    before ESI EDI ECX=5 DF=0
    | |
    |00|11|22|33|44|55|66|77|88|99|

    after ESI EDI ECX=0 DF=0
    REP MOVSB | |
    |00|11|22|11|22|11|22|11|88|99|

    **** "multiply" string from the right (ESI>EDI, DF=1)
    before EDI ESI ECX=5 DF=1
    | |
    |00|11|22|33|44|55|66|77|88|99|

    after EDI ESI ECX=0
    REP MOVSB | |
    |00|11|88|77|88|77|88|77|88|99|

    **** "shift" string to the right (ESI<EDI, DF=1)
    before ESI EDI ECX=5 DF=1
    | |
    |00|11|22|33|44|55|66|77|88|99|

    after ESI EDI ECX=0
    REP MOVSB | |
    |00|11|22|33|22|33|44|55|66|99|

Posted on 2004-02-24 08:46:39 by vit$oft
I think that ESI and EDI should be preserved for the O.S.
(push/pop).

By the way, what do you think about this function, is it good?

strlenX:
push ebp
mov ebp,esp
push edi
push esi
mov edi,
xor ecx,ecx
xor al,al
cld
doit:
inc ecx
scasb
jne doit
dec ecx
mov eax,ecx
pop esi
pop edi
leave
retn 04h


Regards,
Mariano.:alright:
Posted on 2004-02-24 10:04:24 by Eternal Idol Birmingham
Would this be better than the previous?

strlenX:
push ebp
mov ebp,esp
push edi
push esi
mov edi,
xor ecx,ecx
xor al,al
cld
not ecx
repne scasb
not ecx
dec ecx
mov eax,ecx
pop esi
pop edi
leave
retn 04h

:alright:
Posted on 2004-02-24 10:26:36 by Eternal Idol Birmingham
If you want a simple byte scanner, I would choose something like


proc StrLen, hString ; proc StrLen [hString]
enter
mov eax,[hString]
.scan:
cmp byte[eax],0
lea eax,[eax+1]
jne .scan
sub eax,[hString]; return value in eax
return
Posted on 2004-02-25 06:00:26 by roticv
================================================



Thanks vit$oft , Donkey , rotivc , and all the others for helping me :)






just an example not using this INSTRUCTIONS :)



%include "\lab\vasm\inc\nagoa.inc"



..start:


section data
password db "ola amigo",0
user_pass db "ola amigo",0
user_pass_1 equ $ - user_pass -1 ; lenght user_pass = 9
section code


cmpString:
push ecx
push ebx
push edi
push esi

mov ecx,user_pass_1
mov eax,password
mov ebx,user_pass

.good_caracter_go_next
xor edi,edi
xor esi,esi
mov edi,
mov esi,
cmp di,si
je .increment_decrement_stuff
jmp .BadBoy
.increment_decrement_stuff
inc eax
inc ebx
dec ecx
cmp ecx,0
je .GoodBoy
jmp .good_caracter_go_next



.BadBoy
call MessageBoxA , NULL,"BAD BOY !!! ","INFO",MB_OK
jmp .out_

.GoodBoy

call MessageBoxA , NULL,"GOOD BOY !!! ","INFO",MB_OK

.out_
pop esi
pop edi
pop ebx
pop ecx
xor eax,eax
ret

============================================
Posted on 2004-02-25 09:00:06 by Nguga