抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

缓存

知识点

WC(写组合/写合并)

同一时刻只能保证4个地址;

WB(写回绕/回写)

WT(直写)

通常是做多媒体

实验代码

课程中test1比test2快, 实验是test2比test1快???

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 10_19_Cache(缓存).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>

#define ALLOCATE_SIZE 0x10000
#define MASK (ALLOCATE_SIZE - 1)

void test1()
{
PUCHAR x1 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x2 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x3 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x4 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x5 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x6 = (PUCHAR)malloc(ALLOCATE_SIZE);

int startTime = GetTickCount();
int i = INT_MAX;
while (i--)
{
int index = i & MASK;
char b = i;
x1[index] = b;
x2[index] = b;
x3[index] = b;
}

int j = INT_MAX;
while (j--)
{
int index = j & MASK;
char b = j;
x4[index] = b;
x5[index] = b;
x6[index] = b;
}
int endTime = GetTickCount();
printf("1. 一共耗时%d毫秒\r\n", endTime - startTime);
free(x1);
free(x2);
free(x3);
free(x4);
free(x5);
free(x6);
}

void test2()
{
PUCHAR x1 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x2 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x3 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x4 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x5 = (PUCHAR)malloc(ALLOCATE_SIZE);
PUCHAR x6 = (PUCHAR)malloc(ALLOCATE_SIZE);

int startTime = GetTickCount();
int i = INT_MAX;
while (i--)
{
int index = i & MASK;
char b = i;
x1[index] = b;
x2[index] = b;
x3[index] = b;
x4[index] = b;
x5[index] = b;
x6[index] = b;
}

int endTime = GetTickCount();
printf("2. 一共耗时%d毫秒\r\n", endTime - startTime);
free(x1);
free(x2);
free(x3);
free(x4);
free(x5);
free(x6);
}


int main()
{
test1();
test2();
test1();
test2();
test1();
test2();

system("pause");
return 0;
}

PAT

TLB

每个核有4个TLB, 2个数据核(dTLB), 2个指令TLB(iTLB);

实验步骤

  1. 申请2个地址, 分别赋值;
  2. 把第一个地址挂在0地址上, 然后访问, 取出结果保存变量;
  3. 又把第二个地址挂在0地址上, 然后访问, 取出结果也保存变量;
  4. 观察变量1, 变量2有什么不同;

401080
gdtr: 0040ec00`00081080

实验代码

代码出现问题, 获取0地址时为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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// 10_21_TLB.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>

PUCHAR addr1 = NULL;
PUCHAR addr2 = NULL;
ULONG temp1 = 0, temp2 = 0;

void __declspec(naked) test()
{
__asm
{
pushad;
pushfd;
push 0x30;
pop fs;


mov eax, [addr1]; // 线形地址1, 使用原始汇编代码, 注释代码会导致系统蓝屏
shr eax, 0x9;
and eax, 0x7ffff8;
mov ecx, [eax-0x3FFFFFFC];
sub eax, 0x40000000;
mov ecx, [eax];
mov edx, [eax + 4];

//and eax, 0xC0000000;
//int 3;
//mov ecx, [eax]; // 取低4字节
//mov edx, [eax + 4]; // 取高4字节

mov dword ptr ds:[0xC0000000], ecx;
mov dword ptr ds:[0xC0000004], edx;
mov eax, dword ptr ds:[0];
int 3;
mov [temp1], eax;

mov eax, cr3; //刷新cr3
mov cr3, eax; // 刷新cr3

//mov eax, [addr2]; // 线形地址2
//shr eax, 0x9;
//and eax, 0x7ffff8;
//and eax, 0xC0000000;
//mov ecx, [eax]; // 取低4字节
//mov edx, [eax + 4]; // 取高4字节

//mov dword ptr ds : [0xC0000000], ecx;
//mov dword ptr ds : [0xC0000004], edx;
//mov eax, dword ptr ds : [0];
//mov [temp2], eax;

push 0x3b;
pop fs;
popfd;
popad;
retf;
}
}

int main()
{
addr1 = (PUCHAR)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
addr2 = (PUCHAR)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

*(PUCHAR)addr1 = 0x1000;
*(PUCHAR)addr2 = 0x2000;

temp1 = 0;
temp2 = 0;

printf("addr1 = %x, addr2 = %x, test = %x\r\n", addr1, addr2, test);
system("pause");

char bufcode[6] = { 0,0,0,0,0x4b,0 };
__asm
{
// push fs;
call fword ptr bufcode;
// pop fs;
}
printf("temp1 = %x, temp2 = %x\r\n", temp1, temp2);

system("pause");
return 0;
}

刷新CR3

  1. 当切换CR3的时候, CPU就认为在切换不同的页表; 当页表发生变化的时候, TLB就会产生一个刷新; 凡是G位等于0的通通刷新掉; 刷新除G位为1的情况;
    切换线程的时候, 判断当前被切换与切换是否是一个进程, 如果不是, 会切换页表(CR3);
1
2
mov eax, cr3;	//刷新cr3
mov cr3, eax; // 刷新cr3
  1. 把地址变为无效缓存; 刷新一条
1
invlpg dword ptr ds:[0];		// 强制刷新TLB中某一行
  1. CR4控制寄存器中有一个PGE位, 这个是控制所有的G位是否有效; 刷新所有;

评论