【滴水逆向笔记】第十一章 C语言数据类型及堆栈


前言

C语言结构复习一下。。。

返回值得类型 函数名(参数类型 参数名,参数类型 参数名)
{
    
    
    //如果前面是void,不用return
    //如果有:
    return 11}

一、C是如何变成汇编的?

1.裸函数

void  __declspec(naked) Function()
{
    
    


}

上述结构叫做裸函数实验1
键入上行代码,F7,F5之后,直接F11,一直按F11,发现直接没了
因为这个裸函数一行代码都没有生成,编译器不管你
裸函数应用:
如何变成二进制

2.C变成汇编

在处理缓冲区后

push 2
push 1

通过【ebp+8】来找到第一个数这些就是函数参数,此时入栈

局部变量存储在缓冲区里
而返回值一般存储在EAX里面

在VC6里面输入如下

//保留调用函数前的堆栈
push ebp
mov ebp,esp
sub esp,0x40
//保存现场
push ebx
push esi
push edi
//填充缓冲区
mov eax,0xccc
mov ecx,0x40
lea edi,dword ptr ds:[ebp-0x40]
rep stosd
//函数功效
mov eax,dword ptr ds:[ebp+8]
add eax.dword ptr ds:[ebp+c]
//恢复现场
pop edi
pop esi
pop ebx
//恢复栈堆
mov esp,ebp
pop ebp

ret

发现可以执行,说明了编译器把C变成汇编

3.调用约定

在这里插入图片描述

cdecl

int _cdecl plus1(int x, int y) 
{
    
    
    return x + y;

}

在这里插入图片描述
谁调用函数,谁平衡堆栈
C和的C++默认的调用约定

stdcall

int _stdcall plus1(int x, int y)
{
    
    
    return x + y;

}


在这里插入图片描述
这里没有平衡堆栈,但是在之前有在这里插入图片描述
相当于ret后,esp+8,在函数里面平衡,叫内平栈

fastcall

寄存器读写速度快,所以这里是fast,比之前堆栈(内存)快

int _fastcall plus1(int x, int y)
{
    
    
    return x + y;

}

在这里插入图片描述
用寄存器存的,不涉及堆栈,所以没有弄堆栈平衡在这里插入图片描述
但是超过两个数仍然push
在这里插入图片描述
所以别整太多参数,传两个才能保证传输效率
最后平衡堆栈是是ret 8

二、函数入口

1.调用堆栈

函数真正的入口是call stack(调用堆栈窗口)里显示的mainCRTstartup
mainCRTstartup做了很多事情,都是控制台程序必须要用的,所以不能替换

void plus(){
    
    


}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

此处main函数的窗口如图
在这里插入图片描述
VC6的编译器变成三个参数,调用main方法的函数进行了获取命令行,获取版本信息

2.找main函数方法

在这里插入图片描述
看到getcommandLineA,往下找三个参数的
在这里插入图片描述
因为最后平衡堆栈是ESP+8,所以是三个参数,main方法

三.数据类型

在这里插入图片描述

1.基本类型

有整数类型和浮点类型

整数类型

char short int long
在这里插入图片描述
如图,为整数类型的宽度对应及其字节大小
在这里插入图片描述
如图,为汇编
如果超出了宽度,则取最后两个字节输入如下代码

void Plus1()
{
    
    
    char i = 0x12345678;
    short x = 0x12345678;
    int i = 0x12345678;
}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

栈堆中的结果28-char 24-short 20-int在这里插入图片描述
整数类型区分为有符号和无符号
当什么都不写,默认有符号

void Plus1()
{
    
    
    char i = 0xFF;
    unsigned k = 0xFF;
}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

这里unsigned默认四个字节,如果unsign char就是一个字节

void Plus1()
{
    
    
    char i = 0xFF;
    unsigned k = 0xFF;
    printf("%d",i);
    printf("%d",k);
}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

这里打印出来,i和K的值分别是-1,255
也可以比较大小

void Plus1()
{
    
    
    char i = 0xFF;
    char k = 1;
    if(i>k){
    
    
        printf("i>k");
    }
    else{
    
    
        printf("i<k");
    }
  
}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

运行,结果是i<k

void Plus1()
{
    
    
    unsigned char i = 0xFF;
    unsigned char k = 1;
    if(i>k){
    
    
        printf("i>k");
    }
    else{
    
    
        printf("i<k");
    }
  
}
int main(int argc,char* argv[])
{
    
    
    plus();
    return 0;
}

运行结果是i>k
if语句编译:

void Plus1( char i ,char k = 1)
{
    
    
   
    
    if(i>k){
    
    
        printf("i>k");
    }
    else{
    
    
        printf("i<k");
    }
  
}
int main(int argc,char* argv[])
{
    
    
    plus(0xFF,1);
    return 0;
}

这种编译结果在这里插入图片描述

void Plus1(unsigned  char i ,unsigned char k)
{
    
    
   
    
    if(i>k){
    
    
        printf("i>k");
    }
    else{
    
    
        printf("i<k");
    }
  
}
int main(int argc,char* argv[])
{
    
    
    plus(0xFF,1);
    return 0;
}

这种编译结果:
在这里插入图片描述

浮点类型

float double

void Plus1()
{
    
    
   
    
   float i = 12.5f
}
int main(int argc,char* argv[])
{
    
    
    plus(0xFF,1);
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
例子:
在这里插入图片描述
三个部分,前三步对应后半部分,456,对应前两个部分
在这里插入图片描述

duoble是这样存:
在这里插入图片描述
套用float的模板就行了

英文字符存储

void Plus()
{
    
    

    char c = 'A';
}
int main(int argc, char*argv[])
{
    
    
    plus();
}

转化位ascii编码存储,在汇编中是这样存的
在这里插入图片描述
编译器帮我们做了这些事情

中文字符存储

char* x ='啊';
char* y ='北';

在这里插入图片描述
相当于用两个ASCII码
将上面的代码改一下

void Plus()
{
    
    

    char c = '中';
}
int main(int argc, char*argv[])
{
    
    
    plus();
}

但是这样没有意义,因为char类型的字符变量只能存储一个字节
在这里插入图片描述
但是这样写,就能存进去中文:

void Plus()
{
    
    

    char * c = '中';
}
int main(int argc, char*argv[])
{
    
    
    plus();
}

猜你喜欢

转载自blog.csdn.net/qq_46441427/article/details/113004474