一、机器语言和汇编语言

在开始之前,我们先回想一下之前了解到的CPU(戳这里查看详情)。CPU靠指令来做各种运算,每个CPU都有一些自己能够直接识别的指令,我们称之为CPU的"指令集",或者叫做机器语言(机器码)。

我们也提到过了,这些指令集其实都是一些0101的二进制组合,计算机会将它们转换为一系列高低电平的电信号,配合我们前面了解的继电器、门电路等完成对硬件的控制。而不同的CPU结构,即使是对同一功能的实现,其电平脉冲都是不一样的,所以我们说CPU的指令集对于同一类的CPU是“独有的”。而这些01组合非常难以识别,要以这种形式操作计算机,那难度那不是一般的大,比如将用0, 1数字编成的程序代码打在纸带或卡片上:1打孔,0不打孔,再将程序通过纸带机或卡片机输入计算机进行运算。早期的程序员们就是这么干的,简直6的飞起,但是他们觉得很累!而且对于不同结构的CPU还要使用不同01组合,想想都难过,所以,他们发明了“汇编语言”。

汇编语言其实可以认为是机器语言的另一种表现形式,它使用助记符和标号等来代替原来复杂的01组合,比如ROR、SHR等等。于是乎,程序员们就开始了用汇编语言编写程序。虽然汇编语言对于人类来说要简单的多了,但是计算机还是只认识0101这种格式啊,所以在引入汇编语言的同时,同时引入了一个“中间翻译人”:汇编编译器。汇编编译器的作用就是将用汇编语言编写的程序编译成计算机能认识的机器语言:也就是程序员们最开始用纸带、卡片编程的时候使用的语言。

由于这个汇编语言是机器语言的一种符号表示,而不同类型的CPU有不同的机器语言,所以汇编语言程序和CPU指令系统有很大的关系,这就导致了其在可移植性上有很大的局限性。一般计算机专业都会开设编译原理这种课程,它对于我们理解编程原理是很有帮助的,因为后面出现的高级语言都屏蔽了很多较底层的操作。比如将某个寄存器的内容送到另一个寄存器。

二、从机器语言到操作系统

上面说到的汇编语言,即使相对于机器语言好用的多,但是我们已经知道,它只是机器语言的另一种表现形式,其仍然要面向处理器编程,太过贴近于底层,编程和调试工程量仍然巨大,专业要求性也太高。所以,人们提出了一种更为接近自然语言的“算法语言”。算法语言则更加贴近人们的认知,极大的简化了编码调试工程,且它是独立于计算机的指令系统的,可移植性强。虽然这样说,但是我们也要明确,不论什么时候,程序运行最终都要依赖于CPU的指令集,这点是不变的。就如我们的汇编语言需要对应的汇编编译器一样,要保障算法语言的可移植性,也必须要求对应计算机上提供该语言的编译系统,能够将算法语言通过编译汇编,最终转换为对应CPU认识的机器语言。算法语言的提出是里程碑式的,我们使用的C、C++、VB等等都属于算法语言。

历史上出现的第一款算法语言是ALGO,之后剑桥大学在ALGO基础上设计出CPL语言,又将CPL改进为BCPL。BCPL是早期比较典型的面向过程的高级语言,它以一个主函数开始,可以将功能模块添加到各个函数中,函数已经支持递归、嵌套等等。但是BCPL在字符串处理、内存管理上都有不小的缺点,于是没过多久,美国贝尔实验室的Ken Thompson(图领奖得主之一)就将其进行了优化改进,取BCPL的首字母命名,称之为“B”语言。

同样是Ken Thompson这位大佬,因为他想玩游戏的缘故,就使用B语言开发出了第一款UNIX操作系统。之后Dennis M.Ritchie(C语言之父)因为同样的原因加入其中,而他主要负责改良B语言。没过多久,Ritchie就在B语言的基础上设计出了一门新的语言,他取BCPL的第二个字母命名,称其为:C语言。没错,就是我们熟悉的C,他也由此被称为“C语言之父”、“Unix之父”。之后一年不到,C语言的主体就完成了,然后他们就毫不犹豫地将Thompson之前使用B语言开发的UNIX“推翻”,使用C语言重写了一个新的UNIX。随着UNIX的发展,C语言自身也在不断地完善。直到今天,各种版本的UNIX内核和周边工具仍然使用C语言作为最主要的开发语言,其中还有不少继承Thompson和Ritchie之手的代码。(历史事件于网络收集)

操作系统本身其实也是应用程序,是使用编程语言开发出来的,而这些编程语言都是一步步从机器语言演变进化而来,其中有一个不可或缺的东西,就是我们不只一次提到的:编译器。而编译器是一个很大的概念,比如本地编译器、交叉编译器等,感兴趣的可以自行查阅相关资料。这里我们只需要知道,编译就是一个从源码(比如高级语言编写的程序)到目标代码(比如机器语言或汇编语言)的过程,一个程序(包括操作系统本身)要运行在一台计算机上,就必须要将其代码通过编译汇编等操作将其转化为对应计算机CPU能识别的指令,也就是机器语言。

笼统的说,Linux能在很多不同的机器上跑是因为其开源,人们可以“自主”、“自由”的提供对应多个不同CPU架构的编译器。为什么Windows XP只能运行在X86、X64架构的机器上?则是它又不开源,又没有提供支持其它CPU架构的编译器。感兴趣的可以去了解了解“WINTEL联盟”。

三、高级语言、编译器和操作系统

我们在在初学编程语言的时候都会了解到,一个源代码文件要经过编译器处理才能被执行,而它又和我们所使用的操作系统有什么关系呢?比如我们使用visual studio学习c或者c++,代码写完之后,要点击“编译”,然后再运行,计算机就开始执行我们的程序了。visual studio本身集成了编译器,我们点击“编译”的时候也就是在使用编译器。可是运行呢?(注:高级语言的运行方式一般分为编译型和解释型,编译型就是一次性编译成目标代码由机器运行,而解释型则先翻译成中间代码,再由解释器对中间代码进行解释运行,每执行一次都会进行翻译,因此相对于编译型效率较低,但跨平台性好。这个暂时不是我们讨论的重点,感兴趣的朋友可以先自行查阅资料)。

接下来需要先提到一个名词,叫做可执行文件。这个比较容易理解,我们平时使用windows,像exe就是一种可执行文件,双击可以运行。我们使用一个操作系统运行我们的程序,需要遵循一些约定,比如数据对齐、调用约定、编码等等,叫做:ABI(Application Binary Interface),也就是应用程序二进制接口。ABI掩盖了各种细节,它允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。UNIX的主要执行文件格式ELF,就是作为ABI开发的,而对于Windows,则是PE文件格式(当然,COFF、PE都在使用,.exe使用PE文件格式,.obj使用COFF文件格式)。但不论是ELF还是PE,它们都源于COFF文件 ,即通用对象文件格式(戳这里看百科解释),而对象文件格式也不只COFF这一种。

现在再来说我们的VC。使用VC的编译器编译后生成的目标文件(.obj),其实就是使用COFF文件格式存储的,运行该目标文件其实就依托于ABI。所以,对于不兼容ABI的系统,目标代码是无法直接运行的。比如,在windows下编译的目标代码,拿到Linux直接运行是行不通的,需要一些特殊手段才行。

注:本文内容为博主个人理解,很多地方可能不一定正确,如有错误,希望读者朋友不吝指出,谢谢!

Java并发编程(五):计算机基础-机器语言、高级语言和操作系统相关推荐

  1. Java并发编程-线程安全基础

    线程安全基础 1.线程安全问题 2.账户取款案例 3.同步代码块synchronized synchronized的理解 java中有三大变量的线程安全问题 在实例方法上使用synchronized ...

  2. 第九十三期:带你聊聊 Java 并发编程之线程基础

    百丈高楼平地起,要想学好多线程,首先还是的了解一下线程的基础,这边文章将带着大家来了解一下线程的基础知识. 作者:小九 01.简介 百丈高楼平地起,要想学好多线程,首先还是的了解一下线程的基础,这边文 ...

  3. Java并发编程笔记—摘抄—基础知识

    什么是线程安全 当多个线程访问某个类时,不管运行环境采用何种调度方式或者这些线程如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 竞态 ...

  4. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  5. java并发编程:lock_编程的第五个十年:J代表Java

    java并发编程:lock 一段非常个人的编程历史中的第五章第一部分 在自己的一类 尽管Microsoft并不认同Oracle对Java的所有雄心壮志,但我们同意它对于软件开发人员来说是非常有价值的工 ...

  6. Java并发编程实战基础概要

    文章目录 Java并发编程实战基础概要 开篇 多线程问题有啥难点呢? 为啥要学习并发编程? 并发问题的根源是什么? CPU切换线程执导致的原子性问题是如何发生的? 缓存导致的可见性问题是如何发生的? ...

  7. Java并发编程(五)JVM指令重排

    我是不是学了一门假的java...... 引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序:在特定情况下,指令重排将会给我们的程序带来不确定的结果.. ...

  8. Java并发编程 基础知识学习总结

    Java并发编程一直是Java程序员必须懂但又是很难懂的技术内容,这部分的内容我也是反复学习了好几遍才能理解.本篇博客梳理一下最近从<Java 并发编程的艺术>和他人的博客学习Java并发 ...

  9. java并发编程-进程和线程调度基础

      弄清楚计算机底层进程.线程调度等原理对我们理解java并发编程有很大的帮助. 文章目录 1.什么是进程 2.什么是线程 3.进程和线程的区别与联系 4.CPU内核数和线程数的关系 5.CPU时间片 ...

最新文章

  1. jsp mysql 图片路径,请教JSP中怎么向MySql中存入和取出图片
  2. VM 7 下ubuntu安装vmtools
  3. MySQL的SQL Profiler性能分析器
  4. 哪里可以找到python的免费教程-哪里有实用且免费的Python视频教程
  5. java mysql 多表查询_解析Mysql多表查询的实现
  6. C# 哈希表(Hashtable)用法笔记
  7. LeetCode 322. Coin Change
  8. C语言解释器的实现--语法解析(五)
  9. 自觉培养“舆商” 争做成功网商
  10. LeetCode 501. 二叉搜索树中的众数(中序遍历)
  11. Java中矩阵运算(math3的使用)
  12. java 栈的用法_让Java程序员再次生机勃勃,还是技术的力量
  13. mysql 服务意外停止1067错误解决办法小结
  14. linux下调整交换分区的大小
  15. druid Approximate Histograms
  16. Atitit poi读取大文件内存溢出的解决 目录 1. poi提供了两种读取excel的方式,一种是类似xml的Dom, 1 2. POI官网上提到XSSF有三种读写excel,POI地址 1 3
  17. SpringMVC的乱码问题解决
  18. Matlab趋势线公式引用,批量提取excel中图表趋势线的公式中的斜率 - 程序语言 - 小木虫 - 学术 科研 互动社区...
  19. QQ群下载解除限速小技巧【提高千倍不止】【无需会员】
  20. 【编译原理】自上而下语法分析(C/C++源码+实验报告)

热门文章

  1. 全国计算机等级陕西一级题库,全国计算机等级考试一级题库与答案
  2. 由异常处理引出的对沟通和学习的思考
  3. C#算法题目自己的解答 约德尔测试
  4. java relativelayout,在java代码中设置RelativeLayout
  5. 英飞凌 AURIX 系列单片机的HSM详解(2)——与HSM相关的UCB和寄存器
  6. ironpython使用方法_您如何使用IronPython?
  7. C++11中时间库chrono的使用
  8. 隧道人员定位系统的实施,使隧道施工人员安全得到保障--新导智能
  9. 蔡文胜创业周末演讲实录
  10. sendmail服务器配置linux,Sendmail具体配置