C语言-数据类型

裸函数

编译器不做任何分配,配合钩子执行自己想要的效果

普通的C程序可以正常执行,但是如下裸函数不允许直接调用

1
2
3
4
void __declspec(naked) Add()
{

}

image-20230423093531484

修改裸函数为普通C程序的运行模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int __declspec(naked) Add(int x,int y)
{
__asm
{
push ebp

mov ebp,esp
sub esp,40

push ebx
push esi
push edi

mov eax,0xcccccccc
mov ecx,0x10
lea edi,dword ptr ds:[ebp-0x40]
rep stosd

mov eax,dword ptr ds:[ebp+0x8]
add eax,dword ptr ds:[ebp+0xc]

pop edi
pop esi
pop ebx

mov esp,ebp
pop ebp

ret
}
}

int main(int argc, char* argv[])
{
Add(1,2);
return 0;

}

image-20230423093743667

调用约定

image-20230422182006824

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int __cdecl ADD1(int x,int y)
{
return x + y;
}

int __stdcall ADD2(int x,int y)
{
return x + y;
}

int __fastcall ADD3(int x,int y)
{
return x + y;
}

int main(int argc, char* argv[])
{
ADD1(1,2);
return 0;

}

__cdecl C语言默认的约定

image-20230423095441728

__stdcall windowsapi用的约定

image-20230423095515072

image-20230423095549761

__fastcall 快速处理参数入栈(注意参数不能超过两个,不然没有足够的寄存器传参还是要用内存)

image-20230423095719985

数据类型与数据存储

三要素

宽度

格式

作用域

数据类型

基本类型

整数类型

浮点类型

构造类型

数组类型

结构体类型

共用体类型

空类型

void

指针类型

数据存储形式

整数

char=byte

short=word

int=long=dword

有符号数与无符号数在比较大小,数学运算和类型转换的时候需要注意

有符号数

char i = 0xff; 默认就是有符号数

无符号数

unsigned char i = 0xff

image-20230423123949631

运算的时候编译器会根据程序员确定的是有符号数还是无符号数来调用不同的JCC指令运算,但是不管有符号数还是无符号数,数据在内存里存储的值是一致的

浮点数

float(四字节)
1
2
3
4
5
6
7
8
9
10
11
12
13
// Test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


int main(int argc, char* argv[])
{
float a = 8.25f;

return 0;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
8.25--十进制

浮点数存储在内存中由三部分组成

1、先将这个数的绝对值转化为二进制
从下向上计位
8/2 0 |
4/2 0 |
2/2 0 |
1/2 1 |
从上向下计位(遇到0.4这种无限循环的小数部分根据精度有最大存储精度)
0.25*2=0.5 0
0.5*2=1.0 1

8.24----->1000.01


21000.01左移三位,相当于1.00001乘以2的三次方,指数为3,左移还是右移需要判断有效位,要把小数点移动到第一个有效位的右侧,比如整数部分为0,那么我们需要有效位为1的地方就需要右移,左移是正数,右移是负数


3、 小数点右侧第一个数开始数23个数放入尾数部分。
指数部分,左移第一位填1,右移就是0,剩余的七位用移动了几位减1
符号位:区分正数与负数,正数存0,负数存1

4、根据 符号位 指数部分 尾数部分的格式转换二进制为十六进制

image-20230423170110685

image-20230423165733972

-8.25只需要把符号位变为1即可,

image-20230423170356344

image-20230423170344497

0.25

image-20230423171445852

image-20230423171531164

double