diff --git a/C++/C++基础/1 变量和基本类型.md b/C++/C++基础/1 变量和基本类型.md index c3f4b22c..d935b38e 100644 --- a/C++/C++基础/1 变量和基本类型.md +++ b/C++/C++基础/1 变量和基本类型.md @@ -299,3 +299,13 @@ data a,b; ``` a.sold =1; ``` +## 7 常用限定符说明 + +### 存储类别 +* auto 默认存储类别,自动变量int i = 3; +* static 静态存储类别的变量,静态变量static int m = 5; +* register 寄存器变量register n = 6; +* extern 声明外部链接属性 +### 类型限定 +* const限定:制度变量、常变量 const int i = 6;必须直接初始化,避免对重要手进行错误修改。 +* volatile限定:隐式存取变量。 \ No newline at end of file diff --git a/C++/C++基础/补充1 程序设计基础.md b/C++/C++基础/补充1 程序设计基础.md new file mode 100644 index 00000000..9d28b475 --- /dev/null +++ b/C++/C++基础/补充1 程序设计基础.md @@ -0,0 +1,108 @@ +# 冯诺依曼计算机 + +## 组成部分 + +1. 运算器:算术逻辑单元ALU。算术运算和逻辑运算。加法器、寄存器、控制线路。 +2. 控制器:程序计数器PC、指令寄存器IR、指令译码器ID、时序控制电路。运算器和控制器组成了CPU。 +3. 存储器:计算机用来存储数据的记忆装置。内存储器和外存储器。 +4. 输入设备:接受用户输入的程序和数据信息,将他们转换成计算机可以处理的二进制形式的数据存储到内存当中。 +5. 输出设备:将存放在内存中的计算机处理结果以人们能够识别的形势表现出来。 + +> 分类:高性能计算机、微信计算机、工作站、服务器、嵌入式计算机。 + +> 程序和数据均以二进制表示,以相同的方式存放在存储器中,按地址寻访。 + +## 指令与程序 + +* 指令:计算机执行某种操作的及其命令,他可以被计算机硬件直接识别和执行。组成:操作码+操作数。操作码指明操作的类型。操作数指明操作对象的数据或所在的内存单元地址。 +* 指令系统:一台计算机所有指令的集合称为指令系统。指令分类:数据传送指令、数据处理指令、程序控制指令、输入输出指令、硬件管理指令。 +* 执行指令的步骤:取指令、分析指令、处理指令。指令流水线技术。 +* 程序:完成一定功能的指令的有序集合。包含算法和数据两部分。 +* 算法:控制流是对数据所进行操作的描述,即指定的操作步骤和方法。 +* 软件:值程序、程序运行所需要的数据以及开发、使用和维护这些程序所需要的文档的集合。 + +## 信息的存储与标识 + +##### 计算机的数字系统 +* r称为该数制的基数,数制中每个位置对应的单位称为位权。 +* 常用的有二进制八进制十进制是,就禁止。 + +##### 进位计数制的转换 +* 进制转换:十进制转换r进制:除r取余法和乘r取整法。r进制转换十进制:基数乘位权相加。二进制、八进制、十六进制的相互转换。直接使用位数对应。 + +##### 数值数据的表示 + +* 整数的原码: +* 整数的反码: +* 整数的补码: +* 浮点数的表示:32位,s-一位符号位。e-八位指数位。f-二十三位小数位。 + +##### 非数值数据的表示 + +* ASCII码,7位二进制编码。 +* 汉字字符及其他双字节编码的字符集。 +* 多媒体信息。 + + +## 程序设计语言 +* 机器语言:二进制0和1按照一定规则组成的,能被计算机直接理解和执行的指令集合。难写难记难阅读,不同硬件机器指令不同,通用性差。机器语言程序占用存储空间少,运行速度快。 +* 汇编语言 +* 高级语言-编译:编译器程序把高级语言编写的源程序翻译成机器指令的目标代码。目标代码和源程序在功能上完全邓建。通过连接器程序将目标程序和相关的库连接成一个完成的可执行的程序。 +* 高级语言-解释:解释器程序将高级语言编写的源程序主句进行分析,解释一句执行一句。移植到不同平台是不用修改代码,只要有合适的解释器就能运行。 + +## 程序设计概述 +##### 基本特点 +* 确定数学模型和数据结构 +* 算法分析和描述 +* 编写程序 +* 程序测试 + +##### 算法的定义与特性 + +* 有穷性 +* 确定性 +* 有效性 +* 算法可以有零个、一个或多个输入 +* 算法可以有一个或多个输出。 + + +##### 算法的表示 + +* 自然语言 +* 流程图,顺序结构、选择结构和循环结构。 +* N-S图表示 +* 伪代码 +* UML + +##### 结构化程序设计 + +* 以模块功能和处理过程设计为主的详细设计的基本原则。 + +##### 面向对象的程序设计 + +* 类和对象 +* 封装与信息隐藏。 +* 抽象 +* 继承与重用 +* 多态性 +* 消息传送与处理 + +## C++的基本词法 + +* 字符集:字母、数字、符号、空白符 +* 三元符 +* 关键字 +* 标识符 +* + + + + + + + + + + + + diff --git a/C++/C++基础/补充2 数字编码.md b/C++/C++基础/补充2 数字编码.md new file mode 100644 index 00000000..105c0f8c --- /dev/null +++ b/C++/C++基础/补充2 数字编码.md @@ -0,0 +1,118 @@ +## 进位计数 +### 数制 +* ##### 2进制 +* ##### 8进制 +* ##### 10进制 +* ##### 16进制 +### 数制转化 +* ##### r进制数转化成十进制 +$$ +I = a_{n-1}\times r^{n-1} + \cdots + a_0 \times r^0 +$$ +* ##### 十进制整数转化r进制数——除r取余法 +$$ +\frac Ir=\frac{a_{n-1}\times r^{n-1}+ \cdots + a_0 \times r^0}{r} + \frac {a_0 \times r^0}{r} +$$ +* ##### 十进制小数转化r进制数——乘r取整法 +$$ +f = a_{-1} \times r^{-1} + a_{-(m-1)} \times r^{-(m-1)} + a_{-m} \times r^{-(m-1)} +$$ +> 为什么十进制相对其他进制来说特殊,因为我们在计算的时候,加减乘除,全部都使用十进制的法则,所以十进制计算表达起来更简单。 + +## 数值编码 + +### 原码 +$$ +(X)_y= +\left\{ + \begin{array}{lr} + X & 0 \leq X < 2^{n-1}\\ + 2^{n-1} + |X| & -2^{n-1} < X \leq 0 + \end{array} +\right. +$$ + + +### 反码 +$$ +(X)_f= +\left\{ + \begin{array}{lr} + X & 0 \leq X < 2^{n-1}\\ + 2^{n}-1 - |X| & -2^{n-1} < X \leq 0 + \end{array} +\right. +$$ +**关系说明:** 对于正数,反码等于补码;对于负数,反码数值位等于原码数值位按位取反。 +### 补码 +$$ +(X)_b= +\left\{ + \begin{array}{lr} + X & 0 \leq X < 2^{n-1}\\ + 2^{n} - |X| & -2^{n-1} < X \leq 0 + \end{array} +\right. +$$ +**关系说明:** 为了满足数值计算,使得正数负数能够在同一的编码下进行加减计算。正数的机器数,原码,反码,补码,都是在固定字长下讨论的 + +### 浮点数 + +规格化数: +$$ +eq = (-1)^s \times 2^E \times 1.f +$$ +s-1位符号位,E-8位指数位,f-23位小数位。提供了24位的小数(二进制)小数的精度,-126~127的指数次(二进制)范围。 + +## 字符编码 + +### 西文字符 +ASCII 使用7位而金子编码,0~127等128个字符 + +### 汉字字符 +包括输入码、字形码、国标码、机内码 +> 汉字机内码 = 汉字国标码 + 8080H = 区位码 + A0A0H + +## 程序语言 + +### 机器语言(指令) + +### 汇编语言 + +### 高级语言 + +##### 编译 +用编译器把高级语言编写的源程序翻译成机器指令表示的目标代码。通过连接器程序将目标程序于相关库连接成一个完整的可执行程序。有点:速度快,脱离源程序运行。 +##### 解释 +用解释器程序将高级语言编写的源程序进行分析翻译,解释一句,执行一句。优点:跨平台,移植性高。 + +## 程序设计概述 + +### 步骤 + +1. ##### 确定数学模型和数据结构 +2. ##### 算法分析和描述 +3. ##### 编写程序 +4. ##### 程序测试 + +### 算法 + +##### 定义 +算法是为了求解问题而采取的,按照一定次序进行的操作步骤。 + +##### 特性 +又穷性、确定性、有效性、另个或多个输入、一个或多个输出。 + +##### 表示方法 +* 自然语言 +* 流程图 +* N-S图 +* 伪代码 +* UML图 + + + + + + + diff --git a/C++/代码片段.md/1.cpp b/C++/代码片段/1.cpp similarity index 100% rename from C++/代码片段.md/1.cpp rename to C++/代码片段/1.cpp diff --git a/Git/git.md b/Git/git.md new file mode 100644 index 00000000..87df160b --- /dev/null +++ b/Git/git.md @@ -0,0 +1,432 @@ +Git的本地操作 + +> 参考文献 +> * [git使用教程](https://github.com/geeeeeeeeek/git-recipes/wiki) + +一个非常详细的中文版git使用详解 + +本地操作主要是指在同一个仓库中实现版本控制,包括版本的提交、回退等基本擦偶作。 + +**git安装** + +- Linux上通过命令行能够很轻松的部署好git + +- Windows上需要安装GitBash,模拟linux命令行 + +- 安装完成后需要配置全局信息的命令 + +\$ git config --global user.name "Your Name" + +\$ git config --global user.email "email@example.com" + +创建版本库 + +- git init + +生成.git文件,将这个目录初始化为一个版本的仓库。 + +- git add readme.txt + +将文件添加到缓冲区,可以连续多次向缓冲区中添加东西 + +- git commit -m "wrote a message" + +将缓冲区的文件提交到历史记录当中当中,可以一次提交对缓冲区的多次修改。 + +**时光穿梭机** + +- it status + +用来查看当前仓库的状态。主要有changes not staged for +commit状态(工作区有变化没有提交),chages to be +committed状态(缓存区有变化等待提价) + +- git diff readme.txt + +用来对比工作区和历史记录内容的差别。 + +**版本回退** + +- git log + +用来查看版本的历史记录 + +- git log --pretty=oneline + +在一行显示历史记录 + +- git reset --hard HEAD\^ + +回退到上一次的历史记录 + +- git reset --hard id + +回退到指定id的版本 + +- git reflog + +用来查看所有操作的历史记录,可以使用reset命令去定位到任何版本 + +**工作区和暂存区概念理解** + +- 工作区Wording Directory:在电脑中能够看到的目录,是工作区 + +- 版本库Repository:工作区有一个隐藏的目录.git是版本库 + +- 版本库中有Stage暂存区和master等分支以及一个纸箱master的指针HEAD + +**管理修改** + +- git跟踪管理的是对文件的修改而并非文件本身 + +**撤销修改** + +- git checkout --readme.txt + +把readme.txt在工作区的修改全部撤销掉。如果缓存区有readme.txt的中间状态,则从缓存区恢复,如果缓存区没有readme.txt的中间状态,则从版本库中恢复。 + +- git reset HEAD readme.txt + +把readmen.txt在缓存区的修改全部撤销掉。但是依然会保留工作区的修改。 + +**删除文件** + +- git rm test.txt + +把某个文件从缓存区删掉,然后commit之后会从版本库删掉。如果删错了可以通过checkout从缓存区恢复这个文件。 + +Git的远程操作 + +远程操作主要是指,在不同的仓库之间进行提交和代码更改。是一个明显的对等的分布式系统。其中本地个仓库与远程仓库,不同的远程仓库之间都可以建立这种关系。这种关系之间的操作主要有pull和push。 + +**远程仓库** + +- 创建SSH key远程仓库和本地仓库一般是通过ssh通信的,需要ssh通信的加密钥匙。 + +id_rsa是私钥,id_rsa.pub是公钥,可以告诉别人。 + +ssh-keygen -t rsa -C 'yinkanglong@163.com' + +- 登录github,添加公钥内容。建立本地与远程仓库的通信协议 + +**添加远程仓库** + +- github的界面操作可以很轻松的创建一个远程仓库。但如果想要直接上传自己本地的完整git库,必须创建一个没有lisence和readme的空库。 + +- git remote add origin git@github.com:michaelliao/learngit.git + +将本地仓库和远程仓库进行关联。一般都叫远程关联仓库为origin,本地的主干分支一般名为master + +- git push -u origin master + +将本地的主干分支master推送到远程的origin分支上。-u参数实现了两个分支的关联,将远程的git仓库的master和本地的master进行了分支管理,当再次执行时,只需要使用git +push origin master命令。 + +**从远程仓库克隆** + +- git clone git@github.com:michaelliao/gitskills.git + +分支管理 + +这里主要体现的git的功能的分离,这才是真正的git吧。每一个分支都是一个单独的可以分离的工作单位。每个用户可以建立不同的分支进行工作,最终提交到同一个开发分支上。一个用户可以建立不同的分支实现不同的功能,最终提交到同一个用户分支上。分支的灵活性,可以让我们很容易的实现不同分工的分割。 + +**创建分支** + +- git checkout -b dev + +创建分支,并且将工作目录切换到dev的工作目录上。 + +- git branch dev + +使用当前版本分支创建新的分支(即添加一个分支指针)。 + +- git checkout dev + +将工作区切换到某一个分支指针所指的版本上。 + +- git branch + +会列出所有的分支目录。 + +**分支合并** + +- git merge dev + +将dev分支合并到当前工作目录下的分支上(不一定是产生他的父分支) + +- git branch -d dev + +用来删除一个已经无效的分支指正,但是在这个分支指针上左右的操作都会保留。 + +**解决冲突** + +- 当合并过程中出现冲突,会进入长途解决工作区,手动解决后提交,就会退出。 + +- 关于一点,提交后的分支有必要继续工作吗,都行。完全可以提交后删掉重新创建一个分支,获取主干分支上集成的最新内容,然后继续工作。也可以直接在分支上合并一次主干分支,然后得到最新的内容,继续在原来的分支上进行工作。 + +- git log --graph + +可以查看分支合并图。 + +**分支合并方式** + +- git merge --no-ff -m "merge messge" dev + +\--no-ff +不适用fastfoward方式进行合并,会产生一个新的版本节点。加上-m参数,是因为这种方式合并过程中会自己提交合并后的版本。 + +**分支管理** + +- 团队合作的分支管理组图就是你们要的方式 + +![clipboard.png](media/202749bd52950c0c839d73190cd2fd9d.png) + +**BUG分支** + +- 因为总会在自己工作的过程中出现紧急的需要更改的bug,但是现在工作区中的内容还不能提交,所以必须生成现在工作区的一个快照,等处理完紧急的bug之后,再来回复工作区的内容。 + +- git stash + +将当前的工作现场储存起来,等到修复完成bug之后可以再次进行更改。工作现场包括工作区和stage缓存区。然后可以清空工作区和缓存区的内容,新建bug分支进行工作。 + +- git stash list + +用来查看保存中的工作区。 + +- git stash apply stash@{0} + +恢复stash内容,但并不清楚stash列表中的内容。 + +- get stash drop + +用来删除stash列表中的内容。(因为已经恢复或者没有必要恢复) + +- git stash pop + +可以用来弹出stash列表中的内容。 + +**Feature分支** + +- 当添加一个新的功能的时候,因为是一些实验性的代码,所以要创建一个单独的分支进行处理。 + +- git checkout -b feature-vulcan + +创建一个新的功能分支 + +git status + +git add vulcan.py + +git commit -m "add feature vulcan" + +git checkout dev + +git merge vulcan.py + +git branch -D feature-vulcan 不合并,强制删除 + +多人协作 + +通过远程库的push和pull操作实现夺人合作 + +**推送分支或分支内容** + +- 当从远程库进行克隆的时候,实际上已经将本地master分支和远程的master分支进行乐关联。 + +- git remote [-v] + +可以显示与远程库关联的信息 + +- git push origin master + +推送分支,吧分支上的所有本地内容提交到远程库中的相同分支当中。 + +- 哪些分支需要推送 + +mater分支是主分支,需要实时推送 + +dev是开发分支,所有成员都要在上面工作。也需要与远程同步。 + +bug分支只需要在本地修复bug,没有必要推送到远程。 + +feature分支,可以不用推送到远程。单人开发不用,夺人开发要推送到远程。 + +**抓取分支或者分支的内容** + +- git checkout -b dev origin/dev + +可以用来抓取远程分支dev,这样会建立一个本地的本地的dev分支与远程的dev分支进行关联,可以直接实现dev分支的控制(push) + +- git pull \ \ + +如果Git push失败,说明,当前的版本不是最新的版本。git pull +可以将远程库中的最新版本拉去到本地。 + +- git branch --set-upstream dev origin/\ + +这样会制定git的本地分支与远程的分支之间的链接。 + +- 如果git pull有冲突,与分支合并中解决冲突的方法一直。 + +**多人协作的协作模式通常是这样:** + +> 1\. 首先,可以试图⽤git push origin branch-name推送自己的修改; + +> 2\. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并; + +> 3\. 如果合并有冲突,则解决冲突,并在本地提交; + +> 4\. 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功! + +> 5\. 如果git pull提“no tracking +> information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch +> \--set-upstream branch-name origin/branch-name。 + +标签管理 + +**创建标签** + +- git tag v1.0 + +对当前版本打标签,为v1.0 + +- git tag + +查看所有已经创建的标签 + +- git tag v0.9 6.225 + +对指定id的版本打标签 + +- git show v0.9 + +查看标签信息 + +- git tag -a v0.1 -m "version 0.1 released" 3628164 + +创建带有标签说明的标签 + +**操作标签** + +- git tag -d v0.1 + +删除制定版本的标签 + +- git push origin v1.0 + +推送某个标签到远程 + +- git push origin --tags + +一次性推送所有标签。 + +- git tag -d v0.9 + +git push origin :refs/tags/v0.9 + +从远程删除标签,先在本地删除标签,然后将操作推送到远程。 + +使用github + +https://www.bilibili.com/video/av10475153/index_2.html\#page=5 + +这是一个比较啰嗦的讲解github页面的东西,学号英文真的十分重要。 + +**git的简介** + +Create Repository + +创建仓库 + +Star + +收藏 + +Fork + +复制一份远程仓库 + +Pull Request + +拉我呀,快点,我改好了。 + +Open & Merge Request + +拉你了,别墨迹。 + +Watch + +看着你呢,关注一个项目。 + +Github主页 + +仓库主页——仓库相关的信息和相关操作 + +个人主页 + +这是一些补充的内容 + +保持同步 + +**git remote** + +- git remote + +列出你和远程仓库之间的远程连接 + +- git remote -v + +列出每个连接的名字和url + +- git remote add \ \ + +创建一个新的远程连接并添加名字 + +- git remote rm \ + +移除远程仓库的链接 + +git fetch + +- git fetch \ + +拉取仓库中的所有分支(包括相关的文件和所有的提交) + +- git fetch \ \ + +拉取制定仓库中的所有分支(包括相关的文件和所欲的提交) + +\> +注意,这个步骤知识拉取远程的分支,在本地并没有合并也没有生成本地分支,知识一个可读的远程分支。使用 +git branch -r 命令可以查看所有只读的远程分支。使用git +checkout命令可以创建本地分支,并与远程分支关联。使用git merge +命令可以将远程分支与本地分支合并。 + +git pull + +- git pull remote + +拉取当前分支对应的远程副本,并将远程副本的更改写入本地副本。相当于git +fetch之后git merge。 + +- git pull -rebase \ + +使用git rebase命令合并远程分支与本地分支,不使用git merge + +git push + +- git push \ \ + +将制定分支推送到远程分支。包括所有的文件和提交。 + +- git push \ --force + +强制推送 + +- git push \ --all + +本地所有的分支推送到远程仓库当中 + +- git push \ --tags + +将本地所有标签推送到远程仓库中 diff --git a/Git/media/202749bd52950c0c839d73190cd2fd9d.png b/Git/media/202749bd52950c0c839d73190cd2fd9d.png new file mode 100644 index 00000000..0d8f7e98 Binary files /dev/null and b/Git/media/202749bd52950c0c839d73190cd2fd9d.png differ diff --git a/windows程序设计/C字符串操作.md b/windows程序设计/C字符串操作.md new file mode 100644 index 00000000..7ad4aec1 --- /dev/null +++ b/windows程序设计/C字符串操作.md @@ -0,0 +1,56 @@ +果然,就语言中的语法来说,最基础的两部分超级难的两部分,也就是字符串操作和输入输出流的操作。到现在都不知道java各个流的嵌套顺序,以及每个流的封装实现的具体方法。Python字符串操作能够支持运算符和强大的通配符匹配,感觉相对简单,java也还好,但是这个C真的烦,各种函数……,得花点时间,来重新学一下C语言的流操作和字符串操作了。 + +1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 +strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度字符串 strlen(p) +取字符串长度 strcmp(p, p1) 比较字符串 strcasecmp忽略大小写比较字符串 strncmp(p, +p1, n) 比较指定长度字符串 strchr(p, c) 在字符串中查找指定字符 strrchr(p, c) +在字符串中反向查找 strstr(p, p1) 查找字符串 strpbrk(p, p1) +以目标字符串的所有字符作为集合,在当前字符串查找该集合的任一元素 strspn(p, p1) +以目标字符串的所有字符作为集合,在当前字符串查找不属于该集合的任一元素的偏移 +strcspn(p, p1) +以目标字符串的所有字符作为集合,在当前字符串查找属于该集合的任一元素的偏移\* +具有指定长度的字符串处理函数在已处理的字符串之后填补零结尾符 + +2)字符串到数值类型的转换 strtod(p, ppend) 从字符串 p 中转换 double +类型数值,并将后续的字符串指针存储到 ppend 指向的 char\* 类型存储。 strtol(p, +ppend, base) 从字符串 p 中转换 long 类型整型数值,base +显式设置转换的整型进制,设置为 0 以根据特定格式判断所用进制,0x, 0X +前缀以解释为十六进制格式整型,0 前缀以解释为八进制格式整型 atoi(p) 字符串转换到 +int 整型 atof(p) 字符串转换到 double 符点数 atol(p) 字符串转换到 long 整型 + +3)字符检查 isalpha() 检查是否为字母字符 isupper() 检查是否为大写字母字符 +islower() 检查是否为小写字母字符 isdigit() 检查是否为数字 isxdigit() +检查是否为十六进制数字表示的有效字符 isspace() 检查是否为空格类型字符 iscntrl() +检查是否为控制字符 ispunct() 检查是否为标点符号 isalnum() 检查是否为字母和数字 +isprint() 检查是否是可打印字符 isgraph() 检查是否是图形字符,等效于 isalnum() \| +ispunct() + +char \*strset(char \*string, int c); 将string串的所有字符设置为字符c, +遇到NULL结束符停止. 函数返回内容调整后的string指针. char \*strnset(char +\*string, int c, size_t count); 将string串开始count个字符设置为字符c, +如果count值大于string串的长度, 将用string的长度替换count值. +函数返回内容调整后的string指针. size_t strspn(const char \*string, const char +\*strCharSet); 查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外) +在string串中首次出现的位置序号. 返回一个整数值, +指定在string中全部由characters中的字符组成的子串的长度. +如果string以一个不包含在strCharSet中的字符开头, 函数将返回0值. size_t +strcspn(const char \*string, const char \*strCharSet); +查找strCharSet串中任何一个字符在string串中首次出现的位置序号, +包含字符串结束符NULL. 返回一个整数值, +指定在string中全部由非characters中的字符组成的子串的长度. +如果string以一个包含在strCharSet中的字符开头, 函数将返回0值.char \*strspnp(const +char \*string, const char \*strCharSet); +查找任何一个不包含在strCharSet串中的字符 (字符串结束符NULL除外) +在string串中首次出现的位置指针. 返回一个指针, +指向非strCharSet中的字符在string中首次出现的位置.char \*strpbrk(const char +\*string, const char \*strCharSet); +查找strCharSet串中任何一个字符在string串中首次出现的位置, +不包含字符串结束符NULL. 返回一个指针, +指向strCharSet中任一字符在string中首次出现的位置. +如果两个字符串参数不含相同字符, 则返回NULL值. + +函数名: strcmpi + +功 能: 将一个串与另一个比较, 不管大小写 + +用 法: int strcmpi(char \*str1, char \*str2); diff --git a/windows程序设计/C数据类型转化的说明.md b/windows程序设计/C数据类型转化的说明.md new file mode 100644 index 00000000..5b488fe7 --- /dev/null +++ b/windows程序设计/C数据类型转化的说明.md @@ -0,0 +1,36 @@ +**基础转化方式** + +atoi(p) 字符串转换到 int 整型 atof(p) 字符串转换到 double 符点数 atol(p) +字符串转换到 long 整型 + +itoa()将整型值转换为字符串 + +ftoa()将浮点型转化为字符串 + +ultoa()将无符号长整型值转换为字符串 + +**字符串操作方式** + +strtod(p, ppend) 从字符串 p 中转换 double 类型数值,并将后续的字符串指针存储到 +ppend 指向的 char\* 类型存储。 strtol(p, ppend, base) 从字符串 p 中转换 long +类型整型数值,base 显式设置转换的整型进制,设置为 0 +以根据特定格式判断所用进制,0x, 0X 前缀以解释为十六进制格式整型,0 +前缀以解释为八进制格式整型 + +char \*ecvt(double value,int ndigIT,int \*dec,int \*sign) + +ecvt() 将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点 + +char \*fcvt(double value,int ndigIT,int \*dec,int \*sign) + +fcvt() 以指定位数为转换精度,余同ecvt() + +char \* gcvt(double value,int ndec,char \*buf) + +gcvt() 将双精度浮点型值转换为字符串,转换结果中包含十进制小数点 + +**流转化方式** + +sprintf(ctime, "%d:%d:%d", H, M, S); // 将整数转换成字符串ctime + +sscanf( str, "%f", &fp ); // 将字符串转换成浮点数 fp = 15.455000 diff --git a/windows程序设计/Win32 进阶-MFC编程.md b/windows程序设计/Win32 进阶-MFC编程.md new file mode 100644 index 00000000..e871d538 --- /dev/null +++ b/windows程序设计/Win32 进阶-MFC编程.md @@ -0,0 +1,23 @@ +MFC 是一个框架。 + +它封装了主要的win32 接口。win32 接口以函数为主。 + +MFC Microsoft Foundation Class +Libraray,是一个面向对象的以类为主的框架。将库中各种类结合起来,构成了一个应用程序框架。是一种对windows +SDK的封装。MFC框架定义了应用程序的轮廓。他是C++的类库。 + +MFC中的封装: + +用一个C++ 对象封装Windows 对象。class CWnd是一个C++ window object,它把Windows +window(HWND)和Windows window有关的API函数封装在C++ window +object的成员函数内,后者的成员变量m_hWnd就是前者的窗口句柄。 + +用C++的方式,重新定义相关的类。 + +MFC中继承: + +MFC抽象出众多类的共同特性,设计出一些基类作为实现其他类的基础。这些类中,最重要的类是CObject和CCmdTarget。CObject是MFC的根类,绝大多数MFC类是其派生的, +包括CCmdTarget。CObject +实现了一些重要的特性,包括动态类信息、动态创建、对象序列化、对程序调试的支持,等等。所有从CObject派生的类都将具备或者可以具备CObject所拥有的特性。CCmdTarget通过封装一些属性和方法,提供了消息处理的架构。MFC中,任何可以处理消息的类都从CCmdTarget派生。 + +针对每种不同的对象,MFC都设计了一组类对这些对象进行封装,每一组类都有一个基类,从基类派生出众多更具体的类。这些对象包括以下种类:窗口对象,基类是CWnd;应用程序对象,基类是CwinThread;文档对象,基类是Cdocument,等等。 diff --git a/windows程序设计/Windows图形界面.md b/windows程序设计/Windows图形界面.md new file mode 100644 index 00000000..055c553d --- /dev/null +++ b/windows程序设计/Windows图形界面.md @@ -0,0 +1,592 @@ +第二节第一个窗口程序 + +**创建窗口程序** + +主函数为WinMain函数 + +int APIENTRY WinMain(HINSTANCE hInstance, // 本模块的实例句柄 + +> HINSTANCE hPrevInstance, // Win16 留下的废物,现在已经不用了 + +> LPSTR lpCmdLine, // 命令行参数 + +> int nCmdShow) // 主窗口初始化时的显示方式 + +> { // 下面这行代码是我添加的,用于弹出一个小对话框 + +> ::MessageBox(NULL, "Hello, Win32 Application", "04Win32AppDemo", MB_OK); + +> return 0; + +> } + +弹出窗口MessageBox函数 + +int MessageBox( + +> HWND hWnd, // 一个窗口句柄,它指定了哪一个窗口将拥有要创建的消息框 + +> LPCTSTR lpText, // 将要显示的消息 + +> LPCTSTR lpCaption, // 对话框的标题 + +> UINT uType // 指定对话框的内容和行为 + +> ); + +uType的取值 + +(1)为了指定希望在消息框中显示的按钮,要指定下组中的一个值: + +| MB\_OK | 消息框包含一个按钮:确定。这是默认按钮。 | +|---------------------|------------------------------------------| +| MB_OKCANCEL | 消息框包含两个按钮:确定和取消 | +| MB_ABORTRETRYIGNORE | 消息框包含 3 个按钮:终止、重试和忽略 | +| MB_YESNOCANCEL | 消息框包含 3 个按钮:是、否和取消 | +| MB_YESNO | 消息框包含两个按钮:是和否 | +| MB_RETRYCANCEL | 消息框包含两个按钮:重试和取消 | + +(2)为了在对话框中显示一个图标,要指定下组中的一个值: + +MB_ICONHAND 一个停止标志图标: + +MB_ICONQUESTION 一个询问标志图标: + +MB_ICONEXCLAMATION 一个感叹号图标: + +(3)为了指示默认的选中按钮,要指定下组中的一个值: + +MB_DEFBUTTON1 第一个按钮是选中按钮 + +MB_DEFBUTTON2 第二个按钮是选中按钮 + +MB_DEFBUTTON3 第三个按钮是选中按钮 + +MB_DEFBUTTON4 第四个按钮是选中按钮 + +**窗口应用程序实例** + +// 窗口函数的函数原形 + +LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY WinMain(HINSTANCE hInstance, + +> HINSTANCE hPrevInstance, + +> LPSTR lpCmdLine, + +> int nCmdShow) + +{ char szClassName[] = "MainWClass"; + +> WNDCLASSEX wndclass; + +> // 用描述主窗口的参数填充 WNDCLASSEX 结构 + +> wndclass.cbSize = sizeof(wndclass); // 结构的大小 + +> wndclass.style = CS_HREDRAW\|CS_VREDRAW; // 指定如果大小改变就重画 + +> wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针 + +> wndclass.cbClsExtra = 0; // 没有额外的类内存 + +> wndclass.cbWndExtra = 0; // 没有额外的窗口内存 + +> wndclass.hInstance = hInstance; // 实例句柄 + +> wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); // 使用预定义图标 + +> wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW); // 使用预定义的光标 + +> wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); // +> 使用白色背景画刷 + +> wndclass.lpszMenuName = NULL; // 不指定菜单 + +> wndclass.lpszClassName = szClassName ; // 窗口类的名称 + +> wndclass.hIconSm = NULL; // 没有类的小图标 + +> // 注册这个窗口类 + +> ::RegisterClassEx(&wndclass); + +> // 创建主窗口 + +> HWND hwnd = ::CreateWindowEx( + +> 0, // dwExStyle,扩展样式 + +> szClassName, // lpClassName,类名 + +> "My first Window!", // lpWindowName,标题 + +> WS_OVERLAPPEDWINDOW, // dwStyle,窗口风格 + +> CW_USEDEFAULT, // X,初始 X 坐标 + +> CW_USEDEFAULT, // Y,初始 Y 坐标 + +> CW_USEDEFAULT, // nWidth,宽度 + +> CW_USEDEFAULT, // nHeight,高度 + +> NULL, // hWndParent,父窗口句柄 + +> NULL, // hMenu,菜单句柄 + +> hInstance, // hlnstance,程序实例句柄 + +> NULL) ; // lpParam,用户数据 + +> if(hwnd == NULL) + +> { ::MessageBox(NULL, "创建窗口出错! ", "error", MB_OK); + +> return -1; + +} + +> // 显示窗口,刷新窗口客户区 + +> ::ShowWindow(hwnd, nCmdShow); + +> ::UpdateWindow(hwnd); + +> // 从消息队列中取出消息,交给窗口函数处理,直到 GetMessage 返回 +> FALSE,结束消息循环 + +> MSG msg; + +> while(::GetMessage(&msg, NULL, 0, 0)) + +> { // 转化键盘消息 + +> ::TranslateMessage(&msg); + +> // 将消息发送到相应的窗口函数 + +> ::DispatchMessage(&msg); + +> } + +> // 当 GetMessage 返回 FALSE 时程序结束 + +> return msg.wParam; + +} + +LRESULT CALLBACK MainWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM +lParam) + +{ char szText[] = "最简单的窗口程序! "; + +> switch (message) + +> { + +> case WM_PAINT: // 窗口客户区需要重画 + +> { HDC hdc; + +> PAINTSTRUCT ps; + +> // 使无效的客户区变的有效,并取得设备环境句柄 + +> hdc = ::BeginPaint (hwnd, &ps) ; + +> // 显示文字 + +> ::TextOut(hdc, 10, 10, szText, strlen(szText)); + +> ::EndPaint(hwnd, &ps); + +> return 0; + +> } + +> case WM_DESTROY: // 正在销毁窗口 + +> // 向消息队列投递一个 WM_QUIT 消息,促使 GetMessage 函数返回 0,结束消息循环 + +> ::PostQuitMessage(0) ; + +> return 0 ; + +} + +// 将我们不处理的消息交给系统做默认处理 + +return ::DefWindowProc(hwnd, message, wParam, lParam); + +} + +**创建窗体的步骤说明:** + +注册窗口类 RegisterClassEx + +创建窗口 CreateWindowEx + +在桌面显示窗口 ShowWindow + +更新窗口客户区 UpdateWindow,发送了WM_PAINDT 消息更新他的客户区 + +进入无线的消息获取消息,转化键盘消息,将消息转发给消息处理函数GetMessage +\-\>TranslateMessage-\> DispatchMessage + +**注册窗口结构体说明** + +typedef struct \_WNDCLASSEX { + +> UINT cbSize; // WNDCLASSEX 结构的大小 + +> UINT style; // 从这个窗口类派生的窗口具有的风格,有多种风格 + +> WNDPROC lpfnWndProc; // 即 window procedure, 窗口消息处理函数指针 + +> int cbClsExtra; // 指定紧跟在窗口类结构后的附加字节数 + +> int cbWndExtra; // 指定紧跟在窗口事例后的附加字节数 + +> HANDLE hInstance; // 本模块的实例句柄 + +> HICON hIcon; // 窗口左上角图标的句柄 + +> HCURSOR hCursor; // 光标的句柄 + +> HBRUSH hbrBackground; // 背景画刷的句柄 + +> LPCTSTR lpszMenuName; // 菜单名 + +> LPCTSTR lpszClassName; // 该窗口类的名称 + +> HICON hIconSm; // 小图标句柄 + +} WNDCLASSEX; + +**消息结构体说明** + +typedef struct tagMSG { + +> HWND hwnd; // 消息要发向的窗口句柄 + +> UINT message; // 消息标识符,以 WM\_ 开头的预定义值(意为 Window Message) + +> WPARAM wParam; // 消息的参数之一 + +> LPARAM lParam; // 消息的参数之二 + +> DWORD time; // 消息放入消息队列的时间 + +> POINT pt; // 这是一个 POINT 数据结构,表示消息放入消息队列时的鼠标位置 + +} MSG, \*PMSG ; + +第二节一个简陋的打字程序 + +**使用资源** + +.rc +资源文件的源文件的脚本。由资源编译器RC.exe编译成res为扩展名的二进制文件。在链接的时候由Link.exe链入到可执行文件中。 + +resource.h +资源文件的生命文件。给资源一个ID好,通过资源的ID进行访问。一般通过资源管理器添加资源,直接生成相应的资源文件的脚本文件和声明文件。 + +**菜单和图标** + +可以直接插入菜单资源。 + +动态设置菜单的方式: + +HMENU hMenu = ::LoadMenu(::GetModuleHandle(NULL),(LPCTSTR)IDR_TYPER); + +::SetMenu(hwnd,hMenu) + +通过这种方式能够动态改变主窗体的菜单栏。 + +点击菜单之后会接收到**WM_COMMAND消息**,使用LOWORD宏从wparam参数中能够取出某个菜单的对应ID。单击后会通过SendMessage函数向窗口发送消息。 + +> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM +> lParam) + +> { + +> int wmId, wmEvent; + +> PAINTSTRUCT ps; + +> HDC hdc; + +> char szText[] = "最简单的窗口应用程序哈哈哈"; + +> switch (message) + +> { + +> case WM_COMMAND: + +> wmId = LOWORD(wParam); + +> wmEvent = HIWORD(wParam); + +> // 分析菜单选择: + +> switch (wmId) + +> { + +> case IDM_ABOUT: + +> DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + +> break; + +> case IDM_EXIT: + +> DestroyWindow(hWnd); + +> break; + +> default: + +> return DefWindowProc(hWnd, message, wParam, lParam); + +> } + +> break; + +> case WM_PAINT: + +> //DefWindowProc会进行默认处理 + +> hdc = BeginPaint(hWnd, &ps); + +> // TODO: 在此添加任意绘图代码... + +> ::TextOut(hdc, 10, 10,szText,strlen(szText)); + +> EndPaint(hWnd, &ps); + +> break; + +> case WM_DESTROY: + +> PostQuitMessage(0); + +> break; + +> default: + +> return DefWindowProc(hWnd, message, wParam, lParam); + +> } + +> return 0; + +> } + +发送消息的方式: + +SendMessage函数发送消息,并阻塞源程序 + +PostMessage函数发送消息后立即返回 + +设置图标 + +wndclass.hIcon = ::LoadIcon(hInstance, (LPSTR)IDI_TYPER); // 使用自定义图标 + +**接受键盘的输入** + +当一个 WM_KEYDOWN 消息被 TranslateMessage 函数转化以后会有一个 WM_CHAR 消 + +息产生,此消息的 wParam 参数包含了按键的 ANSI 码。例如,用户敲击一次“A”键,窗口 + +会顺序地收到以下 3 个消息。 + +| WM\_KEYDOWN | lParam 的含义为虚拟键码“A” (0x41) | +|-------------|-----------------------------------| +| WM_CHAR | lParam 的含义为 ANSI 码“a” (0x61) | +| WM_KEYUP | lParam 的含义为虚拟键码“A” (0x41) | + +**接受鼠标输入** + +> 应用程序以接收发送或者投递到它的窗口的消息的形式接收鼠标输入。当用户移动鼠标, + +> 或按下、释放鼠标的一个键时,鼠标会产生输入事件。系统将鼠标输入事件转化成消息,投递 + +> 它们到相应线程的消息队列。和处理键盘输入一样, Windows +> 将捕捉鼠标动作,并把它们发 + +> 送到相关窗口。 + +> 当用户移动光标到窗口的客户区时,系统投递 WM_MOUSEMOVE 消息到这个窗口。当 + +> 用户在客户区按下或者释放鼠标的键时,它投递下面的消息: + +> 按下 弹起 双击 + +> 左键 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK + +> 中键 WM_MBUTTONDOWN WM_MBUTTONUP WM_MBUTTONDBLCLK + +> 右键 WM_RBUTTONDOWN WM_RBUTTONUP WM_RBUTTONDBLCLK + +> 发送这些消息时, lParam 参数包含了鼠标的位置坐标,可以这样读出坐标信息。 + +> xPos = LOWORD (lParam); + +> yPos = HIWORD (lParam) + +实现坐标转化的函数 + +> 这些坐标都以客户区的左上角为原点,向右是 x 轴正方向,向下是 y 轴正方向。 + +> ClientToScreen 函数可以把坐标转化为以屏幕的左上角为原点的坐标。 + +> BOOL ClientToScreen(HWND hWnd, LPPOINT lpPoint) ; + +> BOOL ScreenToClient(HWND hWnd, LPPOINT lpPoint ); + +wParam 参数包含鼠标按钮的状态,这些状态都以 MK\_(意为 mouse key)为前缀,,取值 + +如下: + +| MK_LBUTTON | 左键按下 | +|-------------|-----------------| +| MK_MBUTTON | 中间的键按下 | +| MK_RBUTTON | 右键按下 | +| MK_SHIFT | \键按下 | +| MK_CONTROL | \键按下 | + +**设置文本和背景** + +> 设置背景色为: + +> wcex.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + +设置文本色 + +::SetTextColor(hdc, RGB(255, 0, 0)); + +::SetBkColor(hdc, ::GetSysColor(COLOR_3DFACE)); + +第四节GDI基本图形 + +**设备环境** + +理解一下几个含义: + +应用实例:HINSTANCE,表示整个应用实例 + +主窗体:hwnd,表示应用实例的主窗体,是一个窗体,不是应用实例 + +窗口客户区:主窗体客户区指的是窗体中菜单下边的内容,客户区,主要县市区 + +窗口客户区设备环境句柄:HDC绘图的句柄,可以是主窗体的设备环境也可以是主窗体客户区的设备环境的句柄。 + +**文本区域绘制** + +case WM_LBUTTONDOWN: + +> hdc = ::GetDC(hWnd); + +> // 设置 DC 结构中的文本颜色为红色(下一小节我们再介绍 Windows 下的颜色) + +> ::SetTextColor(hdc, RGB(255, 0, 0)); + +> // 设置 DC 结构中的文本背景颜色为蓝色 + +> ::SetBkColor(hdc, RGB(0, 0, 255)); + +> ::TextOut(hdc, 10, 10, sz, strlen(sz)); + +> ::ReleaseDC(hWnd, hdc); + +> break; + +在注册窗口类时,向 WNDCLASSEX结构的 style 成员添加一个 CS_OWNDC +标志,可以保存每次修改的内容。如果不设置的话,每次刷新窗口又会变为默认的设置,而不是左键点击后的设置。 + +wcex.style = CS_HREDRAW \| CS_VREDRAW \| CS_OWNDC; + +**颜色和像素点** + +**RGB**颜色RGB(255,255,255) + +像素点颜色设置 + +> COLORREF SetPixel( + +> HDC hdc, // 设备环境句柄 + +> int X, // 象素的 X 坐标 + +> int Y, // 象素的 Y 坐标 + +> COLORREF crColor // 要设置的 COLORREF 值 + +> ); + +> 像素点颜色获取 + +> COLORREF GetPixel( HDC hdc, int nXPos, int nYPos); + +**绘制线条** + +LineTo函数绘制直线。MoveToEx可以设置当前点。 + +::MoveToEx(hDC, 0, 0, NULL); + +::LineTo(hDC, 0, 500); + +BOOL MoveToEx( + +> HDC hdc, // 设备环境句柄 + +> int X, // 新位置的 X 坐标 + +> int Y, // 新位置的 Y 坐标 + +> LPPOINT lpPoint // +> 用来返回原来的当前点位置,如果不需要的话,这个参数可以被设为 NULL) + +使用GetClientRect函数获取窗口客户区的大小。 + +使用Polyline函数绘制相连的多条线段。 + +> BOOL Polyline(HDC hdc, CONST POINT \*lpPoint, int cPoints); + +> BOOL PolylineTo(HDC hdc, CONST POINT \*lpPoint, DWORD cPoints ); + +> lpPoint是指向POINT的数组的指针。 + +**绘制区域** + +Rectangle(hdc, x1, y1, x2, y2); // 画以(x1, y1)和(x2, +y2)为对角坐标的填充矩形 + +> Ellipse(hdc, x1, y1, x2, y2); // 以(x1, y1)和(x2, +> y2)为对角坐标定义一个矩形,然后画矩形相切的椭 + +> // 圆并填充 + +> Polygon(hdc, lpPoint, 5) // lpPoint 指向存放(x0, y0)到(x4, +> y4)的内存,函数从(x1, y1)到(x2, y2)... + +> // 到(x4, y4),再回到(x1, y1),一共画 5 条直线并填充 + +**坐标系统** + +**实例:小时钟** + +几个缩写的含义说明 + +WND window + +WS window style + +CS class style + +WM window message diff --git a/windows程序设计/Windows程序设计——基本知识.md b/windows程序设计/Windows程序设计——基本知识.md new file mode 100644 index 00000000..7aece0a7 --- /dev/null +++ b/windows程序设计/Windows程序设计——基本知识.md @@ -0,0 +1,21 @@ +**两种访问模式** + +Windows使用了内核模式和用户模式两种访问权限,来控制对内存的访问。每种资源都会标记相应的访问模式,只有对应模式才能访问对应的资源。 + +系统地址空间页只能通过内核模式。所有的用户地址空间都可以从用户模式访问。 + +当应用程序调用一个系统函数时,用户的应用程序会从用户模式切换到内核模式去执行。 + +**内核对象** + +内核对象是系统提供的用户模式下代码与内核模式下代码进行交互的基本接口。内核对象是一块内核分配的内存,只能在内核模式下的被访问。其资源为系统资源。内核对象的数据结构是隐蔽的,必须通过一个对象服务才能从对象中得到数据或向其中输入数据。 + +作用:为系统资源提供名字;在进程之间共享资源和数据;保护资源不会被未经认可的代码访问;跟踪对象的引用情况。 + +**对象句柄** + +调用函数创建内核对象时,函数返回标识这个对象的句柄。来定位内核对象。 + +**使用计数** + +内核对象是进程内的资源,使用计数属性记录对特定内核对象的引用次数,当系统发现引用次数是0时,自动关闭资源。 diff --git a/windows程序设计/Windows程序设计——线程.md b/windows程序设计/Windows程序设计——线程.md new file mode 100644 index 00000000..60650879 --- /dev/null +++ b/windows程序设计/Windows程序设计——线程.md @@ -0,0 +1,188 @@ +**线程创建** + +DWORD WINAPI ThreadProc(LPVOID lpParam); // 线程函数名称 ThreadProc 可以是任意的 + +WINAPI +是一个宏明,用来说明调用参数的进栈方式和出栈方式。Windows规定,由内核函数负责调用的用户函数,必须定义为这个类型。 + +线程创建函数 + +HANDLE CreateThread ( + +> LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性 + +> DWORD dwStackSize, // 指定线程堆栈的大小 + +> LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数的起始地址 + +> LPVOID lpParameter, // 传递给线程函数的参数 + +> DWORD dwCreationFlags, // 指定创线程建后是否立即启动 + +> DWORD\* lpThreadId // 用于取得内核给新生成的线程分配的线程 ID 号 + +> ); + +创建线程的具体示例 + +\#include \ + +> \#include \ + +> // 线程函数 + +> DWORD WINAPI ThreadProc(LPVOID lpParam) + +> { int i = 0; + +> while(i \< 20) + +> { printf(" I am from a thread, count = %d \\n", i++); } + +> return 0; + +> } + +> int main(int argc, char\* argv[]) + +> { HANDLE hThread; + +> DWORD dwThreadId; + +> // 创建一个线程 + +> hThread = ::CreateThread ( + +> NULL, // 默认安全属性 + +> NULL, // 默认堆栈大小 + +> ThreadProc, // 线程入口地址(执行线程的函数) + +> NULL, // 传给函数的参数 + +> 0, // 指定线程立即运行 + +> &dwThreadId); // 返回线程的 ID 号 + +> printf(" Now another thread has been created. ID = %d \\n", dwThreadId); + +> // 等待新线程运行结束 + +> ::WaitForSingleObject (hThread, INFINITE); + +> ::CloseHandle (hThread); + +> return 0; + +> } + +WaitForSingleObject +函数用来等待制定对象变为受信状态。默认情况下为INFINITE,但在指定对象变为受信状态时会自动结束 + +**线程内核对象** + +与进程内核对象相似,都是存储对象的基本信息,用来管理线程、进程的对象。 + +![clipboard.png](media/71827cbcb84634eda0a5e339f5c8e351.png) + +SuspendCount,制定了当前线程的状态。0 表示处于可调度状态,1,表示处于挂起状态。 + +获取线程的句柄函数 + +> HANDLE OpenThread( + +> DWORD dwDesiredAccess, // 想要的访问权限,可以为 THREAD_ALL_ACCESS 等 + +> BOOL bInheritHandle, // 指定此函数返回的句柄是否可以被子进程继承 + +> DWORD dwThreadId // 目标线程 ID 号 + +> ); + +> 唤醒一个挂起的线程 + +> DWORD ResumeThread (HANDLE hThread); // 唤醒一个挂起的线程 + +> 挂起一个可调度的线程 + +> DWORD SuspendThread (HANDLE hThread); // 挂起一个线程 + +ExitCode退出代码 + +DWORD dwExitCode; + +> if(::GetExitCodeThread(hThread, &dwExitCode)) + +> { if(dwExitCode == STILL_ACTIVE) + +> { // 目标线程还在运行 } + +> else + +> { // 目标线程已经中止,退出代码为 dwExitCode } + +> } + +Signaled是否受信。线程运行期间,Signaled的值为False,线程结束后,Signaled的值为True + +**线程终止** + +- 线程执行结束自然终止 + +- 使用ExitTread函数来终止自身。 + +void ExitThread( DWORD dwExitCode); // 线程的退出代码 + +- 使用TerminateThread函数强行终止另一个线程 + +BOOL TerminateThread( + +> HANDLE hThread, // 目标线程句柄 + +> DWORD dwExitCode // 目标线程的退出代码 + +> ); + +- 使用ExitProcess函数结束进程,相关县城就会结束。 + +**线程的优先级** + +**Windows**的6个优先级类:idle、below normal、normal、above normal、 +high、real-time。 + +CPU支持0-31优先级号(数字越大优先级越高。) + +优先级设置函数 + +BOOL SetThreadPriority(HANDLE hThread,int nPriority ); + +线程同步 + +…… + +设计自己的线程局部存储 + +…… + +设计线程类 + +…… + +多线程文件搜索器 + +…… + +OHIUHI + +**回调函数的定义** + +> 回调函数就是一个通过函数指针调用的函数。如果你把函数的[指针](https://baike.baidu.com/item/%E6%8C%87%E9%92%88)(地址)作为[参数传递](https://baike.baidu.com/item/%E5%8F%82%E6%95%B0%E4%BC%A0%E9%80%92)给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。 + +**::含义** + +类作用域,类名::成员变量。用来表示类和他的成员变量 + +命名空间作用域,命名空间::变量或函数。命名空间中的成员 + +全局作用域,::变量。全局的变量或函数,好像可以省略。 diff --git a/windows程序设计/Windows程序设计——进程创建.md b/windows程序设计/Windows程序设计——进程创建.md new file mode 100644 index 00000000..45de2f4e --- /dev/null +++ b/windows程序设计/Windows程序设计——进程创建.md @@ -0,0 +1,382 @@ +这一部分的学习还是要通过大量的代码阅读吧。在这里可以截取有用的代码并添加注释。 + +**进程定义** + +正在运行的程序,拥有自己的虚拟地址空间拥有自己的代码、数据和其他资源。 + +组成:进程内核对象,操作系统使用内核对象来管理该进程。私有的虚拟地址空间。 + +**应用程序启动过程** + +操作系统通过CreateProcess +函数来创建新的进程,分配虚拟地址空间,加载代码和数据;然后创建一个主线程,调用main函数。 + +CreateProcess( + +> LPCSTR lpApplicationName, // 可执行文件的名称 + +> LPSTR lpCommandLine, // 指定了要传递给执行模块的参数。 + +> LPSECURITY_ATTRIBUTES lpProcessAttributes,// 进程安全性,值为 NULL +> 的话表示使用默认的安全属性 + +> LPSECURITY_ATTRIBUTES lpThreadAttributes,// 线程安全性,值为 NULL +> 的话表示使用默认的安全属性 + +> BOOL bInheritHandles, // 指定了当前进程中的可继承句柄是否可被新进程继承。 + +> DWORD dwCreationFlags, // 指定了新进程的优先级以及其他创建标志 + +> LPVOID lpEnvironment, // 指定新进程使用的环境变量 + +> LPCSTR lpCurrentDirectory, // 新进程使用的当前目录 + +> LPSTARTUPINFO lpStartupInfo, // 指定新进程中主窗口的位置、大小和标准句柄等 + +> LPPROCESS_INFORMATION lpProcessInformation +> //【out】返回新建进程的标志信息,如 ID 号、句柄等 + +); + +对创建进程中用到的结构体进行简单说明。通过STARTUPINFO类型的变量,指定新的进程的相关信息。通过GetStartupInfo函数来获取父进程创建自己时使用的变量: + +typedef struct { + +> DWORD cb; // 本结构的长度,总是应该被设为 sizeof(STARTUPINFO) + +> LPSTR lpReserved; // 保留(Reserve)字段,即程序不使用这个参数 + +> LPSTR lpDesktop; // 指定桌面名称 + +> LPSTR lpTitle; // 控制台应用程序使用,指定控制台窗口标题 + +> DWORD dwX; // 指定新创建窗口的位置坐标(dwX,dwY)和大小信息 + +> DWORD dwY; + +> DWORD dwXSize; + +> DWORD dwYSize; + +> DWORD dwXCountChars; // 控制台程序使用,指定控制台窗口的行数 + +> DWORD dwYCountChars; + +> DWORD dwFillAttribute; // 控制台程序使用,指定控制台窗口的背景色 + +> DWORD dwFlags; // 标志。它的值决定了 STARTUPINFO +> 结构中哪些成员的值是有效的。 + +> WORD wShowWindow; // 窗口的显示方式 + +> WORD cbReserved2; + +> LPBYTE lpReserved2; + +> HANDLE hStdInput; // 控制台程序使用, 几个标准句柄 + +> HANDLE hStdOutput; + +> HANDLE hStdError; + +} STARTUPINFO, \*LPSTARTUPINFO; + +通过pROCESS_INFORMATION结构体来获取进程创建后的信息 + +typedef struct{ + +> HANDLE hProcess; // 新建进程的内核句柄 + +> HANDLE hThread; // 新建进程中主线程的内核句柄 + +> DWORD dwProcessId; // 新建进程的 ID + +> DWORD dwThreadId; // 新建进程的主线程 ID + +} PROCESS_INFORMATION, \*LPPROCESS_INFORMATION; + +**解决了字符集的问题** + +发现内核对象的方法中W表示的宽字符,一般对应的是utf8,工程如果是用unicode进行编码的时候,就会使用W结尾的内核方法。(非Unicode编码的时候链接A结尾的方法)。所以在工程中可以配置为多字符编码,这样可以调用程序设计中的大部分代码,不存在编码问题。 + +**进程控制** + +**获取进程快照的方法** + +> \#include \ + +> \#include \ // 声明快照函数的头文件 + +> int main(int argc, char\* argv[]) + +> { + +> //这是一个进程的记录变量 + +> PROCESSENTRY32 pe32; + +> // 在使用这个结构之前,先设置它的大小 + +> pe32.dwSize = sizeof(pe32); + +> // +> 给系统内的所有进程拍一个快照,这个对象是一个列表,需要用专门的函数进行遍历 + +> HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + +> if(hProcessSnap == INVALID_HANDLE_VALUE) + +> { + +> printf(" CreateToolhelp32Snapshot 调用失败! \\n"); + +> return -1; + +> } + +> // 遍历进程快照,轮流显示每个进程的信息 + +> BOOL bMore = ::Process32First(hProcessSnap, \&pe32); + +> while(bMore) + +> { + +> printf(" 进程名称: %s \\n", pe32.szExeFile); + +> printf(" 进程 ID 号: %u \\n\\n", pe32.th32ProcessID); + +> bMore = ::Process32Next(hProcessSnap, \&pe32); + +> } + +> // 不要忘记清除掉 snapshot 对象 + +> ::CloseHandle(hProcessSnap); + +> return 0; + +> } + +CreateToolhelp32Snapshot()也可以获取其他类型的快照。TH32CS_SNAPPROCESS、TH32CS_SNAPHEAPLIST、TH32CS_SNAPMOUDULE、TH32CS_SNAPMOUDULE。 + +储存进程信息的结构体PROCESSENTRY32 + +typedef struct + +> { DWORD dwSize; // 结构的长度,必须预先设置 + +> DWORD cntUsage; // 进程的引用记数 + +> DWORD th32ProcessID; // 进程 ID + +> DWORD th32DefaultHeapID; // 进程默认堆的 ID + +> DWORD th32ModuleID; // 进程模块的 ID + +> DWORD cntThreads; // 进程创建的线程数 + +> DWORD th32ParentProcessID; // 进程的父线程 ID + +> LONG pcPriClassBase; // 进程创建的线程的基本优先级 + +> DWORD dwFlags; // 内部使用 + +> CHAR szExeFile[MAX_PATH]; // 进程对应的可执行文件名 + +> } PROCESSENTRY32; + +**终止当前进程** + +主线程的入口函数返回。 + +进程中一个线程调用了ExitProcess函数。 + +此进程中的所有线程都结束了。 + +其他进程中的一个线程调用了TerminateProcess函数 + +说明: + +退出当前进程 + +void ExitProcess(UINT uExitCode); // 参数 uExitCode +为此程序的退出代码,当期那进程力科技术。 + +终止其他进程 + +BOOL TerminateProcess( + +> HANDLE hProcess, // 要结束的进程(目标进程)的句柄 + +> UINT uExitCode // 指定目标进程的退出代码,你可以使用 GetExitCodeProcess +> 取得一个进程的退出代码 + +> );//用来结束其他进程。 + +获取某个进程的句柄,方便对一个进程进行操作 + +HANDLE OpenProcess( + +> DWORD dwDesiredAccess, // 想得到的访问权限,可以是 +> PROCESS_ALL_ACCESS,所有可以进行的权限,PROCESS_QUERY_INFORMATION +> 查看该进程信息的权限…… + +> BOOL bInheritHandle, // 指定返回的句柄是否可以被继承 + +> DWORD dwProcessId // 指定要打开的进程的 ID 号 + +> ); + +> 终止其他进程的代码示例 + +> BOOL TerminateProcessFromId(DWORD dwId) + +> { BOOL bRet = FALSE; + +> // 打开目标进程,取得进程句柄 + +> HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId); + +> if(hProcess != NULL) + +> { // 终止进程 + +> bRet = ::TerminateProcess(hProcess, 0); + +> } + +> CloseHandle(hProcess);//注意句柄类型需要使用这个函数进行关闭 + +> return bRet; + +> } + +> 进程终止后会发生的事情 + +> 1\. 相关对象句柄都被关闭 + +> 2\. 进程内的线程终止执行 + +> 3\. 集成内核对象变为受信状态,所有等待在此对象上的线程开始运行。 + +> 4\. 系统将进程对象中退出代码的值由STILL_ACTIVE改为退出码。 + +**保护进程** + +> 以下函数用来实现进程内存的读写。 + +> BOOL ReadProcessMemory( + +> HANDLE hProcess, // 待读进程的句柄 + +> LPCVOID lpBaseAddress, // 目标进程中待读内存的起始地址 + +> LPVOID lpBuffer, // 用来接受读取数据的缓冲区 + +> DWORD nSize, // 要读取的字节数 + +> LPDWORD lpNumberOfBytesRead // 用来供函数返回实际读取的字节数 + +> ); + +> WriteProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize, +> lpNumberOfBytesRead); // 参数含义同上 + +> 以下函数用来获取当前系统的版本信息 + +> BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInfo); + +> 系统会将操作系统的版本信息返回到参数 lpVersionInfo 指向的 OSVERSIONINFO +> 结构中。 + +> typedef struct OSVERSIONINFO { + +> DWORD dwOSVersionInfoSize; // 本结构的大小,必须在调用之前设置 + +> DWORD dwMajorVersion; // 操作系统的主版本号 + +> DWORD dwMinorVersion; // 操作系统的次版本号 + +> DWORD dwBuildNumber; // 操作系统的编译版本号 + +> DWORD dwPlatformId; // 操作系统平台。可以是 VER_PLATFORM_WIN32_NT(2000 +> 系列)等 + +> TCHAR szCSDVersion[128]; // 指定安装在系统上的最新服务包,例如“Service Pack +> 3”等 + +> } OSVERSIONINFO; + +**Windows程序设计中常见的类型。** + +| BOOL/BOOLEAN | 8bit,TRUE/FALSE | 布尔型 | | +|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|-----------------------------------------------------------------------------------|---| +| BYTE | unsigned 8 bit | | | +| BSTR CComBSTR \_bstr_t | 32 bit | BSTR是指向字符串的32位指针 是对BSTR的封装 是对BSTR的封装 | | +| CHAR | 8 bit | (ANSI)字符类型 | | +| COLORREF | 32 bit | RGB颜色值 整型 | | +| DWORD | unsigned 32 bit | 整型 | | +| FLOAT | float型 | float型 | | +| HANDLE | | Object句柄 | | +| HBITMAP | | bitmap句柄 | | +| HBRUSH | | brush句柄 | | +| HCURSOR | | cursor句柄 | | +| HDC | | 设备上下文句柄 | | +| HFILE | | OpenFile打开的File句柄 | | +| HFONT | | font句柄 | | +| HHOOK | | hook句柄 | | +| HKEY | | 注册表键句柄 | | +| HPEN | | pen句柄 | | +| HWND | | window句柄 | | +| INT | 不同系统长度不同 | 一般为32位 | | +| LONG | 不同系统长度不同 | 一般为32位 | | +| LONGLONG | | 64位带符号整型 | | +| LPARAM | 32 bit | 消息参数 | | +| LPBOOL | | BOOL型指针 | | +| LPBYTE | | BYTE型指针 | | +| LPCOLOREF | | COLORREF型指针 | | +| LPCSTR/LPSTR/PCSTR | | 指向8位(ANSI)字符串类型指针 | | +| LPCWSTR/LPWSTR/PCWSTR | | 指向16位Unicode字符串类型 | | +| LPCTSTR/LPTSTR/PCTSTR | | 指向一8位或16位字符串类型指针 | | +| LPVOID | | 指向一个未指定类型的32位指针 | | +| LPDWORD | | 指向一个DWORD型指针 | | +| 其他相似类型: LPHANDLE、LPINT、LPLONG、LPWORD、LPRESULT PBOOL、PBOOLEAN、PBYTE、PCHAR、PDWORD、PFLOAT、PHANDLE、PINT、PLONG、PSHORT…… 说明:(1)在16位系统中 LP为16bit,P为8bit,在32位系统中都是32bit(此时等价) (2)LPCSTR等 中的C指Const,T表示TCHAR模式即可以工作在ANSI下也可UNICODE | | | | +| SHORT | usigned | 整型 | | +| 其他UCHAR、UINT、ULONG、ULONGLONG、USHORT为无符号相应类型 | | | | +| TBYTE | | WCHAR型或者CHAR型 | | +| TCHAR | | ANSI与unicode均可 | | +| VARIANT \_variant_t COleVariant | | 一个结构体参考OAIDL.H \_variant_t是VARIANT的封装类 COleVariant也是VARIANT的封装类 | | +| | | | | +| | | | | +| WNDPROC | | 指向一个窗口过程的32位指针 | | +| WCHAR | | 16位Unicode字符型 | | +| WORD | | 16位无符号整型 | | +| WPARAM | | 消息参数 | | +| MFC 独有 数据 类型 | 下面两个数据类型是微软基础类库中独有的数据类型 | | | +| | POSITION | 标记集合中一个元素的位置的值 被MFC中的集合类所使用 | | +| | LPCRECT | 指向一个RECT结构体常量(不能修改) 的32位指针 | | +| | CString | 其实是MFC中的一个类 | | +| | | | | + +**Windows数据类型命名规律** + +- 基本数据类型包括:BYTE、CHAR、WORD、SHORT、INT等。 + +- 指针类型的命令方式一般是在其指向的数据类型前加“LP”或“P”,比如指向DWORD的指针类型为“LPDWORD”和“PDWORD” + +- 各种句柄类型的命名方式一般都是在对象名前加“H”,比如位图(BITMAP)对应的句柄类型为“HBITMAP”。 + +- 无符号类型一般是以“U”开头,比如“INT”是符号类型,“UINT”是无符号类型 + +- DWORD实质上就是 unsigned long 数据类型,32位无符号整型。 + +- 而经常要用到的HANDLE类型实质上是无类型指针void,HANDLE定义为: + + typedof PVOID HANDLE; + + HANDLE实际上就是一个PVOID,那PVOID又是什么呢? + + Typeof void \*PVOID; + + PVOID就是指向void的指针。 diff --git a/windows程序设计/media/71827cbcb84634eda0a5e339f5c8e351.png b/windows程序设计/media/71827cbcb84634eda0a5e339f5c8e351.png new file mode 100644 index 00000000..7b7c695c Binary files /dev/null and b/windows程序设计/media/71827cbcb84634eda0a5e339f5c8e351.png differ diff --git a/windows程序设计/建立Windows编程的体系.md b/windows程序设计/建立Windows编程的体系.md new file mode 100644 index 00000000..6559d3a1 --- /dev/null +++ b/windows程序设计/建立Windows编程的体系.md @@ -0,0 +1,34 @@ +C++ +是一种语言,像java、Python语言,他们都通过强大库来提供定向的功能。他们都包含自己基本的库,用来实现基础的功能,也有自己的基本语法。对于语言的学习,起始就是对基本语法的了解,和最基础的函数库(自带函数库的学习) + +真正的开发过程是不可能仅仅限于对语言的学,真正开发过程往往涉及大量的第三方库,C开发也是如此。 + +C、C++开发windows应用程序的第三方库就是微软光放提供的SDK开发工具包。 + +C语言不具有跨平台的特性,因为如果他要开发windows应用程序,必须要使用windows版本的开发工具包进行开发,到了其他系统就不能使用了。 + +C语言的SDK开发工具包,实现了,程序调用系统资源的方式,VisualC++是常用的开发工具,可以集成SDK开发工具包,使用集成环境进行开发。 + +一般而言SDK即开发 [Windows](https://baike.baidu.com/item/Windows) +平台下的应用程序所使用的 +SDK。它可以简单的为某个程序设计语言提供[应用程序接口](https://baike.baidu.com/item/%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%8E%A5%E5%8F%A3) +[**API**](https://baike.baidu.com/item/API)的一些文件,但也可能包括能与某种嵌入式系统通讯的复杂的硬件。一般的工具包括用于调试和其他用途的实用工具。SDK +还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。 + +SDK开发工具包括了基础的API,主要包括以下几个模块和基础类库: + +GDI + +GDI+ + +OpenGL + +MonitorConfiguration + +WindowsColor System + +WPF bitmap Effects + +Win32 Application,即SDK程序。 + +MFC是基于WIN32即SDK的一个框架 diff --git a/单片机/单片机开发系统.md b/单片机/单片机开发系统.md new file mode 100644 index 00000000..fda5e505 --- /dev/null +++ b/单片机/单片机开发系统.md @@ -0,0 +1,21 @@ +# 仿真开发 + +## > 仿真开发系统 + +----- + +* **仿真开发系统** + 1. 能够诊断用户系统的硬件电路 + 2. 能够对程序进行加载和修改 + 3. 能够对程勋进行运行和调试和状态显示 + 4. 将程序固化(烧录)到程序存储器中 + +* **仿真器** + 1. 单片机替代型仿真器和接口型 + 2. 像飞思卡尔的LQ-USBDM +* **开发过程** + 1. 硬件设计和电路设计,pcb布线,电路板设计 + 2. 软件编程(PC机 + 3. 动态在线调试(单步调试 + 4. 固化程序 + 5. 脱机运行 \ No newline at end of file diff --git a/单片机/单片机指令系统概论.md b/单片机/单片机指令系统概论.md new file mode 100644 index 00000000..b028cb20 --- /dev/null +++ b/单片机/单片机指令系统概论.md @@ -0,0 +1,70 @@ +#单片机的指令系统概述 + +## >指令系统概述 + +----- + +* **基本知识** + 1. 包括功能、时间、空间三种属性,每条指令指明具体功能,一条指令执行所用的时间,指令占用的字节数 + 2. 机器语言指令、汇编语言指令。机器语言的复杂指令集,111条。 + 3. 每条指令由操作码和操作数组成。 + +* **汇编** + 1. [标号:] 操作码助记符 [目的操作数][,源操作数][;注释] + 2. 标号要求:非关键字,字符开头,字符数字组成,不超过八个字符,行号位于行首 + +## >寻址方式 + +----- + +> 地址给出的方式 +> 操作数的定义:表示参加操作的**数的本身**或者**操作数所在的地址**。这里的操作数更像是备操作的数据,如果是一个地址时,就像指针指向的数据。暂且理解为动作和动作操纵的对象吧! + +* **立即寻址** + 操作数直接出现在指令当中,作为操作码的一部分。#号操作数。 + MOV A,#80H; +* **直接寻址** + 直接使用数所在单元的地址找到该操作数,direct。 + MOV A,00H; +* **寄存器寻址** + 寄存器中存有操作数,Rn表示工作中的寄存器组,DPTR,A,B。direct。 + MOV A,RO; +* **寄存器间接寻址** + 寄存器中存有操作数的地址,寄存器起到地址指针的作用。 + MOV A,@R0;R0作为地址,将其指向的数据传送到RAM中 + MOVX A,@DPTR;DPTR作为地址,将其指向的数据传到RAM中 +* **变址寻址** + 基址寄存器和变址寄存器的和,基址寄存器(只能是指令计数器pc和数据指针DPTR)@+。 + 目的是用来访问程序存储器中的常数表。 + MOVE A,@A+DPTR;数据指针可以任意更改 + MOVE A,@A+PC;PC示取指令的pc+1,不能任意更改 +* **相对寻址** + 当前的PC值加上一个相对值形成的地址+ + 指令的第二个字节用八位二进制补码表示,用于跳转当前执行的程序。 + PC中的当前地址称为基地址,第二个字节的数据称为偏移量 + 目的地址=指令存放地址+指令字节数+rel +* **位寻址** + 对RAM的位寻址区或可为寻址的特殊功能寄存器的某些位进行操纵。 + SETB 3DH;将27H.5 位置置为1。 + + + +------ + +> Rn 表示工作寄存器之一 +> Ri 工作寄存器RO或R1 +> \#data 表示8位立即数 +> \#data16 表示16位立即数 +> direct 表示RAM或SFR的地址 +> bit 片内RAM或SFR的位地址 +> addr11 11位目的地址 +> addr16 16位目的地址 +> rel 补码形式的8位地址偏移量 +> / 位操作指令,该位求反后参与操作,不影响该位 +> X RAM的直接地址 +> (X) 表示地质单元的内容 +> -> 左边内容送入右边内容 + +------------- +[1] CISC complex instruction set computer 复杂指令计算机 +[2] RISC reduced instruction set computer 精简指令计算机 \ No newline at end of file diff --git a/单片机/单片机汇编程序设计.md b/单片机/单片机汇编程序设计.md new file mode 100644 index 00000000..30bd3be5 --- /dev/null +++ b/单片机/单片机汇编程序设计.md @@ -0,0 +1,56 @@ +# 单片机程序设计 + +## >编程语言背景 + +----- + +* **编程语言** + 1. 机器语言, + 2. 汇编语言,需要通过汇编生成机器语言,不同单片机的汇编语言不能通用。 + 3. 高级语言,通过编译编程机器语言 +* **汇编结构** + 1. 四部分:标号:操作码 操作数;注释 + +* **汇编伪指令** + 1. 作用:不产生可执行的目标代码,帮助进行汇编的指令。指定程序或数据的起始位置,给出存放数据的地址。为中间运算保留有份存储空间,表示源程序结束等。 + 2. 起始指令ORG,重新制定了目标程序的起始位置(不再是OOOOH),可以多次使用,定义不同程序段的起始地址 + 3. 结束指令END,只能有一个end指令 + 4. 定义字节的伪指令DB,定义从指定单元开始的若干个字节的数据,用于定义数据常数表。 + - ORG 2000H + - DB 30H,8AH,7FH,'a' + 5. 定义数据字的伪指令DW,定义从指定单元开始存储若干个字的数据(双字节称为字) + - DB 'a','b' == DB 61H,62H == DW 6162H; + 5. 等值伪指令EQU,赋值指令,用特定的字符代替某一个常数。AA EQU 30H; + 6. 位地址定义伪指令BIT,用于给指定位定义一个标号。 + - ABC BIT P1.1;P1.1 可以用ABC标号代替; + 7. 表示目前地址的伪指令$ + +## > 汇编语言程序设计 + +----- + +> 加深对面向过程的理解,觉得需要补充C语言的一些知识。 +> 单片机可以实现电脑完全仿真,如果日后对汇编和51单片机有兴趣的话可以使用Proteus模拟51单片机 +> 但是以及用keil进行编程和开发。 + +* **程序流程图** + 1. 画图 + - 开始框,动作框, 判断框,结束框。 + - 顺序结构 + - 分支结构程序 + - 循环结构 + - 子程序结构 + + 2. 图文翻译 + > 感觉汇编面向过程的时候,用程序流程图,可以直接翻译为汇编代码。 + + + +## > 汇编语言与机器语言 + +----- + +* **汇编** + 汇编的指令能够被 指令存储器翻译成为特定的机器码 + 数据能够被 数据存储器储存。 + 每一条汇编语言,都有一个对应的机器码。 \ No newline at end of file diff --git a/单片机/单片机的内部结构原理.md b/单片机/单片机的内部结构原理.md new file mode 100644 index 00000000..17826573 --- /dev/null +++ b/单片机/单片机的内部结构原理.md @@ -0,0 +1,98 @@ +#MCS-51 单片机的基础知识介绍 + +## >单片机内部基本组成 + +----- + +* **功能结构原理图** +这里有一张图片 +主要部分:中央处理器、特殊功能寄存器、存储器系统、定时/计数器、并行接口,串行接口、中断系统。 +* **51单片机内部细化图** +这里也有一张图片 +* **SFR特殊功能寄存器** +这里还有一张图片 + +## >mcs-51单片机-中央处理器cpu-运算部件 + +----- + +* **ALU 算数逻辑运算单元** + 1. 八位二进制加减乘除算术运算 + 2. 逻辑与、或、异或、循环移位、补、清零等逻辑运算 + 3. 置位、清零、求反、测试转移、位逻辑与或非等位运算(在内部的位运算器C/CY当中) +* **ACC 八位寄存器累加器** + 1. 加法运算 +* **B 辅助寄存器** + 1. 乘法存放被乘数 + 2. 除法存放除数 +* **PSW 标志寄存器** + 1. psw.7 进位标志位C + 2. psw.6 辅助进位标志位AC + 3. psw.5 用户自定义标志位F0 + 4. psw.4/psw.3 寄存器组RS1/RA0 选择位(选择正在工作的寄存器组) + 5. psw.2 溢出标识位OV + 6. psw.0 奇偶标志位P + +## >mcs-51单片机-中央处理器cpu-控制部件 + +----- + +* **控制电路** +* **时序电路** +* **指令寄存器** +* **指令译码器** +* **计数器PC** +* **堆栈指针SP** +* **数据指针DPTR** +* **信息传送控制部件** + + +## >mcs-51单片机-存储结构 + +----- + +* **程序存储器** + 1. 用于存储单片机工作时的程序。程序计数器(寄存器)PC用于存放要执行的指令的地址,并依次取出执行。使用ROM作为程序存储器。程序计数器有16位,有216个地址码,对应64k的寻址空间。 + 2. 物理结构上分为片内存程序储器和片外程序存储器。内部程序存储器大小为0/4kB/8kB,对应寻址地址为0/0000H-0FFFH/0000H-1FFFH,片外程序存储器的寻址地址为片内存储器之后的部分,多余部分的片外存储器不进行寻址。共64KB的地址区域。物理上通过片外程序存储器引脚EA点评的高低来确定。高电平,片内去指令执行,低电平片外取指令执行。 + 3. 0000H为单片机系统程序的系统地址。 + +* **数据存储器** + 1. 程序执行时所需要的数据,片内数据存储器和片外数据存储器。数据计数器有8位地址,28个地址码,用两个16进制数FFH表示,对应256K的寻址空间。 + 2. 片内数据存储器:SFR特殊寄存器、RAM程序存储器具有相同的地址空间。51系列单片机,内部数据RAM128字节,地址编码为00H-7FH,寄存器SFR数据128字节,地址编码80H-FFH,地址不重叠。 + 3. 片内数据存储器RAM分割为工作寄存器区(地址码00-1FH)、位寻址区(20-2FH)、RAM区(30-7FH),堆栈区(80-FFH)。 + - 工作寄存器区,32个地址码对应32个字节的空间,分为四组(每组8个字节,储存有8个寄存器的地址码,对应8个寄存器),淡定点默认工作的寄存器组由程序状态字PSW.4/.3,RS0和RS1来决定。 + - 位寻址区,16个地址码对应16个字节的空间128位,支持按位寻址(以前的寻址结果是字节,现在是以为,即一个地址码,对应一位)。 + - 一般RAM区, + - 堆栈区和堆栈指针SP,按照先入后出的原则进行内存管理。mcs-51单片机为向上生长型,存入数据从低端向高端延伸push,取出数据从高端向低端延伸pop。 + 4. 特殊功能寄存器SFR,(这里需要一张图)如果地址码对应寻址空间中的字节,仍是一个地址码,则相当于地址(指针)的嵌套。 + 5. 片外数据存储器,最多扩展为64K空间,数据指针DPTR(数据计数器,DPH和DPL,256个字节称为一个页面,即一个字节八位所构成的所有的地址码,能形成一个页面的数据。) +* **常见的存储器类型** + 1. RAM存储器 + 2. ROM存储器 + 3. PROM存储器、EPROM存储器、EEPROM存储器 + 4. FLASHI存储器 +> 存储结构可以分为冯诺依曼结构和哈弗结构,前者将程序的指令存储器和数据村粗器放在一块,后者将指令存储器和数据存储器分离了。 + +## >mcs-51单片机-单片机的输入输出接口 + +----- + +* **I/O接口构成** + 1. 涉及到电路的很多知识,无能为力了。但是感觉都是数字电子技术课上的知识(好多都是诶)。 + 2. 四个8位I/O并行接口,输入时具有锁存能力,输出时,具有缓存能力。 + 3. 具体的每一个口的电路实现和功能等以后在了解吧。 + + + + +> 感觉这里的51单片机不能理解为单片机的一个时代,并非其他的单片机都是从这一代产品发展而来的,也并非必须继承51单片机的特点。 +> mcs-51单片机只能说是单片机的某个生产厂商的某个型号,与飞思卡尔系列,Dallas系列,飞利浦系列,Motorola系列等具有并列关系。 +> 单片机的分类,一种方式时按位分类,8/16/32位单片机。或者按照公司及其型号来分。每种单片机具有相同的语言标准(汇编语言通用),也有各自的C高级语言开发环境,其功能大同小异,所以,应该针对某个通用程度比较高的单片机学习即可(mcs-51单片机) +> 这里的地址编码访问指令时,访问的是字节编码,而非位编码。64KB的寻址空间=216位地址码=216个地址码=4个16进制数FFFFH=两个字节的地址码 +> 寻址空间,就是能通过地址码找到的空间的大小,其中每个地址码对应一个字节,两个字节16位的地址码最多能寻址64K个字节的空间。单个字节8位的地址码,最多能寻址256个字节的空间。 + +英文简称解读 +[1] SFR special function register 特殊功能寄存器 +[2] ALU arithmetic logical unit 算数/逻辑运算单元 +[3] FIFO first in,first out FIFO队列,先进先出 +[4] MUX multiplexer 数据选择器/多路开关/多路选择器(数电上有所染指) \ No newline at end of file diff --git a/单片机/单片机的外部结构.md b/单片机/单片机的外部结构.md new file mode 100644 index 00000000..b8203861 --- /dev/null +++ b/单片机/单片机的外部结构.md @@ -0,0 +1,28 @@ +# 单片机的外部结构 + +## >mcs-51单片机-外部引脚 + +------ + +* **引脚图** +(这里应该有一张图) +* **输入输出** + 1. PO口,标准输入输出口,I/O扩展口,骗完存储器接口,分时复用为第八位地址总线。 + 2. P1口 + 3. P2口, + 4. P3口,每一个引脚有独立的功能(此处有一张图) + +* **控制线** + 1. ALE/PROG地址锁存器信号输出端 + 2. PSEN片外存储器控制端 + 3. RST/Vpd重置或备用电源。 + 4. EA/Vpp片外程序存储器。 + 5. Vcc/Vss电源正负 + 6. XTAL1/XTAL2外接晶振引脚。 + + +## >mcs-51单片机-外部扩展总线的形成 + +------ + +> 以后补充 \ No newline at end of file diff --git a/单片机/单片机的执行方式.md b/单片机/单片机的执行方式.md new file mode 100644 index 00000000..a5663af2 --- /dev/null +++ b/单片机/单片机的执行方式.md @@ -0,0 +1,70 @@ +# 单片机的工作方式 + +## > mcs-51单片机-复位方式 + +------- + +RST 端2个机器周期以上的高电位。 + +包括按键复位(通过手动按键决定)、上电复位(通过电路决定) + + +## > mcs-51单片机-程序执行方式 + +------- + +PC程序计数器(非特殊cpu内部寄存器),指针指向最开始的程序地址,逐条进行取指令,译码,执行操作 + +## > mcs-51单片机-单步执行方式 + +------- + +用于调试,可以通过汇编语言实现,可以等待按键 + + +## > mcs-51单片机-掉电和节电方式 + +------- + +掉电方式,主电源掉至下限->中断操作->备用电源供RAM保留数据->主电源回复->重启运行 + +节电方式,很多器件不懂 + +## > mcs-51单片机-编程和校验方式 + +------- + +相关的系统运行要求 + +## > mcs-51单片机-工作过程及时序 + +------- + +震荡电路 产生时钟脉冲 主频的晶振频率 +两个震荡周期为一个状态周期S(P1,P2) +6个状态周期为一个机器周期 +1或者2个机器周期为一个指令周期 +**单片机如何读取外部指令** + 1. 涉及到时序逻辑(以后再深入了解) + + +## > mcs-51单片机-单片机的选型策略和常见cpu的封装方式 + +------- +选型 + +* 功能 +* 存储容量 +* 速度 +* 功耗 +* 封装与管脚 +* 抗干扰能力 +* 特殊应用需求 + +封装 + +* **DIP封装** +* **QFP封装** +* **PFP封装** +* **PGA封装** +* **BGA封装** \ No newline at end of file diff --git a/单片机/单片机背景知识.md b/单片机/单片机背景知识.md new file mode 100644 index 00000000..5f9c9f40 --- /dev/null +++ b/单片机/单片机背景知识.md @@ -0,0 +1,63 @@ +# 单片机学习 + +## > 单片机的背景知识 + +***** + +* **单片机概述** + 1. 注意一下几个名词:冯诺依曼计算机,存储程序计算机,通用计算机,运算器,控制器,存储器,输入设备,位数,容量,字长,外存和内存,输入设备,电子管计算机,晶体管计算机,集成电路计算机,量子计算机,工作站,服务器,个人计算机,嵌入式计算机,云计算机。 + 2. 嵌入式系统是一种完全嵌入空间内部,为特定应用而设计的专用计算机。 + +* **单片机的特点** + 1. 存储结构上采用哈弗结构,ROM和RAM完全分开,功能和寻址方式不同。 + 2. 芯片引脚,采用分时复用技术,有程序决定引脚在当前起什么作用 + 3. 内部资源访问,使用寄存器SFR。 + 4. 采用面向控制流的指令系统。 + 5. 内部集成全双工的串行接口,用于同其他外设进行通信。 + 6. 具有很强的扩展能力,很方便地在外部扩展各种电路,与许多微机接口芯片兼容。 + +* **单片机与DSP,CPLD,FPGA的区别** + 1. DSP digital signal processor 数字信号处理器,独特的微处理器。强大的数据处理能力和高运行速度。 + 2. 单片机,主要操纵的是控制流,对数据处理能力不如DSP, + 3. FPGA field programmable gate array (综合了PAL,GAL,CPLD发展而来),可编程门阵列。可编程逻辑器件CPLD和FPGA。硬件描述语言:Verilog,VHDL。从数电实验课上得到的启发,这个FPGA就是一堆电路元件的阵列,可以通过某些设计软件,或者硬件描述语言,对这些阵列进行编程,使他们具有一定的逻辑性,然后烧录到FPGA当中,使他们具有一定的功能。这个也是嵌入式系统地一部分吧。他针对的不是程序,而是一种硬件的逻辑。 + 4. FPGA是对CPLD的电路规模,功能,性能等方面的强化之后的产物。 + +## > 数制与编码 + +**** + +* **机器码的理解** + 1. 原码,正数不变,负数在正数的最后一个值得基础上加负数的绝对值,中间没有零做间隔。特点:正数变大,原码变大;负数变小,原码变大(单调性不统一) + 2. 反码,正数不变,负数绝对值按位取反,相当于在机器码最大的情况下减去负数的绝对值,即加上负数。特点:正数变大,反码变大,负数变大,反码变大,但是有两个零,0和0的按位取反都是零。 + 3. 不骂,正数不变,负数是反码加一。特点:正数变大,补码变大,负数变大,补码变大,单调性相同,只有一个零。最小值为最大正数的按位取反,也是最大正数的补码加一后形成的补码。 +* **信息编码** + 1. 8421BCD编码,ascii码 + + +## >单片机的其他知识 + +----- + +* **51单片机的系列** + 1. 8031无内部存储器、8051ROM不可擦除、8751EPROM紫外线擦除、8951EEPROM电擦除 + 2. ATM公司,flash闪存集成到单片机内部。 + 3. 飞利浦公司,添加了can总线 + 4. 32/52加强系列,增加了可擦除存储器,增加了数据存储器的大小,怎加了数模转化器。 + +* **微控制器(单片机)的改进** + 1. 增加cpu内核数 + 2. 采用多级流水线结构,取指令、译码、执行,三级流水线结构,可以在任何时候都有cpu执行代码。 +* **对并行接口和串行接口的理解** + 1. 并行接口再多跟数据献上同时传送信息,串行接口是在一根数据线以一位数据为单位进行数据传送。并行适用于近距离告诉的场合。 + 2. 并口存在的问题:干扰问题,并口多条数据线之间会产生耦合电容,增大传输速率会导致错误,如果加强屏蔽,会消耗更多的金属,截面面积更大。同步问题,八条线的延迟不同,如果单线传输速率变高的话,可能会出现数据撞车(不同步的现象)并口单线100Mb/s时不能再增加,二串行传输,可以达到1Gb/s +* **io口的改进** + 1. 增加io的驱动能力 + 2. 增强逻辑控制能力,一秒钟亮,一秒钟灭,通过一个管脚即可实现控制能力,控制一个输出位,然后一秒钟翻转一次。 + 3. 增加特殊的串行接口。 + 4. 外围电路内装化 + + +> ADC analog Digital Converter 数模转换器 +> PWM pulse width modulation 脉冲宽度调制 +> WDT watch dog timer 程序监控定时器,看门狗电路 +> \ No newline at end of file diff --git a/单片机/汇编指令.md b/单片机/汇编指令.md new file mode 100644 index 00000000..bca30ef7 --- /dev/null +++ b/单片机/汇编指令.md @@ -0,0 +1,158 @@ +#汇编语言学习(真的做梦都没想到,居然在看汇编语言) + +## >数据传送指令 + +----- + +* **累加器 目的操作数** + MOV A,#data/direct/Rn/@Rn ; +* **寄存器 目的操作书** + MOV Rn,direct/Rn/#data; +* **直接地址 目的操作数** + MOV direct,#data/direct2/Rn/@Ri; +* **简介寻址 目的操作数** + MOV @Ri,#data/direct/Rn; +* **十六位数 传递** + MOV DPTR,#DATA16;只有DPTR能被16位赋值。 + MOV DPTR,#1234H;执行后DPH=12H,DPL=34H; +* **片外数据传送** + MOVX A,@Ri; +> 只有A累加器可以与外部RAM打交道 +> Ri是八位寄存器,只能存放低八位地址,通过p0口提供高八位 +> 使用前先将地址送入DPTR或者ri中 + + MOV DPTR,#0100H; + MOVX A,@DPTR; + MOV DPTR,#0200H; + MOVX @DPTR,A; + + +* **读取程序存储器指令** + MOVC A,@A+DPTR; + +* **堆栈操作** + PUSH direct; + POP direct; +* **数据交换指令** + XCH A Rn;交换值 + +## > 算数运算类指令 + +----- + +* **无进位加法指令** + ADD A,#data;A=A+#DATA + ADD A,direct; +* **带进位加法指令** + ADDC A,RN;A=A+RN+PSW.CY +> 对于PSW中CY和OV的介绍 +> 当进行二进制无符号运算时,只要使用PSW.CY位就能判定是否有溢出或者进位。 +> 当进行二进制补码运算时,PSW.CY表示进位,PSW.OV表示是否错误或者溢出。是最高两位的抑或(如果是负数且有溢出CY时,相加后不应该更大,而是更小。如果是整数相加后不应该更小,所以最高两位的抑或ov能够实现是否错误的判定) + +* **加一指令** + INC A; +* **十进制调整指令** + DA A; +> DA是按照BCD码调整相加后的二进制数。BCD码需要四位二进制来表示,但是这四位的进位,和二进制四位的进位不同(BCD满十进位),导致二进制码相加后并不是规范的BCD码,所以根据PSW.AC进行调整。 + +* **带借位的减法指令** + SUBB A,RN;A=A-RN-CY +* **减一指令** + DEC A;A=A-1 +* **乘法指令** + MUL AB;BA=A*B +> 8位无符号数相乘,两数相乘结果较大,高八位存放在B中,第八位存放在A中。 + +## >逻辑运算指令 + +----- + +* **逻辑或** + ORL A,RN; +* **逻辑与** + ANL A,RN; +* **逻辑异或** + XRL A,RN; +> 读改写指令对并行端口P0,P1,P2,P3操作是,读取并行端口锁存器中的数据,而非,管处的数据。 +> 非读改写操作,读取引脚处数据,而非锁存器数据。 + +* **清零** + CLR A; +* **循环移位** + RL A; rotate left + RR A; rotate right + RLC A; rotate left with cy + RRC A; rotate right with cy + +## >控制转移类指令 + +----- +>特点,不影响psw。实现了分支、循环、调用。是控制程序的相关指令,而非更改数据的指令。 + + +* **无条件转移指令** + AJMP addr11;短转移指令,11位地址,指令长度两个字节 + LJMP addr16;长转移指令,16位地址,指令长度三个字节 + SJMP rel; 相对转移指令,8位二进制补码地址 + JMP @A+DPTR;间接转移指令 +> 以上指令通过间接修改pc值实现。前两条直接给出类跳转的目标地址。短转移指令只修改PC的低八位地址,高五位不变,转移范围2kB;长转移指令,转移范围64KB;相对转移指令,当前指令PC+rel附近的128B地址。 +> 前三个指令可以直接给出行号。 +> 间接转移指令,可以根据A寄存器中不同的值进行跳转,散转指令,功能相当于C中的swich语句。 + +* **条件转移指令-A寄存器判断** + JZ rel;A==0则转移,否则顺序执行。 + JNZ rel;A!=0则转移,否则顺序执行。 + JZ 标号; 转移到标号出。 +> 当前PC值=PC+指令长度 +> 转移后的PC值=当前PC值+rel + +* **条件转移指令-比较转移** + CJNE A,#data,rel/标号;比较不等转移 +* **调用返回指令** + ACALL addr11;指令长度两个字节 + LCALL addr16;指令长度三个字节 + RET;子程序返回指令 + RETI;中断子程序返回指令 +> 调用子程序,原来的PC指针值压栈,返回时,出栈执行。 +> 嵌套太多是堆栈溢出,压栈出栈配对。 + +* **空操作指令** + NOP;指令执行时间是一个机器周期,用来做软件延时。 + + +## >位操作指令 + +------ + +> 由位处理器负责运算 +> 可以进行位操作的区域20H-2FH,特殊功能寄存器都可以。 +> CY自动用作位累加器 +> 字节地址、寄存器名字后面添加点操作运算符,对位进行操作psw.4; +> 直接使用位名称(一般特殊功能寄存器都有相应的位名称,只是不知道) +> 可以直接定义位地址 + +* **位传送指令** + MOV C,bit; bit to C + MOV bit,C; C->bit +> 实现了位累加器CY和其他地址之间的数据传递 +> C代表了PSW.CY或者PSW.C + + +* **位清零指令** + CLR C; + CLR bit; + SETB bit; + SETB C; 置位为1; +* **位逻辑运算指令** + ANL C,bit; + ANL C,/bit; + ORL C,bit; + CPL C; + +* **位条件转移指令** + JC rel; + JNC rel;根据CY判断是否转移 + JB bit,rel; + JNB bit,rel; 根据bit判定是否转移 + JBC bit,rel 根据bit判定是否转移,判定后该位清零。 + \ No newline at end of file