- 博客(646)
- 收藏
- 关注
原创 C语言完美演绎3-13
* 若省略double,内定型态为int */printf("圆圈的面积 = %3.2f", circle);/* 范例:3-13 const定义PI用以计算圆的面积 */圆圈的面积 = 127.88。
2026-03-13 08:51:19
89
原创 C语言完美演绎3-12
printf("科学符号表示法的浮点数:%e\n",62.2);/* 科学符号表示法的浮点数 */printf("一般的浮点数:%f\n", 62.2);/* 纯粹带有小数点的浮点数*/科学符号表示法的浮点数:6.220000e+01。一般的浮点数:62.200000。/* 范例:3-12 */
2026-03-13 08:50:49
118
原创 C语言完美演绎3-11
printf("字符串C Language总共占%d bytes\n", sizeof(chars));/* 字符串"C Language"中字符C到e,再加上\0后,就占11个空间 *//* 定义一个char类型的数组,并将"C Language"设为初值 */字符串C Language总共占11 bytes。/* 范例:3-11 */
2026-03-12 20:15:00
483
原创 C语言完美演绎3-9
*(\t)跳格字符,看你Tab一次设定跳几格,当编译到(\t)时就会跳格,另外如果你没有自己设定的话是跳8格.*/printf("换码字符将使其后的字符串消失\n\0=>消失的字符串");printf("在两个逗号之后加上退格字符,,\b所产生的结果\n");printf("\"加油,C语言将越来越有趣,不懂就问\" \n");printf("什\t么\t叫\t作\tTab\n");/* (\a)是响铃,会听到Beep一声,(\n)换行 *//* (\b)将会使字符串退一格,吃掉一个逗号 */
2026-03-11 19:32:43
307
原创 C语言完美演绎3—8
* 字符'a'的ASCII码为97,再加上1后ASCII码成为98,字符也就变成'b' */printf("'a'+1后的ASCII码:%d \n", ch);/* 定义ch变量为字符类型,并给ch变量一个初值'a' */printf("'a'+1后的字符是:%c", ch);'a'+1后的ASCII码:98。/* 范例:3-8 */'a'+1后的字符:b。
2026-03-11 19:32:11
314
原创 C语言完美演绎3-7
printf("ASCII:%d 字符:%c\n", a, a);/* ASCII码97~102所对应的字符 */ASCII:100 字符:d。ASCII:101 字符:e。ASCII:102 字符:f。ASCII:97 字符:a。ASCII:98 字符:b。ASCII:99 字符:c。/* 范例:3-7 */
2026-03-10 21:51:38
308
原创 C语言完美演绎3-6
printf("十六进制:0X74 ==> 十进制:%d\n", 0X74);printf("八进制:074 ==> 十进制:%d\n", 074);printf("十进制:116 ==> 十六进制:%x\n", 116);/* 十进制的116转换成十六进制的74 *//* 八进制的074转换成十进制的60 *//* 十进制的60转换成八进制的74 */printf("十进制:60 ==> 八进制:%o\n", 60);十六进制:0X74 ==> 十进制:116。十进制:60 ==> 八进制:74。
2026-03-10 21:51:07
111
原创 C语言完美演绎3-5
* 局部变量,定义myWeather是seasons的型态 *//* 全局变量,定义weather是seasons的型态 *//* 把weather设定成spring */spring, summer, fall, winter /* 自定义的成员 *//* 局部变量,定义为整数类型 *//* 设定a的初值是10 */enum seasons /* 结构声明,自定义文件类型 */#define PI 3.14159 /* 宏常量声明 *//* 范例:3-5 */
2026-03-09 15:51:51
129
原创 C语言完美演绎3—4
printf("1~100的总和等于%d", sum);/* 使用printf()函数,输出sum的总和 */getchar();/* getchar() 读取字符的函数,会使你屏幕停住,后面章节会讲 */for(int a=1;a=a+1) // 缩进,把同一级的对齐。/* for循环属于流程控制,在稍后章节会详细介绍 *//* 将值返回给系统 *//*-------单行注释----------*///--------单行注释。/*-------多行注释。/* 范例:3-4 */
2026-03-09 15:51:07
86
原创 C语言完美演绎3-3
include "my_Include.h" /* 自编的include文件位置与文件名,C会将其展开 *//* 调用定义在自编include文件内的函数 *//* stdio.h已由my_include.h包含 *//* circle()宏函数也是定义在my_include.h文件内,浮点数取至小数点后7位 */printf("可将内建函数的include文件展开在自编的include文件中\n");/* 范例:3-3 执行前请确定my_Include.h存放在同一个目录 */
2026-03-08 19:43:13
35
原创 c语言完美演绎3-2
include<stdio.h> /* 标准输入输出头文件,此行经编译后会将stdio.h"展开" */printf("需要有头文件<stdio.h>才能使用printf()作输出的功能\n");void main(void) /* 主函数(程序进入点) *//* 范例:3-2 */
2026-03-08 19:40:37
121
原创 C语言完美演绎3-1
void sort_num(int x,int y,int z) /* sort_num函数定义在main()之后 *//* 在main()主函数中调用sort_num(a, b, c) */int main(int argc, char* argv[]) /* 程序进入点 */printf("由大至小排序之后的结果:%d %d %d", x, y, z);/* sort_num()的作用是将x、y、z 三数由大至小排序及打印 *//* sort_num()函数定义在调用之后,所以要声明其原型*/
2026-03-07 20:13:12
199
原创 C语言完美演绎1
define circle(radius) (PI*radius*radius) /* 宏函数,圆的面积 */#include <stdio.h> /* 展开C语言的内建函数指令 */#define PI 3.1415926 /* 宏常量,在稍后章节再详解 */printf("由小至大排序之后的结果:%d %d %d\n", a, b, c);/* 将比较数值大小的函数写在自编include文件内 *//* 头文件:my_Include.h */
2026-03-07 20:12:31
95
原创 第3章 Windows运行机理-3.5 PE结构分析(7)
如果高位(0x80000000)被置为1,则该目录项对应一个子目录,低31个二进制数是一个相对于另一个IMAGE_RESOURCE_DIRECTORY结构的偏移量(相对于资源的开始处)。如果高位置为0,则低31位是一个相对于一个IMAGE_RESOURCE_DATA_ENTRY结构的偏移量(相对于该资源节)。如果高位非零,则低的31个二进制数是相对于一个IMAGE_RESOURCE_DIR_STRING_U结构的偏移量(相对资源节的开始处)。在第三层上,有一个图标、一个图标组、一个菜单以及其他等资源。
2026-03-06 17:03:19
328
原创 第3章 Windows运行机理-3.5 PE结构分析(6)
例如,若发现匹配名字的RVA存放在AddressOfNames 数组的第54个元素,那就提取AddressOfNameOrdinals数组的第54个元素作为索引值。 IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]:该域形式上并不是IMAGE_RESOURCE_DIRECTORY_ENTRY结构的部分,而是紧跟其后的一个IMAGE_RESOURCE_DIRECTORY_ ENTRY结构数组。资源目录结构很像磁盘的目录。
2026-03-06 17:02:43
615
原创 第3章 Windows运行机理-3.5 PE结构分析(5)
PE参考指出使用到地址数组的索引作为联接,因此,PE装载器在名字数组中找到匹配名字的同时,它也获取了指向地址表中对应元素的索引。为了起到连接作用,名字数组和索引数组必须并行地成对使用,譬如,索引数组的第一个元素必定含有第一个名字的索引,以此类推。该AddressOfFunctions数组是一个索引值的数组,该索引将用在AddressOfFunctions数组中。例如(假定序数起始值为1),具有引出序数为1的函数的地址将在该数组的第一个元素中,则引出序数是2的函数的地址存在该数组的第二个元素中,依次类推。
2026-03-05 21:13:59
392
原创 第3章 Windows运行机理-3.5 PE结构分析(4)
简单地在该IMAGE_IMPORT_DESCRIPTOR数组(它的每一元素对应一个引入的DLL)上反复进行如下操作就可达到目的:对每个IMAGE_IMPORT_DESCRIPTOR,找出IMAGE_THUNK_DATA DWORD数组的位置并适当地解释它们。当你稍后连接一个用了该引入库的PE文件时,给引入库中的替换具有和被引入的函数相同的名字。如果一个函数用名字来引入,则它的IMAGE_THUNK_DATA DWORD含一个RVA,该RVA是IMAGE_IMPORT_BY_NAME结构所要用到的。
2026-03-05 21:13:29
444
原创 第3章 Windows运行机理-3.5 PE结构分析(3)
对于该数组,没有任何计数来指示该数组中结构的数目,数组的最后一个元素是通过在最后域中填入NULL的一个IMAGE_IMPORT_DESCRIPTOR来表示的。例如,在Windows中,KERNEL32.DLL把它的一些引出函数传递给NTDLL.DLL,一个应用程序或许认为它调用了KERNEL32.DLL中的一个函数,但实际上它的调用进入到了NTDLL.DLL中。.reloc节实际上是记录了映像中一些位置的一张表,在这些位置上,连接器所假定的装载地址和实际装载地址之间的差别需要考虑。8. .reloc节。
2026-03-04 18:52:12
476
原创 第3章 Windows运行机理-3.5 PE结构分析(2)
在.text节中,除了我用编译器创建的和从运行时间库中用到的外,还有另外附加的代码时,我感到很惊奇。在PE文件中,当你调用另一个模块中的函数(例如USER32.DLL的GetMessage())时,编译器产生的CALL指令并不是把控制直接传给DLL中的该函数。在Win32中,变量pfnGetMessage结果存的是在.text节中转换了的JMP DWORD PTR[XXXXXXXX]的地址。正像.text是代码的默认节一样,.data节就是初始化了的数据所在的地方。该节等价于NE文件的一个模块访问表。
2026-03-04 18:51:01
322
原创 第3章 Windows运行机理-3.5 PE结构分析(1)
重要的不是数据/代码是如何使用的,如果PE文件中的数据/代码拥有相同属性,它们就能被归入同一节中。在一个EXE中,它保存代码或数据节的虚拟尺寸,这是调整到最接近文件对齐值倍数的尺寸,本结构中后面的SizeOfRawData域保存这个对齐值。对于OBJ文件,该域指示本节的物理地址。那是因为在这种情况下,你将有整个文件的一个完全线性映射,因此你将在该偏移处找到本节的数据,而不是用VirtualAddress域指定的RVA。取而代之的是,节表的每一项存储一个地址,该地址是文件的生数据被影射入内存所在位置的地址。
2026-03-02 19:41:50
932
原创 第3章 Windows运行机理-3.4 线程的机制(7)
该数组的目的是允许装载器可迅速地找到一个映像的特定节(例如引入函数表),而不必遍历映像的每一个节并逐一比较它们的名字。如果你对CreateThread()指定一个0作为栈的大小,结果线程仍是得到一个域默认值相同的栈。DllCharacteristics (在NT 3.5中标为obsolete)指示什么情况下一个DLL的初始化函数,例如DllMain()要被调用的标志集合。在微软连接器中,该域默认值是0x1000字节(1页),而TLINK默认为0x2000字节(2页)。目前的工具总把该域的值置为16。
2026-03-02 19:40:50
322
原创 第3章 Windows运行机理-3.4 线程的机制(6)
因为在Windows操作系统中,总是把可执行程序安装到虚拟空间中去,每个虚拟空间在逻辑上都是相对独立的,不相干的。例如,如果该值是4096 (1000h),那么每节的起始地址必须是4096的倍数。例如,如果该值是(200h),,那么每节的起始地址必须是512的倍数。若您要改变整个执行的流程,可以将该值指定到新的RVA,这样,新RVA处的指令首先被执行。最后一节的尾端是被调整为最接近节对齐值的倍数的。SizeOfInitializedData表示由初始化的数据(不包括代码段)组成的所有节的总尺寸。
2026-03-01 17:28:18
1029
原创 第3章 Windows运行机理-3.4 线程的机制(5)
在可执行文件中,它是紧随该结构的image_file_header结构的大小。该域只用在OBJ文件和带有COFF调试信息的PE文件中,此信息只在调试文件中有用。NumberOfSymbols表示在COFF符号表中的符号数目,参见前一个域,此信息只在调试文件中有用。主PE头标是一个IMAGE_NT_HEADERS类型的结构,该类型在WINNT.H中定义。其他字段的意义是和DOS头有关的字节,这里没有什么大的作用,就不做介绍了。这个结构的域只包含了关于文件的最基本的信息。我们常见的意义如下。
2026-03-01 17:27:42
850
原创 第3章 Windows运行机理-3.4 线程的机制(3)
该调用包括同时有多少线程使用资源或代码,如果其他线程在另一个进程中,可调用OpenSemaphore去获得一个可利用的HANDLE,当一个线程需要访问共享资源时,要把资源传递给WaitForSingleObject,如果这个Semaphore没有被等待的所有线程请求,等待功能将简单处理Semaphore的使用数,且线程继续执行。除Critical Section外,其余是系统全局对象,并且与不同进程及相同进程中的线程一起工作,这样,同步机也可以用于分离进程的同步活动(同一进程内部的线程除外)。
2026-02-28 15:23:35
459
原创 第3章 Windows运行机理-3.4 线程的机制(2)
这样就不会发生冲突了。因为在C的库中有全局变量,这样用C的库时,如果程序中使用了标准的C的库时,就很容易导致运行不正常,会引起很多的冲突。因为当线程的函数用到了C的标准库的时候,很容易导致冲突,所以在创建VC的工程时,系统提示是用单线程还是用多线程的库,因为在C的内部有很多的全局变量。Win16中,一个正在运行的程序被称为一个任务(task),16位的KERNEL把每一个Win16任务的信息保持在一个叫任务数据库(TDB)的段内,任务数据库的选择器被认为是一个HTASK,通过它可获知正在执行任务的API。
2026-02-28 15:22:56
489
原创 第3章 Windows运行机理-3.4 线程的机制(1)
一个线程被切换有两个原因,原因之一是本线程需要另一个线程先执行,此时,当前线程则把CPU让给另一个线程。Windows 95的时间片是20毫秒,也就是说,一秒钟内,理论上可在50个线程之间进行强制切换,但如果所有的线程都主动放弃CPU或等待系统,则切换的频率就会很高,每秒切换4、5千次也不奇怪。例如,如下是一个文件复制的程序,这个程序由两个线程组成,一个是复制文件的线程,另一个是显示文件复制进度的过程。每一个线程被分配到一个进程中,当操作系统产生一个新的进程时,也要设置一个初始线程。那怎么处理这个问题呢?
2026-02-27 12:50:11
433
原创 第3章 Windows运行机理-3.3 GDI的结构和组成(2)
如果显示卡的内存比较大,如图3.6所示,有一块区域是映像到屏幕上的可见区域,还有的显存区域是屏幕上看不见的,这个区域被称为offscreen。B区域实际上是被隐藏在后面的,就像DOS的游戏一样,先在次显存绘制好图形,当需要显示时,马上就可以切换过来。DirectDraw中有一个这种操作函数,这个命令如果能切换,就直接切换,如果不能直接地切换,就直接通过显示卡,从次缓存复制到主缓存,这种在显卡内的复制要比软件的memcpy命令快很多。如果需要快速地显示图像,就不能用GDI,而应直接使用DirectDraw。
2026-02-27 12:49:33
345
原创 第3章 Windows运行机理-3.3 GDI的结构和组成(1)
在Windows 3.1中,只有5个系统的HDC,在Windows 98下又扩充了几个,它们组成了一个HDC的池。当系统要使用HDC的资源时,系统会随机地从这5个中选取其中一个没有被占用的分配给用户来使用,所以,当用户使用HDC后,一定要释放HDC资源,要不就有可能导致系统的资源不足。在HDC中是通过裁剪来对窗口进行管理的。也就是说,两个应用程序中,当一个程序改变了HDC的属性,例如背景颜色时,另一个程序的背景颜色也会发生改变,这就是为什么使用HDC的资源前,一定要保存原始的值,当用完后就立刻恢复的原因。
2026-02-26 17:00:22
457
原创 第3章 Windows运行机理-3.2 消息的运行方式(3)
在Windows的编程中,有一个很经典的程序“Hello World”。它只要做一些事件,当有事件来时,就处理相应的事件。大家可能对这段代码已很熟悉了,在以前用API进行Windows编程时,几乎所有的程序都会去套用这个框架。从一个WinMain中注册一个窗口,其他再用GetMessage取得窗口的消息,翻译后分给对应的窗口。可以看到,这个WIN32的程序就没用到微软的框架,它完全是自己做自己的事,直到被中止。实际上,很多应用可以不用窗口,例如,Windows NT的服务程序就不需要窗口。
2026-02-26 16:59:41
697
原创 第3章 Windows运行机理-3.2 消息的运行方式(2)
还有一些情况也可以得到消息,例如时钟消息TIMER是底层驱动的,当TIMER产生一个消息时,它会查找当前窗口中定义了时钟消息的时间是否来到,当时间到了,就会在对应的窗口函数中放入一时间消息事件。当键盘或鼠标有消息时,就会发给激活的窗口,当在程序设计中用SendMessage来发送消息时,就会明确指定窗口句柄,当运行此函数后,就会把消息放到此窗口的消息队列中。首先有一个GetMessage,只要这个消息不为0,就可以一直循环,当有消息来时,就通过跳转到消息处理函数来完成相应的功能。HWND hwnd;
2026-02-25 12:58:29
547
原创 第3章 Windows运行机理-3.2 消息的运行方式(1)
这样,这个系统的VM中的DLL就直接调用中断来进行管理,当调用中断时,就会用VxD或.386文件,对中断或IO进行截取,来模拟直接操作硬件的工作。在16位时代,Windows的整个内核是32位的、分时的、抢占的。一个系统中可以运行很多的DOS窗口,因为在16位的时代,能运行DOS的程序是很重要的,所以在当时,Windows的主要任务之一,就是能同时运行很多DOS窗口。还有一种函数是PeekMessage,它会从消息中取出一条消息,但它和GetMessage不同的是,当消息队列中有消息时,它会返回函数;
2026-02-25 12:57:56
550
原创 第3章 Windows运行机理-3.1 内核分析(13)
我们可以通过Windows的系统资源监视器看到,当降温程序打开时,CPU的占用率会马上提高,当降温程序关闭时,CPU的占用率又马上恢复原值。这是因为系统资源监视器也是通过空闲时调用的方法实现的,所以当降温程序工作时,CPU就会暂停了,就好像是占用了很多的资源。在程序的运行中,可以看见,当程序启动的时候,并没有出现窗口,而是在Windows的任务栏的右下角出现了一个下雨一样的小图标,这叫做托盘方法。实现起来也是很简单,很多资料中都介绍了,这里就不赘述。// 添加任务条Icon。// 删除任务条Icon。
2026-02-24 06:14:44
494
原创 第3章 Windows运行机理-3.1 内核分析(12)
在代码中都有详细的注释。其实,VxD的装入方法与一个通常的文件一样,也是通过Win API的函数CreateFile来完成,大家一定不要被Create这个词误解了,其实,CreateFile可以用来打开和创建新文件。//如果不是WinNT就打开VxD,因为VxD只能在WIN9X下工作。{//直接打开默认的.VxD。//设置VxD功能号3。//直接打开全路径的VxD。//设置VxD功能号3。//尝试打开默认的VxD。//取得操作系统的版本。//VxD只认短路径。
2026-02-24 06:14:12
359
原创 第3章 Windows运行机理-3.1 内核分析(11)
DeviceIOControl这个函数只定义了一些必要传递的一批参数,例如调用的服务号。从CVxD_W32_Proc这个函数代码可以看到,功能一、二是没有用的,功能三是用来降温的,功能三调用CVxD_W32_EnableHalt函数,这个函数用来开关降温功能。其中,dwService是传入的服务号,lpClient,dwDDB,hDevice,lpDIOCParms是功能传入的固定的参数。通常,为了方便,一般的VxD的做法是把函数的指针放在某个结构中,然后通过功能号直接去调用这个函数就行了。
2026-02-23 08:48:55
586
原创 第3章 Windows运行机理-3.1 内核分析(10)
W32_DEVICEIOCONTROL是宏来定义的,设备控制程序CVxD_W32_DeviceIOControl,<ebp, ecx, ebx, edx, esi>是调用函数时用来传递参数的寄存器的名字。_UnInstallIDLEProc函数和_InstallIDLEProc函数一样,也是在SthVxD.c中被CVxD_Dynamic_Exit(void)函数调用的。VxD不光可以给WIN32位程序调用,WIN16和DOS程序都可以调用VxD提供的功能,它们都通过中断2FH来调用,并设置相应的参数。
2026-02-23 08:48:06
343
原创 第3章 Windows运行机理-3.1 内核分析(9)
UNDEFINED_INIT_ORDER是初始化的序列,可以通过这个序列号让VMM来决定是装入时初始化还是随机地初始化或者是一定要在某事件前初始化,但一般的VxD是不必要设置这个参数的,它一般用在系统的某些固定的设备的VxD上。定义被其他函数调用的接口的申明,很多VxD中的函数可以给其他的VxD进行调用,有些VxD提供了一此功能能让别的VxD使用,就可以像动态连接库一样引出一些函数。它包含了代码中宏的定义。其实,它是vmm.inc中的宏语句,表示代码在内存中的一种存储方式,请参考介绍LE的文件模式的一节。
2026-02-22 11:55:02
482
原创 第3章 Windows运行机理-3.1 内核分析(8)
一方面,它减轻了VMM和VxD载入器的工作量,因为它们不用定位VxD中所有的服务,那些没有执行过的服务将会保持原样。由于VMM把调用锁定到VxD服务的实际地址上,如果提供这个服务的VxD程序从内存中被卸载了,其他VxD程序调用这个服务时,就会很快地因为调用无效的内存地址而导致系统崩溃。没有办法来消除抓取的链接。可以看到,VMM的ID是1,VPICD的ID是3等。 还有一点最重要的是,您的操作系统一定要是Windows 9x系列的,因为VxD只能用在Windows 9x系列的操作系统中。
2026-02-22 11:54:22
533
原创 第3章 Windows运行机理-3.1 内核分析(7)
我们知道,VxD程序都有一个VxD的DDB列表,当VxD被加载时,DDB就会被装到Windows 95的系统内存里,Windows 95就是通过这个表把所有的VxD作为一个链表来进行管理的。VxD程序,包括VMM在内,通常要导出一系列的被别的VxD程序调用的公共函数,这些函数被称为VxD服务。调用这些服务的机制和在第三层级别运行的应用程序有很大的不同:每个导出VxD服务的VxD程序必须有一个惟一的ID,你可以从Microsoft得到一个这样的ID。当你要调用VMM导出的VxD服务函数时,用VMMCall。
2026-02-21 17:48:29
562
原创 第3章 Windows运行机理-3.1 内核分析(6)
这是因为在VMM加载VxD程序的时候,它是按照初始化顺序值小的VxD先加载的顺序加载的,这样,VxD程序就可以使用那些在它们之前加载的VxD程序提供的服务。(2)Device_Init:控制消息时需要调用一些VxD服务,既然Sys_Critical_Init 控制消息在Device_Init消息之前被发送,所以你应该在Sys_Critical_Init 消息发送时初始化你的程序。那么卸载的时候,理所当然地是初始化顺序值大的VxD程序先被卸载,这样它们仍然可以使用比它们后加载的那些VxD程序提供的服务。
2026-02-21 17:47:53
499
经纬度网格显示模块.rar
2025-12-25
基于QT的页面切换控件重用模块介绍.rar
2025-12-25
四位置寻北解算模块.rar
2025-12-25
通用轻量级日志.rar
2025-12-25
通用配置文件操作.rar
2025-12-25
基于Qt的串口重用模块介绍.rar
2025-12-25
基于QT的程序崩溃内存转储.rar
2025-12-25
基于Qtd的TCPServer重用模块.rar
2025-12-25
基本BI协议的DVL数据处理模块.rar
2025-12-25
航行日志管理模块.rar
2025-12-25
工作状态配置化监控模块.rar
2025-12-25
不同码制字符串间转化.rar
2025-12-25
windows系统下C++实现的软件用户授权.rar
2025-12-25
捷联惯导粗对准-双矢量定姿.rar
2025-12-29
大华摄像头视频重用.rar
2025-12-29
基于qt的曲线绘制.rar
2025-12-29
嵌入式系统多线程网络处理方法.rar
2025-12-29
基于VC6,VS的仅限浮点数输入控件.rar
2025-12-29
环形数据缓存区读写方法.rar
2025-12-29
编队计划航线规划.rar
2025-12-29
vdr告警显示功能.rar
2025-12-29
FPGA数据收发模块.rar
2025-12-29
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅