"Copyright Notice: respect for the original, reproduced please retain the source: blog.csdn.net/shallnet, the article only for learning Exchange, do not use for commercial purposes"
in high-level languages, we often manipulate strings, such as string copies, comparisons, lookups, and so on. There are also commands for implementing these operations in assembly language. This section describes the string transfer related Operations command in assembly language. The Movs instruction can transfer a string from one memory location to another, followed by a character representing the length: MOVSB (1 bytes), MOVSW (2 bytes), Movsl (4 bytes). The directive uses the implied source and target operands. The implied source operand is the ESI register, which points to the memory location of the source string. The implied target operand is the EDI register, which points to the destination memory location where the string is to be copied. When using the GNU assembly, there are two ways to load ESI and EDI values, the first using indirect addressing, for example: Movl $val,%edi, which transmits the 32-bit memory address of the variable Val to EDI. The second is to use the LEA command, which loads a valid address for an object, and the source operand points to a memory location, such as Leal Val,%edi to load the 32-bit memory location of the Val tag into the EDI register. Here is an example:
# movs.s.section. Dataval: . ASCII "Hello, as world!\n". Section. BSS . Lcomm output, 17.section. Text.globl _start _start: NOP Leal Val,%esi leal output,%edi movsb movsw movsl movl $ ,%eax MOVL $, %EBX int $0x80
After make debug run as follows:
Ten NOP (gdb) S11 Leal Val,%esi (gdb) leal output,%edi (gdb) S13 movsb (gdb) S14 movsw (gdb) x/ s &output0x80490a8 <output>: "H" (gdb) S15 movsl (gdb) x/s &output0x80490a8 <output>: "Hel" (gdb ) S17
You can see the memory of output after each Movs instruction, and after each execution of the Movs instruction, the EDI and EDI registers are automatically changed to prepare for the next time after the data is transferred. In this example, the register is incremented, and the register increments or decrements direction varies depending on the DF flag in the EFLAFS register. If the DF flag is zeroed, the ESI and EDI registers are incremented after each Movs instruction, and if the DF flag is set,the ESI and EDI registers are decremented after each movs instruction is executed. If you want to make sure that DF is set to the correct orientation, you can display the settings when writing code: The CLD directive is used to clear the DF flag, and the STD directive sets the DF flag. If you want to copy a longer string, you can simply movs the instruction into the loop and control it by setting the ECX register to the string length. as follows:
# movs.s.section. Dataval: . ASCII "Hello, as world!\n". Section. BSS . Lcomm output, 17.section. Text.globl _start _start: NOP Leal Val,%esi leal output,%edi movl $17,%ecxloop_strcpy: movsb Loop loop_ strcpy MOVL $ $, %eax movl $,%ebx int $0x80
In fact, Intel has a simpler directive: Rep. The rep instruction executes the string instruction following its number of times according to the ECX register value. Examples are as follows:
# rep.s.section. Dataval: . ASCII "Hello, as world!\n". Section. BSS . Lcomm output, 17.section. Text.globl _start_ Start: NOP Leal Val,%esi leal output,%edi movl $17,%ecx CLD Rep MOVSB Movl $,%eax MOVL $,%ebx int $0x80
After make debug run as follows:
movl $17,%ecx (gdb) CLD (gdb)- Rep MOVSB (GDB) MOVL $,%eax (GDB) x/s &output0x80490b0 <output>: "Hello, as world!\n" (GDB)
You can actually transfer multiple bytes in sequence, and you need to place the correct number of times in the ECX register in case the string bounds are exceeded. Using the MOVSL instruction to transfer a string can be more efficient, but it is important to know when to stop using the MOVSL directive and use the MOVSB directive, which can be determined by integer division.
Linux Platform x86 compilation (11): String transfer