32位汇编语言学习笔记(30)--rep movsb指令

时间:2022-08-14 03:33:55


在《32位汇编语言学习笔记(19)--缓冲区溢出实验》中,我们曾遇到过一个字符串指令:repnz scas,现在我们要学习另外一个字符串指令:rep movsb。
首先看一个小程序:

section .data

	EditBuff: db 'abcdefghijklm         ',10
	BUFFERLEN equ $-EditBuff
	ENDPOS    equ 12
	INSRTPOS  equ 0
	
section .text

WriteStr:
	push eax		; Save pertinent registers
	push ebx
	mov eax,4		; Specify sys_write call
	mov ebx,1		; Specify File Descriptor 1: Stdout
	int 80H			; Make the kernel call
	pop ebx			; Restore pertinent registers
	pop eax
	ret			; Go home
	
	global	_start
_start:
	nop
	
	mov ecx,EditBuff		
	mov edx,BUFFERLEN	
	call WriteStr
	
	std				; Up-memory transfer
	mov ebx,EditBuff+INSRTPOS
	mov esi,EditBuff+ENDPOS		; Start at end of text
	mov edi,EditBuff+ENDPOS+1	; Bump text right by 1
	mov ecx,ENDPOS-INSRTPOS+1	; # of chars to bump
	rep movsb			; Move 'em!
	mov byte [ebx],' '
    mov ecx,EditBuff		
	mov edx,BUFFERLEN	
	call WriteStr

Exit:	mov eax,1		; Code for Exit Syscall
	mov ebx,0		; Return a code of zero	
	int 80H			; Make kernel call

程序分析:
 mov ecx,EditBuff  
 mov edx,BUFFERLEN 
 call WriteStr      //打印字符串的初值

 std    //std指令,设置DF标志位,这会使得rep movsb执行循环拷贝操作时,源地址和目的地址变化方向是从高到低。
 mov ebx,EditBuff+INSRTPOS //ebx= EditBuff
 mov esi,EditBuff+ENDPOS  //esi = &EditBuff[12],esi是rep movsb的源地址,指向’m’。
 mov edi,EditBuff+ENDPOS+1 //edi= &EditBuff[13],edi是rep movsb的目的地址,指向第一个空格。
 mov ecx,ENDPOS-INSRTPOS+1 //ecx=13,用于rep movsb的循环计数器
 rep movsb   //通过循环把源地址的数据拷贝到目的地址上,每循环一次ecx就会减1,esi和edi也会减1,当ecx=0时终止循环。执行顺序是:先判断ecx是否为0,如果非0,进行拷贝操作,然后ecx=ecx-1,edi=edi-1,esi=esi-1,进入下一次循环,否则退出循环。因此,循环次数是13。
 mov byte [ebx],' ' // EditBuff[0]=’ ’

 mov ecx,EditBuff  
 mov edx,BUFFERLEN 
 call WriteStr //打印修改后的字符串。

makefile文件:

movsbdemo: movsbdemo.o
	ld -o movsbdemo movsbdemo.o
movsbdemo.o: movsbdemo.asm
	nasm -f elf -g -F stabs movsbdemo.asm -l movsbdemo.lst

测试:

[root@bogon movsbdemo]# make
nasm -f elf -g -F stabs movsbdemo.asm -l movsbdemo.lst
ld -o movsbdemo movsbdemo.o
[root@bogon movsbdemo]# ./movsbdemo 
abcdefghijklm         
 abcdefghijklm