Download - [ASM]Lab8
Assembly Language (Lab 8)String Primitives Instructions
AgendaMOVSx
CMPSx
SCANSx
STOSx
LODSx
2D Arrays
Assignment
Replace x with B,
W and D
B = Byte
W = Word
D = Dword
Introduction
String Primitives These instructions use memory operands pointed by the
ESI register or EDI register or both.
Used register(s) is automatically incremented or decremented after instruction execution based on the Direction flag (a bit in the EFLAGS register).
If the direction flag is cleared (DF = 0), registers are incremented. Otherwise (DF = 1), they are decremented.
Direction flag can be set by std instruction, and cleared by cldinstruction
String Primitives They often used with repeat prefix which allows them to
be automatically repeated using ECX as a counter. So, you can process an entire array or string using only single instruction.
The following repeat prefixes are used:
REP inst_Name
String Primitives When repeat prefix is used, the sequence of its operation
is as follows:
1. Test repeat condition(s) [ECX > 0 and zero flag status with REPE and REPNE]
2. If test success, perform the instruction (in addition to incrementing or decrementing ESI or EDI or both). Otherwise, skip the entire instruction.
MOVSx (Move)
MOVSB / MOVSW / MOVSD Instructions
These instructions copy data pointed by ESI to the memory location pointed by EDI. They are used with repeat prefixes to copy arrays and strings.
It’s Like:
T
H
E
T
H
E
ESIEDI
ESI
ESI
EDI
EDI
MOV [EDI], [ESI]
[Hands On] Copy an ArrayUse string primitive instructions to copy items from
double word array to another, then display the output
.datasource dword 10,20,30,40,50target dword 5 dup(?).codemain proc
cld ;clear direction flag. Move forwardmov ecx, lengthof sourcemov esi, offset sourcemov edi, offset targetrep movsd; display the target arraymov edx, OFFSET targetmov ecx, lengthof targetL1:
MOV eax, [edx]CALL WriteIntCALL CRLFADD edx, TYPE target
LOOP L1exitmain endpend main
CMPSx (Compare)
CMPSB / CMPSW / CMPSDThese instructions compare a memory operand pointed
by ESI (source) with the memory operand pointed by EDI(destination).
They actually subtract target from source and set flags according to the result like CMP instruction.
It’s Like:CMP [EDI], [ESI]
Example
.DATASOURCE DWORD 1234hTARGET DWORD 5678h
.CODEMOV ESI, OFFSET SOURCEMOV EDI, OFFSET TARGETCMPSD ;like cmp [EDI], [ESI] JA l1JMP l2
[Solved Example] CMP 2 StringsCompare two strings assuming that both strings have the
same size.
.datasource byte 'ameen'target byte 'ayman'
strSmall byte "source is smaller",0strGreat byte "source is greater",0strEqual byte "both strings are equal",0
.codemain proc
cld ;clear the direction flagmov esi, offset sourcemov edi, offset targetmov ecx, lengthof source
repe cmpsb ;compare the 2 arrays and stop at the first mismatch
jb source_smaller ;check last char in source and lastja source_greater ;char in dest
mov edx, offset strEqualjmp done
source_smaller:mov edx, offset strSmalljmp done
source_greater:mov edx, offset strGreat
done:call writestringcall Crlf
exitmain endpend main
[Hands On] CMP 2 Strs with Diff Len
Implement the same previous example but assume the strings have different length
Key Idea:
1.Loop for the length of the minimum
2.Handle case JB and JA like pervious
3.In case of having the same chars check the length of each
.datasource byte 'ameen'target byte 'ayman'
strSmall byte "source is smaller",0strGreat byte "source is greater",0strEqual byte "both strings are equal",0
.codemain proc
cld ;clear the direction flagmov esi, offset sourcemov edi, offset targetmov ecx, lengthof sourcemov eax, lengthof target ;EAX = length of target string
.if ecx > eaxmov ecx, eax
.endifrepe cmpsb ;compare the 2 arrays and stop at the first mismatchjb source_smaller ;check last char in source and last char in destja source_greater.if eax < lengthof source ;if both chars are equal then
jmp source_greater ;check the length of each one.elseif eax > lengthof source
jmp source_smaller.else
mov edx, offset strEqualjmp done
.endifsource_smaller:
mov edx, offset strSmalljmp done
source_greater:mov edx, offset strGreat
done:call writestringcall Crlf
exitmain endp
SCASB / SCASW / SCASD InstructionsCompare a value in AL/AX/EAX to a byte, word, or double
word addressed by EDI respectively.
They are useful when looking for a single value in an array or a string.
1. Start = EDI
2. Inversed Index = ECX
3. What to search for = AL/AX/EAX
4. Return the index if exists in ECX register It counts from the end of the array
20
[Hands On] Find ‘W’Write an assembly program the search for letter ‘w’ in a
given string
It’s a sequential search…
.datastr1 byte "hello world",0
.codemain proc
cldmov edi, offset str1mov ecx, lengthof str1mov al, 'w'repne scasb ;scan string till 'w' is foundjne not_found ;'w' is not found, jump to not_found label;Otherwise, ecx has the index of that character but reversed;So, make eax = lengthof(str1) - ecx - 1mov eax, lengthof str1 - 1sub eax, ecxjmp donenot_found:
mov eax, -1done: ;eax has the index of the char OR -1 if not found
call writeintexitmain endp
STOSx (Store)
STOSB / STOSW / STOSD InstructionsThese instructions store the content of AL/AX/EAX into
memory at the offset pointed to by EDI.
They are useful for filling all elements of a string or array with a single value.
It’s Like
MOV BYTE PTR [EDI], AL
MOV WORD PTR [EDI], AX
MOV DWORD PTR [EDI], EAX
[Solved Example] Fill an ArrayUses string primitive instructions to initialize an array by a
specific value.
It reminds me with DUP API ;)
Use an already defined word array with length 20 Init. it with 5
.dataarr1 word 20 dup (?)
.codemain proc
cldmov edi, offset arr1mov ecx, lengthof arr1mov ax, 5 ;save number you want to initialize with in the AXrep stosw ;set all items in arr1 by AX value
;display the array elementsmov ecx , lengthof arr1mov esi, offset arr1L1:
movzx eax, WORD PTR[esi]call writeIntCall CRLF
LOOP L1exitmain endpend main
LODSx (Load)
The inverse of STOSx
LODSB / LODSW / LODSD Instructions
These instructions load a byte, word, or double word from memory at ESI into AL/AX/EAX respectively.
REP prefix is rarely used with them as each new value loaded into accumulator overwrites its previous contents.
MOV AL, BYTE PTR [ESI]
MOV AX, WORD PTR [ESI]
MOV EAX, DWORD PTR [ESI]
[Hands On] Array Multiplier Write an assembly program the multiply a Dword array with
10
Example
You have a fixed array 1, 2, 3, 4, 5
Print 10, 20, 30, 40, 50
Key Idea
1. Load array element by element
2. Multiply loaded element by 10
3. Store element
.dataarr1 dword 1, 2, 3, 4, 5multiplier dword 10
.codemain proc
cldmov esi, offset arr1 ;initialize ESI for LODSD instructionmov edi, esi ;initialize EDI for STOSD instructionmov ecx, lengthof arr1l1:
lodsd ;mov eax, [esi]mul multiplier ;edx:eax = eax * multiplierstosd ;mov [edi], eax
loop l1
;display array elements…mov ecx, lengthof arr1mov esi, offset arr1L2:
mov eax, [esi] ;Or use LODSB instruction…call writeIntcall crlfadd esi, type arr1
Loop L2
exitmain endpend main
2D Arrays!
Two Dimensional ArraysMulti-dimensional arrays in assembly are defined as
single dimensional arrays… WHY??
For example, a 2D array can be defined as 1D array where rows are concatenated in a single row.
Accessing items in 2D arrays can be done by indirect memory addressing mode using a base register and an index register like [ebx+esi].
In such addressing mode, a base register (i.e. ebx) should contain the row offset while an index register (i.e. esi) should contain the column offset.
[Solved Example] Sum 2D ArrGiven 2D array
Calculate it’s sum in the EAX
Then display it
Questions?
1. 2D Array how to declare?
2. How to parse/navigate from row to row? key idea
include irvine32.inc.data
table1 dword 1, 2, 3, 4dword 5, 6, 7, 8dword 9, 10, 11, 12
;the same as: table1 dword 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12ncol dword 4
.codeSum2DArr proto table: PTR DWORD, nrow:DWORD, ncol:DWORDmain proc
invoke Sum2DArr, offset table1, 3, 4call writeintcall CrLfexitmain endp
Sum2DArr proc USES esi ecx ebx edx, table: PTR DWORD, nrows:DWORD, ncols:DWORD
mov esi, table ;ESI = start of 1st rowmov ecx, nrows ;ECX: # of rows
; will be used as a row indexmov edx, ncolsshl edx, 2 ;EDX: # of bytes in each row (ncols*4)
mov ebx, 0 ;col indexmov eax, 0 ;EAX: accumulator for the result
l1:.while ebx < ncols
add eax, [esi+4*ebx]inc ebx
.endwmov ebx,0 ;Reset col. Index for each rowadd esi, edx ;ESI: points to the next row
loop l1ret
Sum2DArr endp
[Hands On] Sum i Col. In 2D ArrCalculate the sum of a given column in a 2D array
USING PROC
Given in .datatable1 dword 1, 2, 3, 4
dword 5, 6, 7, 8dword 9, 10, 11, 12
Col to be summed = 3Sum = 24
include irvine32.inc.data
table1 dword 1, 2, 3, 4dword 5, 6, 7, 8dword 9, 10, 11, 12
;the same as: table1 dword 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12ncol dword 4
.code
SumCol proto table: PTR DWORD, nrow:DWORD, ncol:DWORD, icol:DWORD
main proc
invoke SumCol, offset table1, 3, 4, 3call writeintcall CrLf
exitmain endp
SumCol proc USES esi ecx ebx edx, table: PTR DWORD, nrows:DWORD, ncols:DWORD, icol:DWORD
mov esi, table ;ESI: points to the beginning of array (1st row) base regmov ecx, nrows ;ECX: # of rows
; will be used as a row indexmov edx, ncolsshl edx, 2 ;EDX: # of bytes in each row (ncols*4)
mov ebx, icol ;EBX: index of target columnmov eax, 0 ;EAX: accmulator for the result
l1:add eax, [esi+4*ebx]add esi, edx ;ESI: points to the next row
loop l1retSumCol endpend main
Assignment
You Must Use PROC in Your Solution…
asm_strCat1. Write a procedure named asm_strCat that
concatenates a source string to the end of a target string. Use string primitive instructions when is possible.
asm_strFind2. Write a procedure named asm_strFind that searches
for a string inside a target string and returns the first matching position if any. Use string primitive instructions when is possible.
asm_strRemove3. Write a procedure named asm_strRemove that
removes n characters from a string. This procedure should take a pointer to a string, the position in the string where the character are to be removed and number of characters to be removed n. Use string primitive instructions when is possible.
Questions?!
Thanks!