Storing A String Byte Using String Primitives Increments/decrements Which Register?
Affiliate Half-dozen The Cord Instructions
6.1 Affiliate Overview
A string is a drove of objects stored in contiguous memory locations. Strings are commonly arrays of bytes, words, or (on 80386 and later on processors) double words. The 80x86 microprocessor family unit supports several instructions specifically designed to cope with strings. This chapter explores some of the uses of these string instructions.
The 80x86 CPUs tin procedure three types of strings: byte strings , word strings, and double word strings. They can move strings, compare strings, search for a specific value inside a cord, initialize a string to a fixed value, and practice other primitive operations on strings. The 80x86's string instructions are likewise useful for manipulating arrays, tables, and records. Y'all tin can easily assign or compare such information structures using the string instructions. Using cord instructions may speed upwards your assortment manipulation code considerably.
6.two The 80x86 Cord Instructions
All members of the 80x86 family support five dissimilar cord instructions: MOVSx, CMPSx, SCASx, LODS10, and STOSten one. (10= B, Due west, or D for byte, word, or double word, respectively. This text will mostly drop the 10 suffix when talking about these string instructions in a general sense.) They are the cord primitives since yous can build virtually other string operations from these five instructions. How you use these five instructions is the topic of the next several sections.
For MOVS: movsb(); movsw(); movsd(); For CMPS: cmpsb(); // Note: repz is a synonym for repe cmpsw(); cmpsd(); cmpsb(); // Note: repnz is a synonym for repne. cmpsw(); cmpsd(); For SCAS: scasb(); // Notation: repz is a synonym for repe scasw(); scasd(); scasb(); // Notation: repnz is a synonym for repne. scasw(); scasd(); For STOS: stosb(); stosw(); stosd(); For LODS: lodsb(); lodsw(); lodsd();
6.2.one How the String Instructions Operate
The string instructions operate on blocks (contiguous linear arrays) of retention. For instance, the MOVS teaching moves a sequence of bytes from one memory location to another. The CMPS pedagogy compares 2 blocks of retentiveness. The SCAS instruction scans a block of memory for a particular value. These string instructions oftentimes require 3 operands, a destination block address, a source block address, and (optionally) an element count. For example, when using the MOVS instruction to re-create a string, you lot demand a source address, a destination address, and a count (the number of cord elements to move).
Different other instructions which operate on memory, the string instructions don't accept any explicit operands. The operands for the string instructions include
- the ESI (source alphabetize) register,
- the EDI (destination index) register,
- the ECX (count) register,
- the AL/AX/EAX register, and
- the direction flag in the FLAGS register.
For example, one variant of the MOVS (motion string) instruction copies a string from the source accost specified by ESI to the destination address specified past EDI, of length ECX. Also, the CMPS educational activity compares the cord pointed at by ESI, of length ECX, to the string pointed at by EDI.
Not all instructions have source and destination operands (only MOVS and CMPS support them). For example, the SCAS educational activity (browse a string) compares the value in the accumulator (AL, AX, or EAX) to values in memory.
half dozen.2.2 The REP/REPE/REPZ and REPNZ/REPNE Prefixes
The string instructions, past themselves, practise not operate on strings of data. The MOVS instruction, for example, volition motility a single byte, word, or double word. When executed by itself, the MOVS instruction ignores the value in the ECX register. The repeat prefixes tell the 80x86 to do a multi-byte string operation. The syntax for the repeat prefix is:
For MOVS: rep.movsb(); rep.movsw(); rep.movsd(); For CMPS: repe.cmpsb(); // Annotation: repz is a synonym for repe. repe.cmpsw(); repe.cmpsd(); repne.cmpsb(); // Note: repnz is a synonym for repne. repne.cmpsw(); repne.cmpsd(); For SCAS: repe.scasb(); // Note: repz is a synonym for repe. repe.scasw(); repe.scasd(); repne.scasb(); // Note: repnz is a synonym for repne. repne.scasw(); repne.scasd(); For STOS: rep.stosb(); rep.stosw(); rep.stosd();
You don't normally use the repeat prefixes with the LODS pedagogy.
When specifying the repeat prefix earlier a string education, the string didactics repeats ECX timestwo. Without the repeat prefix, the instruction operates only on a single byte, word, or double word.
Yous tin utilise echo prefixes to process entire strings with a unmarried instruction. Yous can use the cord instructions, without the repeat prefix, every bit string archaic operations to synthesize more powerful string operations.
6.ii.three The Direction Flag
Besides the ESI, EDI, ECX, and AL/AX/EAX registers, one other annals controls the 80x86'south cord instructions - the flags register. Specifically, the management flag in the flags register controls how the CPU processes strings.
If the direction flag is articulate, the CPU increments ESI and EDI later operating upon each cord chemical element. For example, if the direction flag is clear, then executing MOVS will move the byte, word, or double discussion at ESI to EDI and will increase ESI and EDI by i, ii, or four. When specifying the REP prefix before this education, the CPU increments ESI and EDI for each element in the cord. At completion, the ESI and EDI registers will exist pointing at the first item beyond the strings.
If the direction flag is set, then the 80x86 decrements ESI and EDI after processing each string element. After a repeated string operation, the ESI and EDI registers will be pointing at the first byte or word before the strings if the direction flag was set.
The direction flag may exist set or cleared using the CLD (clear direction flag) and STD (set direction flag) instructions. When using these instructions inside a process, keep in mind that they modify the machine state. Therefore, you lot may need to save the management flag during the execution of that process. The post-obit example exhibits the kinds of issues you might run across:
procedure Str2; nodisplay; begin Str2; std(); <Do some string operations> . . . cease Str2; . . . cld(); <do some operations> Str2(); <do some string operations requiring D=0>
This code will not work properly. The calling code assumes that the management flag is clear after Str2 returns. However, this isn't true. Therefore, the cord operations executed later on the phone call to Str2 will non function properly.
There are a couple of ways to handle this problem. The first, and probably the most obvious, is always to insert the CLD or STD instructions immediately before executing a sequence of ane or more string instructions. The other alternative is to save and restore the management flag using the PUSHFD and POPFD instructions. Using these ii techniques, the code above would await like this:
Always issuing CLD or STD earlier a string instruction:
process Str2; nodisplay; begin Str2; std(); <Do some cord operations> . . . terminate Str2; . . . cld(); <practise some operations> Str2(); cld(); <do some cord operations requiring D=0>
Saving and restoring the flags annals:
procedure Str2; nodisplay; brainstorm Str2; pushfd(); std(); <Do some string operations> . . . popfd(); end Str2; . . . cld(); <do some operations> Str2(); <practice some string operations requiring D=0>
If you use the PUSHFD and POPFD instructions to save and restore the flags register, proceed in mind that you're saving and restoring all the flags. Therefore, such subroutines cannot return any data in the flags. For example, yous will non be able to return an error condition in the carry flag if y'all use PUSHFD and POPFD.
6.2.four The MOVS Education
The MOVS pedagogy uses the following syntax:
movsb() movsw() movsd() rep.movsb() rep.movsw() rep.movsd()
The MOVSB (move string, bytes) educational activity fetches the byte at address ESI, stores it at address EDI and so increments or decrements the ESI and EDI registers by one. If the REP prefix is nowadays, the CPU checks ECX to meet if it contains zero. If not, then it moves the byte from ESI to EDI and decrements the ECX register. This procedure repeats until ECX becomes zero.
The MOVSW (move string, words) instruction fetches the word at address ESI, stores it at accost EDI and then increments or decrements ESI and EDI by ii. If at that place is a REP prefix, so the CPU repeats this procedure every bit many times as specified in ECX.
The MOVSD instruction operates in a like fashion on double words. Incrementing or decrementing ESI and EDI by four for each data motility.
When you use the rep prefix, the MOVSB education moves the number of bytes you specify in the ECX register. The following code segment copies 384 bytes from CharArray1 to CharArray2:
CharArray1: byte[ 384 ]; CharArray2: byte[ 384 ]; . . . cld(); lea( esi, CharArray1 ); lea( edi, CharArray2 ); mov( 384, ecx ); rep.movsb();
If you substitute MOVSW for MOVSB, then the lawmaking in a higher place will move 384 words (768 bytes) rather than 384 bytes:
WordArray1: discussion[ 384 ]; WordArray2: word[ 384 ]; . . . cld(); lea( esi, WordArray1 ); lea( edi, WordArray2 ); mov( 384, ecx ); rep.movsw();
Recollect, the ECX annals contains the element count, not the byte count. When using the MOVSW instruction, the CPU moves the number of words specified in the ECX register. Similarly, MOVSD moves the number of double words you specify in the ECX register, not the number of bytes.
If you've set the direction flag before executing a MOVSB/MOVSW/MOVSD teaching, the CPU decrements the ESI and EDI registers afterward moving each string chemical element. This means that the ESI and EDI registers must point at the end of their respective strings before issuing a MOVSB, MOVSW, or MOVSD instruction. For instance,
CharArray1: byte[ 384 ]; CharArray2: byte[ 384 ]; . . . cld(); lea( esi, CharArray1[383] ); lea( edi, CharArray2[383] ); mov( 384, ecx ); rep.movsb();
Although there are times when processing a cord from tail to caput is useful (run across the CMPS description in the next section), more often than not you'll process strings in the forrard direction since it'due south more straightforward to practise then. There is one class of cord operations where existence able to procedure strings in both directions is absolutely mandatory: processing strings when the source and destination blocks overlap. Consider what happens in the post-obit lawmaking:
CharArray1: byte; CharArray2: byte[ 384 ]; . . . cld(); lea( esi, CharArray1 ); lea( edi, CharArray2 ); mov( 384, ecx ); rep.movsb();
This sequence of instructions treats CharArray1 and CharArray2 every bit a pair of 384 byte strings. Even so, the concluding 383 bytes in the CharArray1 assortment overlap the first 383 bytes in the CharArray2 array. Allow'southward trace the operation of this code byte by byte.
When the CPU executes the MOVSB instruction, information technology copies the byte at ESI (CharArray1) to the byte pointed at by EDI (CharArray2). And then it increments ESI and EDI, decrements ECX by one, and repeats this process. At present the ESI register points at CharArray1+one (which is the address of CharArray2) and the EDI annals points at CharArray2+1. The MOVSB instruction copies the byte pointed at past ESI to the byte pointed at by EDI. All the same, this is the byte originally copied from location CharArray1. So the MOVSB instruction copies the value originally in location CharArray1 to both locations CharArray2 and CharArray2+1. Again, the CPU increments ESI and EDI, decrements ECX, and repeats this operation. Now the movsb instruction copies the byte from location CharArray1+2 (CharArray2+1) to location CharArray2+2. Simply once more, this is the value that originally appeared in location CharArray1. Each repetition of the loop copies the next element in CharArray1[0] to the next available location in the CharArray2 assortment. Pictorially, it looks something similar that shown in Figure 6.i.
Figure 6.1 Copying Data Between Two Overlapping Arrays (frontwards direction)
The stop result is that the MOVSB instruction replicates X throughout the string. The MOVSB didactics copies the source operand into the retentivity location which volition become the source operand for the very next move operation, which causes the replication.
If y'all really want to motility one array into another when they overlap, you lot should move each element of the source cord to the destination cord starting at the end of the two strings as shown in Figure six.ii.
Effigy 6.2 Using a Backwards Copy to Copy Data in Overlapping Arrays
Setting the management flag and pointing ESI and EDI at the cease of the strings will allow you lot to (correctly) move i string to another when the two strings overlap and the source string begins at a lower address than the destination string. If the two strings overlap and the source cord begins at a higher address than the destination string, then clear the direction flag and indicate ESI and EDI at the beginning of the ii strings.
If the ii strings exercise not overlap, and then yous can use either technique to motion the strings around in memory. Generally, operating with the direction flag clear is the easiest, and so that makes the most sense in this case.
You shouldn't utilize the MOVSx pedagogy to fill an array with a single byte, discussion, or double word value. Another string instruction, STOS, is much better for this purpose. Nevertheless, for arrays whose elements are larger than four bytes, you lot can use the MOVS instruction to initialize the entire assortment to the content of the first element.
The MOVS didactics is generally more efficient when copying double words than information technology is copying bytes or words. In fact, it typically takes the same corporeality of time to copy a byte using MOVSB as it does to re-create a double word using MOVSD3. Therefore, if yous are moving a large number of bytes from one array to some other, the re-create operation volition be faster if yous can use the MOVSD didactics rather than the MOVSB instruction. Of class, if the number of bytes you wish to move is an even multiple of four, this is a trivial change; but divide the number of bytes to copy by iv, load this value into ECX, and and then use the MOVSB teaching. If the number of bytes is not evenly divisible by four, and then you tin use the MOVSD instruction to copy all but the concluding one, two, or three bytes of the array (that is, the remainder after you lot divide the byte count by four). For instance, if y'all want to efficiently motility 4099 bytes, you can do then with the following instruction sequence:
lea( esi, Source ); lea( edi, Destination ); mov( 1024, ecx ); // Copy 1024 dwords = 4096 bytes rep.movsd(); movsw(); // Copy bytes 4097 and 4098. movsb(); // Copy the concluding byte.
Using this technique to copy information never requires more 3 MOVSx instructions since you tin re-create one, ii, or iii bytes with no more than than two MOVSB and MOVSW instructions. The scheme to a higher place is almost efficient if the 2 arrays are aligned on double word boundaries. If non, you might want to move the MOVSB or MOVSW instruction (or both) before the MOVSD so that the MOVSD educational activity works with dword-aligned data (meet Chapter Three for an explanation of the performance benefits of double word aligned data).
If y'all do not know the size of the block you are copying until the programme executes, you lot tin still use lawmaking like the following to amend the performance of a block move of bytes:
lea( esi, Source ); lea( edi, Dest ); mov( Length, ecx ); shr( two, ecx ); // split up by four. if( @nz ) so // Only execute MOVSD if four or more than bytes. rep.movsd(); // Copy the dwords. endif; mov( Length, ecx ); and( %11, ecx ); // Compute (Length mod four). if( @nz ) then // Only execute MOVSB if #bytes/4 <> 0. rep.movsb(); // Re-create the remaining 1, two, or three bytes. endif;
On most computer systems, the MOVSD instruction provides virtually the fastest fashion to copy bulk data from one location to another. While in that location are, arguably, faster ways to copy the data on certain CPUs, ultimately the memory bus performance is the limiting factor and the CPUs are generally much faster than the memory bus. Therefore, unless you have a special organisation, writing fancy code to improve retention to retention transfers is probably a waste material of time. Also note that Intel has improved the performance of the MOVSx instructions on later processors so that MOVSB operates about as efficiently as MOVSW and MOVSD when copying the same number of bytes. Therefore, when working on a later x86 processor, information technology may be more efficient to simply apply MOVSB to copy the specified number of bytes rather than go through all the complexity outlined in a higher place.
half dozen.2.5 The CMPS Instruction
The CMPS education compares two strings. The CPU compares the string referenced past EDI to the string pointed at by ESI. ECX contains the length of the 2 strings (when using the REPE or REPNE prefix). Like the MOVS instruction, HLA allows several different forms of this pedagogy:
cmpsb(); cmpsw(); cmpsd(); repe.cmpsb(); repe.cmpsw(); repe.cmpsd(); repne.cmpsb(); repne.cmpsw(); repne.cmpsd();
Like the MOVS instruction you specify the bodily operand addresses in the ESI and EDI registers.
Without a repeat prefix, the CMPS instruction subtracts the value at location EDI from the value at ESI and updates the flags. Other than updating the flags, the CPU doesn't use the divergence produced by this subtraction. After comparison the ii locations, CMPS increments or decrements the ESI and EDI registers by one, two, or 4 (for CMPSB/CMPSW/CMPSD, respectively). CMPS increments the ESI and EDI registers if the management flag is clear and decrements them otherwise.
Of course, yous will not tap the real power of the CMPS instruction using information technology to compare single bytes, words, or double words in memory. This instruction shines when y'all use it to compare whole strings. With CMPS, you tin compare consecutive elements in a string until you detect a lucifer or until consecutive elements do not match.
To compare 2 strings to see if they are equal or non equal, yous must compare corresponding elements in a cord until they don't lucifer. Consider the following strings:
"String1"
"String1"
The merely fashion to determine that these two strings are equal is to compare each grapheme in the first cord to the respective character in the 2nd. After all, the second string could have been "String2" which definitely is not equal to "String1". Of course, once yous encounter a grapheme in the destination cord which doesn't equal the corresponding graphic symbol in the source string, the comparison can cease. You lot needn't compare any other characters in the two strings.
The REPE prefix accomplishes this functioning. It will compare successive elements in a string every bit long as they are equal and ECX is greater than zero. We could compare the two strings in a higher place using the following 80x86 assembly language code:
cld(); mov( AdrsString1, esi ); mov( AdrsString2, edi ); mov( seven, ecx ); repe.cmpsb();
After the execution of the CMPSB instruction, you tin test the flags using the standard provisional bound instructions. This lets you cheque for equality, inequality, less than, greater than, etc.
Grapheme strings are usually compared using lexicographical ordering. In lexicographical ordering, the least significant element of a string carries the near weight. This is in direct dissimilarity to standard integer comparisons where the most significant portion of the number carries the most weight. Furthermore, the length of a string affects the comparison only if the two strings are identical up to the length of the shorter string. For example, "Zebra" is less than "Zebras", because it is the shorter of the ii strings, all the same, "Zebra" is greater than "AAAAAAAAAAH!" fifty-fifty though information technology is shorter. Lexicographical comparisons compare corresponding elements until encountering a character which doesn't match, or until encountering the terminate of the shorter string. If a pair of corresponding characters do not lucifer, and then this algorithm compares the ii strings based on that single character. If the two strings match up to the length of the shorter string, we must compare their length. The two strings are equal if and only if their lengths are equal and each corresponding pair of characters in the two strings is identical. Lexicographical ordering is the standard alphabetical ordering you've grown up with.
For character strings, use the CMPS instruction in the following mode:
- The direction flag must be cleared before comparing the strings.
- Employ the CMPSB instruction to compare the strings on a byte by byte footing. Fifty-fifty if the strings contain an even number of characters, you cannot use the CMPSW or CMPSD instructions. They practise non compare strings in lexicographical order.
- You lot must load the ECX annals with the length of the smaller cord.
- Use the REPE prefix.
- The ESI and EDI registers must point at the very first character in the two strings you want to compare.
Later on the execution of the CMPS instruction, if the two strings were equal, their lengths must be compared in order to end the comparing. The following code compares a couple of character strings:
mov( AdrsStr1, esi ); mov( AdrsStr2, edi ); mov( LengthSrc, ecx ); if( ecx > LengthDest ) and then // Put the length of the shorter string in ECX. mov( LengthDest, ecx ); endif; repe.cmpsb(); if( @z ) then // If equal to the length of the shorter string, cmp lengths. mov( LengthSrc, ecx ); cmp( ecx, LengthDest ); endif;
If yous're using bytes to concur the string lengths, you should adjust this code accordingly (i.e., use a MOVZX instruction to load the lengths into ECX). Of grade, HLA strings apply a double discussion to hold the current length value, so this isn't an issue when using HLA strings.
You tin can also employ the CMPS instruction to compare multi-word integer values (that is, extended precision integer values). Because of the amount of setup required for a string comparison, this isn't practical for integer values less than half dozen or eight double words in length, but for large integer values, information technology'due south an splendid way to compare such values. Unlike character strings, we cannot compare integer strings using a lexicographical ordering. When comparing strings, we compare the characters from the least significant byte to the most pregnant byte. When comparing integers, we must compare the values from the nigh significant byte (or give-and-take/double discussion) downwardly to the to the lowest degree pregnant byte, word or double give-and-take. And then, to compare two 32-byte (256-bit) integer values, use the following lawmaking on the 80x86:
std(); lea( esi, SourceInteger[28] ); lea( edi, DestInteger[28] ); mov( 8, ecx ); rep.cmpsd();
This code compares the integers from their most significant word downwards to the to the lowest degree significant word. The CMPSD pedagogy finishes when the ii values are diff or upon decrementing ECX to nada (implying that the two values are equal). In one case again, the flags provide the issue of the comparison.
The REPNE prefix volition instruct the CMPS instruction to compare successive cord elements as long equally they exercise non match. The 80x86 flags are of niggling utilize subsequently the execution of this instruction. Either the ECX annals is zero (in which case the two strings are totally different), or it contains the number of elements compared in the two strings until a lucifer. While this grade of the CMPS educational activity isn't particularly useful for comparing strings, it is useful for locating the first pair of matching items in a couple of byte, word, or double word arrays. In full general, though, you'll rarely use the REPNE prefix with CMPS.
1 concluding matter to keep in mind with using the CMPS instruction - the value in the ECX register determines the number of elements to process, not the number of bytes. Therefore, when using CMPSW, ECX specifies the number of words to compare. This, of form, is twice the number of bytes to compare. Besides, for CMPSD, ECX contains the number of double words to process.
half-dozen.2.6 The SCAS Pedagogy
The CMPS education compares two strings against one another. You do not employ it to search for a particular chemical element within a string. For example, y'all could not use the CMPS instruction to apace browse for a zero throughout some other string. You lot can use the SCAS (scan string) educational activity for this chore.
Unlike the MOVS and CMPS instructions, the SCAS instruction only requires a destination string (pointed at by EDI) rather than both a source and destination cord. The source operand is the value in the AL (SCASB), AX (SCASW), or EAX (SCASD) register. The SCAS education compares the value in the accumulator (AL, AX, or EAX) against the value pointed at by EDI and and then increments (or decrements) EDI by i, two, or iv. The CPU sets the flags according to the consequence of the comparison. While this might be useful on occasion, SCAS is a lot more useful when using the REPE and REPNE prefixes.
With the REPE prefix (repeat while equal), SCAS scans the string searching for an element which does not match the value in the accumulator. When using the REPNE prefix (echo while not equal), SCAS scans the string searching for the first cord chemical element which is equal to the value in the accumulator.
You're probably wondering "why do these prefixes practice exactly the opposite of what they ought to practice?" The paragraphs above haven't quite phrased the operation of the SCAS instruction properly. When using the REPE prefix with SCAS, the 80x86 scans through the string while the value in the accumulator is equal to the string operand. This is equivalent to searching through the string for the commencement element which does not match the value in the accumulator. The SCAS didactics with REPNE scans through the string while the accumulator is not equal to the string operand. Of course, this form searches for the kickoff value in the string which matches the value in the accumulator register. The SCAS instructions take the following forms:
scasb() scasw() scasd() repe.scasb() repe.scasw() repe.scasd() repne.scasb() repne.scasw() repne.scasd()
Like the CMPS and MOVS instructions, the value in the ECX register specifies the number of elements to process, not bytes, when using a repeat prefix.
half-dozen.2.7 The STOS Teaching
The STOS instruction stores the value in the accumulator at the location specified by EDI. Later on storing the value, the CPU increments or decrements EDI depending upon the state of the direction flag. Although the STOS education has many uses, its primary use is to initialize arrays and strings to a abiding value. For example, if yous have a 256-byte array y'all want to clear out with zeros, employ the following code:
cld(); lea( edi, DestArray ); mov( 64, ecx ); // 64 double words = 256 bytes. xor( eax, eax ); // Zero out EAX. rep.stosd();
This lawmaking writes 64 double words rather than 256 bytes because a single STOSD operation is faster than four STOSB operations.
The STOS instructions accept four forms. They are
stosb(); stosw(); stosd(); rep.stosb(); rep.stosw(); rep.stosd();
The STOSB instruction stores the value in the AL annals into the specified memory location(s), the STOSW instruction stores the AX register into the specified memory location(s) and the STOSD instruction stores EAX into the specified location(southward).
Keep in heed that the STOS education is useful merely for initializing a byte, word, or double word array to a constant value. If you need to initialize an array to different values, y'all cannot apply the STOS teaching. See the exercises for boosted details.
vi.2.8 The LODS Instruction
The LODS education is unique among the string instructions. You will probably never use a repeat prefix with this instruction. The LODS didactics copies the byte, word, or double word pointed at by ESI into the AL, AX, or EAX annals, after which it increments or decrements the ESI register by 1, two, or four. Repeating this teaching via the repeat prefix would serve no purpose whatever since the accumulator register will exist overwritten each time the LODS instruction repeats. At the end of the echo operation, the accumulator will comprise the last value read from memory.
Instead, apply the LODS instruction to fetch bytes (LODSB), words (LODSW), or double words (LODSD) from memory for farther processing. By using the STOS instruction, you can synthesize powerful string operations.
Like the STOS instruction, the LODS instructions take four forms:
lodsb(); lodsw(); lodsd(); rep.lodsb(); rep.lodsw(); rep.lodsd();
Equally mentioned earlier, you lot'll rarely, if ever, use the REP prefixes with these instructions4. The 80x86 increments or decrements ESI by ane, two, or four depending on the direction flag and whether you're using the LODSB, LODSW, or LODSD instruction.
6.2.9 Building Circuitous String Functions from LODS and STOS
The 80x86 supports only 5 unlike string instructions: MOVS, CMPS, SCAS, LODS, and STOS5. These certainly aren't the but string operations you'll always want to use. Nevertheless, you can utilise the LODS and STOS instructions to easily generate any particular cord performance yous like. For example, suppose you wanted a string operation that converts all the upper instance characters in a string to lower instance. Y'all could use the post-obit code:
mov( StringAddress, esi ); // Load string address into ESI. mov( esi, edi ); // Also point EDI here. mov( (type str.strrec [esi].length, ecx ); repeat lodsb(); // Become the next character in the string. if( al in 'A'..'Z' ) and so or( $20, al ); // Convert upper case character to lower case. endif; stosb(); // Store converted character back into string. december( ecx ); until( ecx == 0 );
Since the LODS and STOS instructions utilize the accumulator equally an intermediary, you can use any accumulator operation to quickly manipulate string elements.
6.3 Putting It All Together
In this chapter we took a quick look at the 80x86'due south string instructions. We studied their implementation and saw how to apply them. These instructions are quite useful for synthesizing character gear up functions (see the source code for the HLA Standard Library string module for examples). We also saw how to use these instructions for not-graphic symbol cord purpose such as moving big blocks of memory (i.e., assigning ane array to another) and comparing large integer values. For more information on the utilize of these instructions, please see the volume on Advanced String Treatment.
1The 80x86 processor support two boosted string instructions, INS and OUTS which input strings of data from an input port or output strings of data to an output port. Nosotros will not consider these instructions since they are privileged instructions and yous cannot execute them in a standard 32-chip Bone application.
2Except for the cmps educational activity which repeats at most the number of times specified in the cx register.
3This is true for MOVSW, as well.
fourThey appear hither simply considering they are immune. They're not veryuseful, merely they are allowed.
5Not counting INS and OUTS which we're ignoring here.
| |
|
Web Site Hits Since |
Source: https://www.plantation-productions.com/Webster/www.artofasm.com/Linux/HTML/StringInstructions.html
Posted by: boltwitand.blogspot.com

0 Response to "Storing A String Byte Using String Primitives Increments/decrements Which Register?"
Post a Comment