y = %d --> z = %d", x,y,z);return 0;} 反汇编结果如。C++ 反汇编:数据类型与常量( 二 )。" />

C++ 反汇编:数据类型与常量( 二 )

<&printf>]|0041142E | 83C4 0C| add esp,0xC|
字符与字符串变量:
#include int main(int argc, char* argv[]){char x = 'a', y = 'b',z = 'c';printf("x = %d --> y = %d --> z = %d", x,y,z);return 0;}
反汇编结果如下,观察发现字符型的表现形式与整数类型基本一致,只是在数据位大小方面有所区别,如上int类型使用dword作为存储单位,而字符类型则默认使用byte形式存储 。

C++ 反汇编:数据类型与常量

文章插图
004113CC | 8DBD 1CFFFFFF| lea edi,dword ptr ss:[ebp-0xE4]|004113D2 | B9 39000000| mov ecx,0x39|004113D7 | B8 CCCCCCCC| mov eax,0xCCCCCCCC|004113DC | F3:AB| rep stosd|004113DE | C645 FB 61| mov byte ptr ss:[ebp-0x5],0x61| 第一个字符004113E2 | C645 EF 62| mov byte ptr ss:[ebp-0x11],0x62| 第二个字符004113E6 | C645 E3 63| mov byte ptr ss:[ebp-0x1D],0x63| 第三个字符004113EA | 0FBE45 E3| movsx eax,byte ptr ss:[ebp-0x1D]| 拷贝第三个字符004113EE | 8BF4| mov esi,esp| esi:__enc$textbss$end+109004113F0 | 50| push eax|004113F1 | 0FBE4D EF| movsx ecx,byte ptr ss:[ebp-0x11]| 拷贝第二个字符004113F5 | 51| push ecx|004113F6 | 0FBE55 FB| movsx edx,byte ptr ss:[ebp-0x5]| 拷贝第一个字符004113FA | 52| push edx|004113FB | 68 58584100| push consoleapplication1.415858| 415858:"x = %d --> y = %d --> z = %d"00411400 | FF15 14914100| call dword ptr ds:[<&printf>]| 打印输出00411406 | 83C4 10| add esp,0x10|
虽然使用的是byte存储一个字符,但是每一个字符在分配上还是占用了12个字节的空间4x3=12,编译器并没有因为它是一个字符而区别对待,同样是采用了4字节的分配风格.
反汇编第一种形式的字符串类型,发现首先会从常量字符串中ds:[]取出前四个字节子串,并将其压入堆栈中,然后再循环后四个字节子串并压栈,最后取出第一个字符串的堆栈地址并输出打印,该方法只适用于小字符串.
004113E8 | A1 58584100| mov eax,dword ptr ds:[0x415858]| 在常量字符串中取出数据 "hell"004113ED | 8945 E8| mov dword ptr ss:[ebp-0x18],eax| 将常量前面的hell压栈004113F0 | 8B0D 5C584100| mov ecx,dword ptr ds:[0x41585C]| 继续压栈 "o lyshark"004113F6 | 894D EC| mov dword ptr ss:[ebp-0x14],ecx|004113F9 | 8B15 60584100| mov edx,dword ptr ds:[0x415860]| 00415860:"shark"004113FF | 8955 F0| mov dword ptr ss:[ebp-0x10],edx|00411402 | 66:A1 64584100| mov ax,word ptr ds:[0x415864]| 00415864:L"k"00411408 | 66:8945 F4| mov word ptr ss:[ebp-0xC],ax| 最后将剩下的一个字单位压栈0041140C | 8BF4| mov esi,esp| main.c:80041140E | 8D45 E8| lea eax,dword ptr ss:[ebp-0x18]| 取出hell的内存地址作为首地址使用00411411 | 50| push eax|00411412 | 68 68584100| push consoleapplication1.415868| 415868:"短字符串: %s\n"00411417 | FF15 14914100| call dword ptr ds:[<&printf>]| 打印输出0041141D | 83C4 08| add esp,0x8|
反汇编长字符串与字符串指针,由于这两个类型具有很强的对比性所以放在一起,第1种字符串数组存储,可以看到内部是通过拷贝内存实现的,而第2种指针方式则是直接引用常量地址,从效率上来说指针效率更高,因为没有拷贝造成的性能损失.
004113E5 | 8945 FC| mov dword ptr ss:[ebp-0x4],eax|004113E8 | B9 06000000| mov ecx,0x6| 循环拷贝6次004113ED | BE 58584100| mov esi,0x415858| 字符串常量地址004113F2 | 8D7D DC| lea edi,dword ptr ss:[ebp-0x24]| 取出初始化的内存空间首地址004113F5 | F3:A5| rep movsd| 循环拷贝6次004113F7 | 66:A5| movsw| 单独拷贝最后的y字符004113F9 | C745 D0 78584100| mov dword ptr ss:[ebp-0x30],0x415858| 取字符串常量地址00411400 | 8BF4| mov esi,esp| main.c:800411402 | 8D45 DC| lea eax,dword ptr ss:[ebp-0x24]| 通过指针指向字符串首地址00411405 | 50| push eax|00411406 | 68 98584100| push consoleapplication1.415898| 415898:"长字符串: %s\n"0041140B | FF15 14914100| call dword ptr ds:[