2.9内存复制

2.9内存复制

本节必须掌握的知识点:

    掌握MOVS指令、STOS指令、REP指令的格式、功能

    在上一节中介绍了部分常用指令,本节继续介绍几个常用指令,看到标题大家肯定能猜到接下来介绍的常用指令肯定和内存有关系。到目前为止我们知道与内存有关系的指令,MOV指令,它是移动指令,可以从内存到寄存器,从寄存器到寄存器,从寄存器到内存,并不能从内存到内存,接下来介绍的这些指令它们可以做到从内存到内存的。

2.9.1【MOVS指令】

MOVS指令串传送指令,用于传送字符串。

知道了MOVS指令的用途,那它主要做什么工作呢?在程序运行过程中,经常要复制大片内存或者初始化某段内存时,MOV指令在32位汇编中一次最多只能操作4个字节,且不能做到直接从内存复制到内存,必须借用寄存器才能将一块内存的数据复制到另一块内存中,而MOVS指令就可以直接做到从一块内存复制到另一块内存,使程序员效率高了些。

MOVS的格式如下:

1、MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]      简写MOVSB

2、MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]    简写MOVSW

3、MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]  简写MOVSD

【注意:MOVS指令只能使用EDI、ESI这两个通用寄存器,不能使用其他寄存器。当我们要把内存中的数据从一个地方复制到一个地方,我们就使用这些特定的串指令,EDI、ESI分别存储需要复制和被复制的两块内存单元地址,这里被复制的内存单元地址为[ESI],复制到的内存单元地址为[EDI]。MOVS一次可以复制一个字节、两个字节和四个字节。】

说了这么多知识点,我们来点干货,借用DTDebug.exe软件,动手做实验。

第一步:打开DTDebug.exe软件,将要调试的软件拖进DTDebug.exe中。【本节调试的软件为GeePlayer.exe】注:可以调试任意其他软件,步骤相同。

第二步:看图2-9-1所示,ESI存储的数据为0x00000000,EDI存储的数据为0x00000000,需要用到两个已经申请的内存地址,需要从堆栈窗口中找,且记住他们存储的数据。用内存地址0x0018F854它存储的数据为0x00EB2BA2及内存地址0x0018F860它存储的数据为0x00000000。接下来我们修改ESI和EDI的数据,分别将两个内存地址写到ESI和EDI中。ESI的数据修改为0x0018F854,将EDI的数据修改为0x0018F860,如图2-9-2所示。

第三步:输入汇编指令,MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]或MOVSB。按一个字节复制,如图2-9-3所示。

第四步:按F8执行,观察ESI和EDI存储的数据有什么变化及内存地址0x0018F854和内存地址0x0018F860它们存储的数据有什么变化,如图2-9-4所示。

我们观察图2-9-4,当按F8执行完后,看到了寄存器窗口中ESI存储的数据发生了变化,从0x0018F854变成了0x0018F855,EDI存储的数据从0x0018F860变成了0x0018F861。堆栈窗口中内存地址0x0018F854的数据没有发生变化,而内存地址0x0018F860的数据发生了变化由数据0x00000000变成了数据0x000000A2。由于我们是按1个字节复制的,所以ESI和EDI存储的数据会自加1,数据也是复制一个字节。

我们用同样的步骤对MOVSW操作观察有什么变化。

第一步:输入指令MOVSW,修改ESI、EDI的数据,ESI存储的数据为0x0018F854,ESI存储的数据为0x0018F85C,内存地址0x0018F854存储的数据为0x00EB2BA2,内存地址0x0018F85C存储的数据为0x00000000如图2-9-5所示。

第二步:按F8执行,并观察各数据的变化,如图2-9-6所示。

我们观察图2-9-6,当按F8执行完后,看到了寄存器窗口中ESI存储的数据发生了变化,从0x0018F854变成了0x0018F856,EDI存储的数据,从0x0018F85C变成了0x0018F85E。堆栈窗口中内存地址0x0018F854的数据没有发生变化,而内存地址0x0018F85C的数据发生了变化,由数据0x00000000变成了数据0x00002BA2。由于我们是按2个字节复制的,所以ESI和EDI存储的数据会自加2,数据也是复制2个字节。

对MOVSB和MOVSW分别做了实验,为了锻炼大家的动手能力,这里将不再对MOVSD做实验,希望大家能总结MOVSD的工作原理。

总结:根据对MOVSB和MOVSW的实验我们得出,MOVS指令会根据操作1字节、2字节、4字节相应的改变ESI和EDI存储的数据变化,会自动增加1、2、4。相应的内存地址存储的数据也会复制1个字节、2字节、4字节。

看到这大家有没有想过,MOVS执行后只会自增,如何才能让它自减哪?有一个寄存器可以帮忙,就是标志寄存器——EFLAGS,它的每一位代表不同的含义,后面会详细介绍它每一位代表什么。这里介绍它的第10位——DF位,也就是方向位。如果是0的时候,我们使用MOVS指令执行完后,ESI和EDI会增加相应的宽度,如果是1,表示MOVS指令执行完后,EDI和ESI会减少相应的宽度。如图2-9-7:DF位。

我们只需要双击DF位对应的数据0,那么DF位就变成了1,当然这是我们自己调试程序时用到的方法。如图2-9-8手动修改DF位。

我们实验一下,修改了DF位通过执行MOVS指令是否真的自减相应的宽度哪?

第一步:输入指令MOVSB,使用当前ESI和EDI存储的数据,如图2-9-9所示。

第二步:按F8执行,观察各数据变化,如图2-9-10所示。

F8执行完后,发现ESI和EDI存储的数据都自减1,而内存地址里对应的数据自动复制了1个字节。

如果我们批量的处理MOVS指令,相应的ESI和EDI 会增加或减少相应字节宽度,相应的内存地址也会相应的改变。自己动手观察下面的例题。

例:

主要观察ESI和EDI存储的数据变化及相关内存地址的变化。

当DF位为0时,输入以下指令:

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]      

MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]

MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]    

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]  

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]  

当DF位为1时,输入以下指令:

MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]      

MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]

MOVS WORD PTR ES:[EDI],WORD PTR DS:[ESI]    

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]  

MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]

ESI、EDI 能自增自减,这样有什么好处呢?好处就是假如我们需要复制大片内存,只需要重复编写MOVSD就可以了,接下来介绍STOS指令。

【STOS指令】

STOS指令:这个指令通常用于将某一块内存设置为特定的值。它是将AI/AX/EAX寄存器里面的值复制到[EDI]中,执行完后EDI增加或减少相应的宽度的字节。[EDI]表示把EDI中的数据当成是一个内存地址,可以说它是一个指针,指向某一块内存。它的格式如下:

[if !supportLists]1、[endif]STOS BYTE PTR ES:[EDI]简写为STOSB

[if !supportLists]2、[endif]STOS WORD PTR ES:[EDI]简写为STOSW

[if !supportLists]3、[endif]STOS DWORD PTR ES:[EDI]简写为STOSD

我们同样借助DTDebug.exe软件做实验。

第一步:打开软件,将要调试的软件拖进DTDebug.exe中,如图2-9-11所示。

第二步:输入以下指令,此时DF位为0,如图2-9-12所示。

MOV EAX,0x11223344

MOV EDI,0x0018FCEC

STOS BYTE PTR ES:[EDI]           //EDI的值+1

STOS WORD PTR ES:[EDI //EDI的值+2

STOS DWORD PTR ES:[EDI] //EDI的值+4

第三步:单步按F8观察,如图2-9-12、2-9-13、2-9-14、2-9-15、2-9-16所示。

当DF位为1时,输入一下指令。

MOV EAX,0x55667788

MOV EDI,0x0018FCEC

STOS BYTE PTR ES:[EDI]          //EDI的值-1

STOS WORD PTR ES:[EDI //EDI的值-2

STOS DWORD PTR ES:[EDI] //EDI的值-4

通过以上实验,我们总结:

当DF位为0时,STOS指令会把AL/AX/EAX存器存储的数据,存储到[EDI]指定的内存地址相对应的数据中去。相应的EDI存储的数据会增加相应的宽度1、2、4,直至AL/AX/EAX存器存储的数据变为0;

当DF位为1时,STOS指令会把AL/AX/EAX寄存器存储的数据,存储到[EDI]指定的内存地址相对应的数据中去。相应的EDI存储的数据会减少相应的宽度1、2、4,直至AL/AX/EAX存器存储的数据变为0。

我们通常用STOS来进行初始化,我们将需要初始化的值放在AI/AX/EAX寄存器中,将需要初始化的内存地址储存到EDI中。

我们介绍了2个指令一个MOVS指令、一个STOS指令,这两个指令都是为了对大量连续内存进行操作的,但是它们本身并不能重复操作,难道我们工作中要手动一行一行的输入这些指令吗?答案是否定的,所以就有了REP指令。什么是REP指令哪?我们接下来介绍REP指令。

【REP指令】

REP指令:按计数寄存器(ECX)中指定的次数重复执行字符串指令。

我们同样借助DTDebug.exe软件做实验。

第一步:打开软件,将要调试的软件拖进DTDebug.exe中。

第二步:输入以下指令,并修改ESI和EDI存储的数据。ESI改为0x0018FDE0,EDI改为0x0018FE00如图2-9-17所示:

MOV ECX,10

REP MOVSD  

第三步:按F8执行并观察数据变化,如图2-9-18、2-9-19、2-9-20所示:

接下来仔细观察REP MOVS指令的变化,由于我们复制的次数较多,按F8单步跳过(一次执行完),按F7是单步步入执行(每使用一次F7,代表程序单步执行一次),这样我们可以看到使用rep指令时,每执行一次, ECX减1,如图2-9-19(按F7)、2-9-20(按F7)、2-9-21(按F8)。

如图2-9-19第一次按F7执行,ECX当前值为F,看到ESI存储的数据变成了0x0018FDE4,EDI存储的数据变成了0x0018FE04,内存地址0x0018FDE0存储的数据没有变化,而内存地址0x0018FE00存储的数据变成了00EB2BA2。

如图2-9-20第而次按F7执行,ECX当前值为E,看到ESI存储的数据变成了0x0018FDE8,EDI存储的数据变成了0x0018FE08,内存地址0x0018FDE4存储的数据没有变化,而内存地址0x0018FE04存储的数据变成了0x11111111。


如图2-9-21按F8执行完,ECX当前值为0,看到ESI存储的数据变成了0x0018FE20,EDI存储的数据变成了0x0018FE40,相对应的内存地址的数据发生了变化。

根据实验我们得出了,当前DF位为0,REP MOVSD指令每按一次F7,ECX存储的数据减少1,对应的ESI和EDI的数据会增加4,而相对应的内存地址存储的数据复制到将要被存储的内存地址中去,且每次内存地址都会自动往下移动4个字节;

当前DF位为1,REP MOVSD指令每按一次F7,ECX存储的数据减少1,对应的ESI和EDI的数据会减4,而相对应的内存地址存储的数据复制到将要被存储的内存地址中去,且每次内存地址都会自动往上移动4个字节。

下一节为介绍堆栈相关指令。

练习:

1、使用 MOVS 指令从一个地址向另一个地址复制0x10字节的数据,分别对DF位为0时、DF位为1时做实验,并能自己总结出MOVS的工作原理

2、向某块内存中填充0x44个 0xCC,分别对DF位为0时、DF位为1时做实验。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352