自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

XA403

积跬步以至千里

  • 博客(29)
  • 资源 (4)
  • 收藏
  • 关注

原创 OS内核(xv6)探究-分段&分页

分段与分页分段和分页是现代操作系统管理和使用内存的方式,一般需要操作系统(软件)配合CPU(硬件)一起来实现分段和分页的功能。我的理解,分段的主要目的是为了实现对内存的保护,即操作系统的保护模式;分页的主要目的是为了提高对内存的利用率,减少内存碎片。分段是程序员能在开发过程中够感知到的部分,例如我们常说的代码段(TEXT段),数据段(DATA段),堆和栈都是段的概念,还有CS,DS,SS等寄存器也是分段机制相关的寄存器。分页则是上层应用开发的程序员通常感知不到的部分,我们在开发上层应用时,面对的是逻辑

2022-04-06 18:00:26 3339 1

原创 OS内核(xv6)探究-系统调用

内核态和用户态计算机在加载操作系统之后,再继续执行任何指令的时候,都会处在某种特权级下(privilege)。例如在Linux下,可能会有ring0,ring1,ring2,ring3等几种状态,这些状态可以简单的分成用户态和内核态两种。我们写的上层应用的代码大多数情况运行在用户态,当我们的程序需要执行一些特殊的任务的时候,例如:访问文件,发起网络请求,向屏幕输出文字,fork一个子进程等等,我们的用户态程序是不具备这些权限的,只能把这些任务委托给操作系统(通过系统调用),因为只有运行在内核态的操作系统才

2022-04-06 17:59:42 4912 1

原创 iOS内存基础知识

操作系统的内存机制冯·诺依曼结构在冯·诺依曼结构中,存储器有着重要地位,它存放着程序的指令以及数据,在程序运行时,根据需要提供给 CPU 使用。可以想象,一个理想的存储器,应该是兼顾读写速度快、容量大、价格便宜等特点的,但是鱼和熊掌不可兼得,读写速度越快的存储器也更贵、容量更小。但冯·诺依曼结构存在一个难以克服的问题,被称为冯·诺依曼瓶颈 —— 在目前的科技水平之下,CPU 与存储器之间的读写速率远远小于 CPU 的工作效率。简单来说就是 CPU 太快了,存储器读写速度不够快,造成了 CPU 性能的浪

2022-03-29 15:43:15 2963

原创 iOS-runtime的数据结构

对象 & 类对象的关系对象和类对象的整体关系图:注:新版runtime中新增了rwe来优化rw对象(objc_object)struct objc_object {private: isa_t isa;...... } 我们平时用的所有对象都是id类型的,在runtime中 id 就是 objc_object 结构体,而 objc_object 的内容是一个 isa_t 的八字节数据,这个 isa_t 是一个共用体。并包含了以下信息:关于 isa 操作的相

2022-03-29 15:42:49 207

原创 iOS-消息转发流程

realizeClassWithoutSwiftrealizeClassWithoutSwift是初始化类的核心方法,主要做了如下事情:读取data数据,设置ro、rw归调用realizeClassWithoutSwift完善类的继承链关系调用methodizeClass,完善类信息(方法、分类的方法、属性列表、协议列表)读取 data 数据,并设置 ro 、rw- ro 表示 read only,其在编译期的时候就已经确定了内存,包含了类的名称、方法列表、协议列表、属性列表和成员变量列表的

2022-03-29 15:41:39 141

原创 iOS-类&分类的加载

realizeClassWithoutSwiftrealizeClassWithoutSwift是初始化类的核心方法,主要做了如下事情:读取data数据,设置ro、rw归调用realizeClassWithoutSwift完善类的继承链关系调用methodizeClass,完善类信息(方法、分类的方法、属性列表、协议列表)读取 data 数据,并设置 ro 、rw- ro 表示 read only,其在编译期的时候就已经确定了内存,包含了类的名称、方法列表、协议列表、属性列表和成员变量列表的

2022-03-29 15:41:04 661

原创 iOS-objc_init

dyld & objc_init前面我们分析到dyld负责加载App主二进制所依赖的动态库,并对APP、动态库做了一些链接和初始化工作。然后针对有初始化方法的动态库,dyld会调用它们的初始化方法,这里就包括runtime的初始化方法objc_init。这个过程如下图:_objc_initdyld_init是runtime的初始化方法,主要做了以下事情:环境初始化read_image:对各个Image中Class相关数据的初始化和处理load_image:调用+load方法

2022-03-29 15:40:29 154

原创 iOS-dyld

dyld在 MacOS 和 iOS 上,可执行程序的启动依赖于 xnu 内核进程运作和动态链接加载器 dyld。dyld 全称 the dynamic link editor,即动态链接器,其本质是 Mach-O 文件,是专门用来加载动态库的库。在 xnu 内核为程序启动做好准备后,执行由内核态切换到用户态,由 dyld 完成后面的加载工作:dyld 会将 App 依赖的动态库加载到内存并做一些初始化的工作。dyld源码下载地址_dyld_start之前我们都知道我们在APP中通过打断点最早能追溯

2022-03-29 15:39:56 1312

原创 Mach-O结构分析

可执行文件我们运行一个程序(进程)是把一些特殊文件在内存中加载并运行得到的结果。那么这类文件的格式必须是系统内核可以理解的,系统内核才能正确解析。这类文件被称为可执行的文件。不同操作系统的可执行文件格式不同:在现代通用计算机系统中,虽然不同平台的可执行文件的格式不完全一样,但是原理大体相同,基本都是基于段结构的,可执行文件的结构基本可以分为:header段:用于让操作系统识别可执行文件TEXT段:存放编译后的函数的二进制代码,TEXT段的内容被标记为只读的,可执行的。如果试图修改TEXT段的内

2022-03-29 15:39:16 1832

原创 对数据结构和算法的看法

对数据结构和算法的看法Eric S·Raymond 在《大教堂和市集》说道:聪明的数据结构和笨拙的代码要比聪明的代码搭配笨拙的数据结构工作得更好。对这个描述深以为然。以前我对数据结构和算法的作用还没有什么深切的感受,我想主要原因是一直在写上层应用,都是逻辑很简单的简单代码,复杂的底层实现都被大牛们用API给屏蔽掉了。但是当我开始阅读一些计算机底层源码的时候(例如操作系统,OC的runtime), 我才开始真正体会到数据结构和算法的巨大作用(尤其是当面对复杂问题的时候)。**采用好的数据结构是

2022-03-29 15:22:43 586

原创 Node.js学习笔记

node.js的优缺点优势:高并发能力:事件驱动,非阻塞I/O模式高性能:基于Chrome V8 JavaScript引擎统一的技术栈:使用 js 一门语言就可以开发web的前后端缺点:难以支持CPU密集型的任务代码自由度高,规范性差node.js的原理Node.js 使用事件驱动, 非阻塞I/O 模型,非常适合运行数据密集型的应用。基于 Chrome V8,它是一个用 C++ 写的超快的解释器。Node.js 的运行是一个Loop,在每个Loop中负责分发和处理各

2022-03-29 15:21:52 1120

原创 探究OC Runtime

Runtime理解OC是基于C的,在C的基础上扩展出了面向对象的能力,支持其面向对象能力的核心就是OC的runtime机制。OC中我们编写的类,最终按照某种数据结构存储在可执行文件的__DATA段中,然后可执行文件被操作系统加载到进程空间,此时进程空间中就有了各个类和函数的信息。runtime是一个动态链接库,在程序执行过程中,我们通过runtime提供的各种能力,来访问、操作、读写各个类、方法、实例对象。总结来说:OC的面向对象能力 = 类和方法的数据结构(数据结构也由runtime定义)+ 算法(r

2022-03-29 15:20:47 165

原创 静态链接分析

注:本篇内容基本参考自:Mach-O 与静态链接。然后自己做一些上手实践和分析,用来加深对静态链接过程的理解。材料准备首先手写一个简单的C程序:a.c,b.c/* a.c */#include <stdio.h>extern int globalA;extern int globalB;void swap(int *a, int *b);void printResult();void printsomething();int main() { globalA =

2020-06-24 11:48:25 264

原创 x86_64汇编下的函数调用过程

材料准备首先手写一个简单的C程序:main.c#include <stdio.h>void empty();int add(int i, int j);void myPrint(int num);void testParams(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k);int main(){ // 测试空函数 empty(); // 测试传2个参数的函数

2020-06-21 09:28:56 2083

原创 计算机发展史

发展阶段【计算】 --> 【计算 + 存储】 --> 【可编程化计算 + 存储】 --> 【人工智能 + 存储】早期计算机简单的加减乘除算数运算工具,目的是利用工具辅助人工计算1、纯手动工具:结绳记事、算盘、计算尺算盘2、手动机械工具:1623年,德国科学家施卡德建造出世界已知的第一部机械式计算器,成为计算机世代之父,这部机械改良自时钟的齿轮技术,能进行六位数的加减,并经由钟声输出答案,因此又称为“算数钟”。1642年法国数学家帕斯卡为税务所苦的税务员父亲发明了滚轮式加

2020-06-21 09:28:17 449

原创 C语言拾遗

short, longshort int x;long int y;short 和 long 用于修饰整型,和 int 一起使用,但使用时 int 关键字可以省略。short, int, long 在不同的机器架构下占用的长度不同,但一般遵循以下限制:short长度小于等于int,int长度小于等于long,一般short长度至少需要16位,long长度至少需要32位。extern引用全局变量(外部变量)时需要先使用 extern 关键字来声明对变量的引用,格式:extern dataType

2020-06-21 09:27:37 243

原创 从0到1构建计算机(12/12)--收获和总结

完成Nand2Tetris这门课,我大概用了4个多月的时间;完成从0到1构建计算机系列博客,大概用了5个多月的时间(课程和博客时间上有交集)。期间也因为工作较忙的原因,挂起过若干次,很高兴最后还是坚持完成了。最后在这里再次做一些总结,算是对这段学习过程的一个暂时的收尾。之所以说是暂时的收尾,是因为我觉得课程中很多知识点自己理解得还不到位,很多精华的思想也没有完全get到。这门课程是一门基础性的课...

2020-03-25 17:39:29 526

原创 从0到1构建计算机(11/12)--在Hack上运行小游戏

经过了前面10章漫长的旅程,我们终于要达成我们的目标了:在一个完全由自己实现的计算机平台上运行一个小游戏。这个小游戏要经过编写、编译、转换虚拟机字节码、汇编、生成机器代码等步骤,最终运行在自己搭建的虚拟计算机上。在游戏的运行过程中,每一条指令都是我们亲手编写,每一个细节我们都了如指掌,是我们完完全全地创造了它(虽然需要基于一个硬件虚拟机),这确实是一件非常有意思的事情。骑手快跑我这里编写了一个...

2020-03-23 14:31:39 265

原创 从0到1构建计算机(10/12)--简单的操作系统

上一篇我们完成了Jack的编译器,这就意味着我们可以随心所欲地在Hack上编写Jack程序了。但是以Jack目前的能力,即使是想完成一些简单的操作也要编写非常复杂的代码,例如我们想要在屏幕上输出“Hello Workd!”,就必须在屏幕上特定位置绘制上几百个像素点。所以我们需要实现一个简单的操作系统来让事情变得更简单一些。操作系统就是用来衔接计算机的硬件系统和软件系统的,以使得计算机对程序员和用...

2020-03-21 14:12:40 608

原创 从0到1构建计算机(9/12)--实现编译器

本篇实现Jack的编译器,也是从0到1构建计算机系列最复杂的一篇。编译器的实现本身是非常复杂的,但得益于Jack超简洁的语法,我们回避掉了很多复杂的问题。总体上Jack编译器是一个完整的编译器,它包括词法分析,语法分析,语义分析,代码生成等重要主题。高级语言为什么能够被编译器理解和编译?因为高级语言是按照某种规则的语法(上下文无关语法)组织的,结构上层次化的语言。程序的每个类,每条语句都是符合某...

2020-02-29 23:33:27 646

原创 从0到1构建计算机(8/12)--高级语言:Jack

本篇我们将设计一门高级语言:Jack。Jack是一门基于面向的对象的语言,具备现代高级语言的基本特性和风格,但是语法相对简单,且不支持继承等高级属性(其实Jack非常寒酸,只是支持了“对象”的功能)。本篇的内容非常简单,主要是介绍Jack的语法。Hello, World众所周知,学习一门新语言的第一步,是写一个 Hello, World。class Main { function v...

2020-02-27 16:47:14 623 1

原创 从0到1构建计算机(7/12)--实现一个虚拟机

计算机工作的本质就是对内存中的数据进行操作,因此只需要具备两种能力即可:(1)对内存的读和写;(2)用对数据进行算数逻辑运算。此外,支持指令跳转能大大提高计算机的可编程能力。直观上看,Hack具备了以上三项能力,我们上一篇也举例了如何实现1+2+…+100。但Hack和我们常用的CPU具备几百条指令集的能力还相去甚远,例如支持四则运算,对栈的操作,指针寄存器的使用,支持函数调用,处理入参和回参等。...

2020-02-24 15:15:58 797

原创 从0到1构建计算机(6/12)--汇编语言与汇编器

前一篇我们完成了Hack平台的硬件部分,本篇开始我们进入到软件的部分。相比较而言,软件部分更加复杂,需要花更多时间来实现和调试。软件部分的第一层就是汇编语言和汇编器,本篇我们将定义Hack的汇编语言,并编写对应的汇编器汇编语言和汇编器汇编语言是机器语言的符号表示,相比于机器语言,汇编语言更接近于自然语言,便于我们阅读和记忆。汇编语言和机器语言在表述上的一致性是非常高的,绝大多数情况下两种指令是...

2020-02-24 15:13:15 892

原创 从0到1构建计算机(5/12)--实现hack:计算机架构、内存、CPU和指令集

经过前两篇我们已经实现了所有的组合逻辑芯片和时序芯片,具备了实现hack计算机的基础,本篇是项目硬件部分的最后一篇,我们将在本篇定义hack能够执行的操作,即hack的指令集;实现hack的内存、CPU,然后将它们组合起来形成完整的计算机硬件架构。计算机架构hack是基于经典的冯·诺伊曼体系架构,它的关键组成部分是将中央处理单元和存储器,通过存储器中存储的程序指令控制中央处理器的执行,即存储程...

2020-02-24 15:12:25 3136

原创 从0到1构建计算机(4/12)--时序逻辑芯片:时序门、寄存器、RAM、计数器

上一篇我们实现了一系列组合逻辑芯片和CPU的运算大脑:ALU,但是组合逻辑芯片是一个实时系统,只要输入值改变了输出值也马上跟着改变,上一秒辛苦计算出来的值,下一秒就消失不见了,因此我们需要一个具备"记忆功能"的原件,用于存储数据。这就是我们本篇要介绍的:时序逻辑芯片。反馈电路、时钟系统、D触发器组合逻辑芯片之所以无法记住上一次计算的值,是因为电流信息的流向是单向的,它总是向前流动,导致我们无法...

2020-02-24 15:12:04 2165 2

原创 从0到1构建计算机(3/12)--组合逻辑芯片:逻辑门、加法器、ALU

上篇说到:通过使用Nand门,我们可以实现任何逻辑门,进而实现可以一个CPU。后面我们就会搭建一个麻雀虽小但五脏俱全的计算机平台:hack。本篇我们开始第一步,实现搭建hack所需的一组芯片:组合逻辑芯片组合逻辑芯片一个最基本的CPU主要由两类芯片组成:组合逻辑芯片(Combinational Chips):与、或、非门,加法器,ALU芯片等。这些芯片主要负责逻辑计算时序芯片(Seque...

2020-02-24 15:11:19 2769 1

原创 从0到1构建计算机(2/12)--与非门实现CPU的数理基础

CPU和布尔函数CPU本质上是一个函数计算器:信号通过输入管脚输入,对应着函数的入参CPU的内部电路是函数的黑盒实现信号通过输出管脚输出,对应着函数的出参大家有没有思考过现代计算机为什么是基于二进制的?????事实上,在计算机的发展历程中确实出现过其他进制的计算机,例如10进制,3进制(现在计算机也是一步步演化过来了,其某些核心设计思想甚至来源于织布机,有兴趣的同学可以翻翻计算机发展史,...

2020-02-24 15:10:47 1745

原创 从0到1构建计算机(1/12)--从与非门到俄罗斯方块

Mark!!! 开始学习课程:From Nand To Tetris本课程将从0到1地构建一个计算机,自底向上地一步步实现各种基本逻辑门、ALU、寄存器、RAM、CPU;定义机器语言、汇编语言,实现汇编器;定义高级语言,实现编译器;实现一套最简单的操作系统;最后编写一个小游戏并把它运行在这个完全由自己构建的计算机之上。现代计算机是非常复杂的,复杂性之一就在于计算机一层层的封装架构(同时工业级...

2020-02-24 15:10:14 1100

原创 浮点数表示

浮点数的概念是相对于定点数来说的。 定点数:小数点的位置是固定的。(小数点的左边表示整数部分,小数点的右边表示小数部分) 浮点数:小数点的位置是浮动的。假设目前只有8bit可供表示一个数,把第一位用于符号位,剩下7位用于数值位1.定点数表示: 假定将小数点放在第五个bit,那么前三位则将用于表示整数部分,后四位将用于表示小数部分 10000.000 == +1.0 ;00000.000 ==

2016-07-11 20:39:28 1505

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除