0%

7-C语言数据类型

C语言数据类型

裸函数

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

}

跟空函数不一样

1
2
3
4
void Plus()
{

}

裸函数依旧是个call,不过里面没有内容

1
2
3
4
void __declspec(naked) Plus()
{
__asm ret
}

这样的就可以正常运行,因为这样会retn

手写汇编实现Add函数

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
int __declspec(naked) Plus(int x, int y)
{
__asm
{
push ebp
mov ebp,esp
sub esp,0x40

push ebx
push edi
push esi

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 esi
pop edi
pop ebx

mov esp,ebp
pop ebp

ret
}
}

调用约定

调用约定参数压栈顺序平衡堆栈
__cdecl从右至左入栈调用者清理栈
__stdcall从右至左入栈自身清理堆栈
__fastcallECX/EDX传送前两个 剩下:从右至左入栈自身清理堆栈

__cdecl

外平衡

1
2
3
4
push 1
push 2
call
add esp,8
1
2
3
4
int __cdecl Plus(int a,int b)
{
return a+b;
}

__stdcall

内平衡

1
2
3
push 1
push 2
call //call里平衡 ret
1
2
3
4
int __stdcall Plus(int a,int b)
{
return a+b;
}

__fastcall

利用寄存器传参

1
2
3
mov edx,2
mov ecx,1
call
1
2
3
4
int __fastcall Plus(int a, int b)
{
return a+b;
}

裸函数实现

1
2
3
4
5
6
7
int plus(int x, int y, int z)
{
int a=2;
int b=3;
int c=4;
return x+y+z+a+b+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
int __declspec(naked) Plus(int x, int y,int z)
{
__asm
{
push ebp
mov ebp,esp
sub esp,0x40

push ebx
push edi
push esi

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

mov eax,2
add eax,3
add eax,4
add eax,dword ptr ds:[ebp+0x8]
add eax,dword ptr ds:[ebp+0xc]
add eax,dword ptr ds:[ebp+0x10]

pop esi
pop edi
pop ebx

mov esp,ebp
pop ebp

ret
}
}

可以修改入口点

入口点实际不是main

link->entrypoint

查找main方法,可以push 3个参数的

数据类型与数据存储

C语言数据类型汇编数据宽度
charbyte
shortword
intdword
longdword
  1. 无符号跟有符号,在内存中存储的是一样的,根据使用的人来决定

  2. 默认有符号,类型转换–比较大小–数学运算要注意

  3. 有符号跟无符号,比较会改掉,jbe跟jle 低于等于,小于等于

浮点类型

这部分就是计算机组成原理

float的存储方法

12.5 在内存中存储为

整数部分: 12

计算余数
12/2=60
6/2=30
3/2=11
1/2=01

从下往上: 1100

小数部分: 0.5

计算小数
0.5*2=1.01

从上往下:1

1100.1=1.1001*2的3次方

1位符号位 中间8位指数 后面23位尾数

尾数从左往右写就行

中间8位开头,左移为1,右移为0,

后面7位,存储指数-1,比如3次方,就是存10,如果是-2次方就是-3,也就是fd, 11111101,然后只取后7位

127 +(3) = 130 = 0x82 = 1000 0010 这里直接加指数

0 10000010 10010000000000000000000

0100 0001 0100 1000 0000 0000 0000 0000

41480000

如果是-12.5呢

就变成

1100 0001 0100 1000 0000 0000 0000 0000

C1480000

将CallingConvention.exe逆向成C语言

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall Add5(int num1, int num2, int num3, int num4, int num5)
{
int result1 = Add3(num1, num2, num3);//8
int result2 = Add2(num1, num2);//4
return Add2(result1, result2);//12=c
}

int __cdecl Add2(int num1, int num2)
{
return num1+num2;
}

int __stdcall Add3(int num1, int num2, int num3)
{
return num1+num2+num3;
}
int main()
{
int result1 = Add5(1,3,4,6,7);
printf("%d", result1);
}

编码

ASCII 英文字符

GB2312或GB2312-80 中文字符,两个字节一个汉字

练习

截取字符串

比如 china中国verygood天朝nice

fn(5) = china

fn(6) = china中

fn(8) = china中国v

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
#include <stdio.h>
#include <string.h>

char str[]= {"china中国verygood天朝nice"};

int getString(int length)
{
int have=0;
int all = sizeof(str)/sizeof(char);
// 不能超过length,和总长度all
char temp[3];
for(int i=0; have < length && i < all; i++)
{
if(str[i] >= 'A' && str[i] <= 'z')
{
printf("%c", str[i]);
}
else
{
printf("%c%c%c", str[i], str[i+1], str[i+2]);
i += 2;
}
have += 1;

}
}
int main()
{
getString(16);
return 0;
}

指针做乘法运算

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
int a=1;
int *result = (int *)((long)&a * 32) ;
printf("%p", result);
return 0;
}

原来强转int *老是说信息丢失报错,改成long就不报错了

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/27709fc2/
版权声明:转载请注明出处!