I recommend reading the Petzold book "Code". It explains these things as best as possible without the physics/electronics knowledge.
Each bit in the memory, at a functional level, HOLDs either a zero or a one (lets not get into the exceptions, not relevant to the discussion), you cannot delete memory you can set it to zeros or ones or a combination. The arbitrary definition of deleted or erased is just that, a definition, the software that erases memory is simply telling the memory to HOLD the value for erased.
There are two basic types of ram, static and dynamic. And are as their names imply, so long as you dont remove power the static ram will hold its value until changed. Dynamic memory is more like a rechargeable battery and there is a lot of logic that you dont see with assembler or microcode or any software (usually) that keeps the charged batteries charged and empty ones empty. Think about a bunch of water glasses, each one is a bit. Static memory the glasses hold the water until emptied, no evaporation, nothing. Glasses with water lets say are ones and ones without are zeros (an arbitrary definition). When your software wants to write a byte there is a lot of logic that interprets that instruction and commands the memory to write, in this case there is a little helper that fills up or empties the glasses when commanded or reads the values in the glasses when commanded. In the case of dynamic memory, the glasses have little holes in the bottom and are constantly but slowly letting the water drain out. So glasses that are holding a one have to be filled back up, so the helper logic not only responds to the read and write commands but also walks down the row of glasses periodically and fills back up the ones. Why would you bother with unreliable memory like that? It takes twice (four times?) as many transistors for an sram than a dram. Twice the heat/power, twice the size, twice the price, with the added logic it is still cheaper all the way around to use dram for bulk memory. The bits in your processor that are used say for the registers and other things are sram based, static. Bulk memory, the gigabytes of system memory, are usually dram, dynamic.
The bulk of the work done in the processor/computer is done by electronics that the instruction set or microcode in the rare case of microcoding (x86 families are/were microcoded but when you look at all processor types, microcontrollers that drive most of the everyday items you touch they are generally not microcoded, so most processors are not microcoded). In the same way that you need some worker to help you turn C into assembler, and assembler into machine code, there is logic to turn that machine code into commands to the various parts of the chip and peripherals outside the chip. download either the llvm or gcc source code to get an idea of the percentages of your program being compiled is compared to the amount of software it takes to do that compiling. You will get an idea of how many transistors are needed to turn your 8 or 16 or 32 bit instruction into some sort of command to some hardware.
Again I recommend the Petzold book, he does an excellent job of teaching how computers work.
I also recommend writing an emulator. You have done assembler, so you understand the processor at that level, in the same assembler reference for the processor the machine code is usually defined as well, so you can write a program that reads the bits and bytes of the machine code and actually performs the function. An instruction mov r0,#11 you would have some variable in your emulator program for register 0 and when you see that instruction you put the value 11 in that variable and continue on. I would avoid x86, go with something simpler pic 12, msp430, 6502, hc11, or even the thumb instruction set I used. My code isnt necessarily pretty in anyway, closer to brute force (and still buggy no doubt). If everyone reading this were to take the same instruction set definition and write an emulator you would probably have as many different implementations as there are people writing emulators. Likewise for hardware, what you get depends on the team or individual implementing the design. So not only is there a lot of logic involved in parsing through and executing the machine code, that logic can and does vary from implementation to implementation. One x86 to the next might be similar to refactoring software. Or for various reasons the team may choose a do-over and start from scratch with a different implementation. Realistically it is somewhere in the middle chunks of old logic reused tied to new logic.
Microcoding is like a hybrid car. Microcode is just another instruction set, machine code, and requires lots of logic to implement/execute. What it buys you in large processors is that the microcode can be modified in the field. Not unlike a compiler in that your C program may be fine but the compiler+computer as a whole may be buggy, by putting a fix in the compiler, which is soft, you dont have to replace the computer, the hardware. If a bug can be fixed in microcode then they will patch it in such a way that the BIOS on boot will reprogram the microcode in the chip and now your programs will run fine. No transistors were created or destroyed nor wires added, just the programmable parts changed. Microcode is essentially an emulator, but an emulator that is a very very good fit for the instruction set. Google transmeta and the work that was going on there when Linus was working there. the microcode was a little more visible on that processor.
I think the best way to answer your question, barring how do transistors work, is to say either look at the amount of software/source in a compiler that takes a relatively simple programming language and converts it to assembler. Or look at an emulator like qemu and how much software it takes to implement a virtual machine capable of running your program. The amount of hardware in the chips and on the motherboard is on par with this, not counting the transistors in the memories, millions to many millions of transistors are needed to implement what is usually few hundred different instructions or less. If you write a pic12 emulator and get a feel for the task then ponder what a 6502 would take, then a z80, then a 486, then think about what a quad core intel 64 bit might involve. The number of transistors for a processor/chip is often advertised/bragged about so you can also get a feel from that as to how much is there that you cannot see from assembler.
It may help if you start with an understanding of electronics, and work up from there (rather than from complex code down).
Let's simplify this for a moment. Imagine an electric circuit with a power source, switch and a light bulb. If you complete the circuit by closing the switch, the bulb comes on. You can think of the state of the circuit as a 1 or a 0 depending on whether it is completed (closed) or not (open).
Greatly simplified, if you replace the switch with a transistor, you can now control the state of the bulb with an electric signal from a separate circuit. The transistor accepts a 1 or a 0 and will complete or open the first circuit. If you group these kinds of simple circuits together, you can begin to create gates and start to perform logic functions.
In essence, the power coming in the back of your computer is being broken into billions of tiny pieces by the components of the computer. The behavior and activity of such is directed by the designs and plans of the engineers who came up with the microprocessors and circuits, but ultimately it is all orchestrated by you, the programmer (or user).
在现代可编程逻辑器件中实现 CPU 是可能的。如果您从简单的电路开始,现在您可以设计并实现自己的 CPU 来享受乐趣。
Heh, good question! Kind of involved for SO though!
Actually, main memory consists of arrays of capacitors, not transistors, although cache memories may be implemented with transistor-based SRAM.
At the low level, the CPU implements one or more state machines that process the ISA, or the Instruction Set Architecture.
Look up the following circuits:
Flip-flop
Decoder
ALU
Logic gates
A series of FFs can hold the current instruction. A decoder can select a memory or register to modify, and the state machine can then generate signals (using the gates) that change the state of a FF at some address.
Now, modern memories use a decoder to select an entire line of capacitors, and then another decoder is used when reading to select one bit out of them, and the write happens by using a state machine to change one of those bits, then the entire line is written back.
It's possible to implement a CPU in a modern programmable logic device. If you start with simple circuits you can design and implement your own CPU for fun these days.
That's one big topic you are asking about :-) The topic is generally called "Computer Organization" or "Microarchitecture". You can follow this Wikipedia link to get started if you want to learn.
此外,在桌面上或 IDE 之外的任何其他地方键入“print(var)”不会产生相同的结果,因为 IDE 背后的软件会激活一组特定的晶体管或门,它们会以适当的方式做出响应。
我认为这就是在基础层面上发生的事情,其余的都是层层构建的。
I don't have any knowledge beyond a very basic level about either electronics or computer science but I have a simple theory that could answer your question and most probably the actual processes involved might be very complex manifestations of my answer.
You could imagine the logic gates getting their electric signals from the keystrokes or mouse strokes you make. A series or pattern of keys you may press may trigger particular voltage or current signals in these logic gates.
Now what value of currents or voltages will be produced in which all logic gates when you press a particular pattern of keys, is determined by the very design of these gates and circuits.
For eg. If you have a programming language in which the "print(var)" command prints "var", the sequence of keys "p-r-i-n-t-" would trigger a particular set of signals in a particular set of logic gates that would result in displaying "var" on your screen.
Again, what all gates are activated by your keystrokes depends on their design.
Also, typing "print(var)" on your desktop or anywhere else apart from the IDE will not yield same results because the software behind that IDE activates a particular set of transistors or gates which would respond in an appropriate way.
This is what I think happens at the Fundamental level, and the rest is all built layer upon layer.
发布评论
评论(5)
我推荐阅读 Petzold 的书《Code》。它在没有物理/电子知识的情况下尽可能最好地解释了这些事情。
在功能级别上,内存中的每一位都保持零或一(让我们不要进入例外,与讨论无关),您不能删除内存,您可以将其设置为零或一或组合。删除或擦除的任意定义只是一个定义,擦除内存的软件只是告诉内存保持要擦除的值。
内存有两种基本类型:静态和动态。正如它们的名字所暗示的那样,只要您不断开电源,静态内存就会保持其值直到发生变化。动态存储器更像是可充电电池,有很多逻辑是您在汇编器或微代码或任何软件(通常)中看不到的,这些逻辑可以使充电电池保持充电状态,使空电池保持空状态。想想一堆水杯,每一个都是一个比特。静态记忆眼镜可以保持水直到空为止,不会蒸发,什么也没有。装有水的玻璃杯可以说是 1,没有水的玻璃杯是 0(任意定义)。当您的软件想要写入一个字节时,有很多逻辑来解释该指令并命令内存写入,在这种情况下,有一个小助手可以在收到命令时填充或清空眼镜,或者在命令时读取眼镜中的值。吩咐道。在动态记忆的情况下,眼镜底部有小孔,并且不断但缓慢地让水排出。因此,必须将持有玻璃杯的玻璃杯重新装满,因此辅助逻辑不仅响应读取和写入命令,而且还定期沿着一排玻璃杯走下去并重新装满玻璃杯。你为什么要为这样不可靠的记忆而烦恼呢? sram 所需的晶体管数量是 dram 的两倍(四倍?)。两倍的热量/功率、两倍的尺寸、两倍的价格,加上增加的逻辑,使用 DRAM 来存储大容量内存仍然更便宜。处理器中用于寄存器和其他内容的位是基于 sram 的、静态的。大容量内存(千兆字节的系统内存)通常是动态的。
处理器/计算机中完成的大部分工作是由电子设备完成的,在微编码的罕见情况下,指令集或微代码(x86 系列是微编码的,但是当您查看所有处理器类型时,驱动大多数日常工作的微控制器您触摸的物品通常没有微编码,因此大多数处理器都没有微编码)。就像你需要一些工人来帮助你将 C 语言转换为汇编程序,将汇编程序转换为机器代码一样,也有逻辑将机器代码转换为对芯片的各个部分和芯片外部外设的命令。下载 llvm 或 gcc 源代码,以了解正在编译的程序的百分比与进行编译所需的软件量的比较。您将了解需要多少个晶体管才能将 8 位、16 位或 32 位指令转换为某种硬件的某种命令。
我再次推荐 Petzold 的书,他在教授计算机如何工作方面做得非常出色。
我还建议编写一个模拟器。您已经完成了汇编程序,因此您了解了该级别的处理器,在处理器的同一汇编器参考中通常也定义了机器代码,因此您可以编写一个程序来读取机器代码的位和字节并实际执行的功能。指令 mov r0,#11 您的模拟器程序中会有一些寄存器 0 的变量,当您看到该指令时,您将值 11 放入该变量中并继续。我会避免使用 x86,而选择更简单的 pic 12、msp430、6502、hc11,甚至是我使用的拇指指令集。无论如何,我的代码不一定很漂亮,更接近暴力(毫无疑问仍然有错误)。如果阅读本文的每个人都采用相同的指令集定义并编写模拟器,那么您可能会拥有与编写模拟器的人一样多的不同实现。同样,对于硬件来说,您得到的结果取决于实施设计的团队或个人。因此,解析和执行机器代码不仅涉及大量逻辑,而且该逻辑可以而且确实因实现而异。一个 x86 到另一个 x86 可能类似于重构软件。或者由于各种原因,团队可能会选择重新开始并从头开始采用不同的实现。实际上,它位于与新逻辑相关的重用旧逻辑块的中间位置。
微编码就像一辆混合动力汽车。微代码只是另一种指令集、机器代码,需要大量逻辑来实现/执行。它在大型处理器中为您带来的好处是可以在现场修改微代码。与编译器不同,你的 C 程序可能没问题,但编译器+计算机作为一个整体可能有错误,通过在编译器中进行修复,这是软的,你不必更换计算机和硬件。如果微代码中的错误可以被修复,那么他们会以这样的方式修补它,即启动时的 BIOS 将重新编程芯片中的微代码,现在您的程序将正常运行。没有创建或破坏晶体管,也没有添加电线,只是改变了可编程部件。微代码本质上是一个模拟器,而且是一个非常非常适合指令集的模拟器。谷歌 Transmeta 以及 Linus 在那里工作时正在进行的工作。微代码在该处理器上更加明显。
我认为回答你的问题的最好方法是,除非晶体管如何工作,否则要么看看编译器中的软件/源代码的数量,该编译器采用相对简单的编程语言并将其转换为汇编语言。或者查看像 qemu 这样的模拟器,以及实现能够运行您的程序的虚拟机需要多少软件。芯片和主板上的硬件数量与此相当,不包括存储器中的晶体管,需要数百万到数百万个晶体管来实现通常几百个或更少的不同指令。如果您编写一个 pic12 仿真器并了解该任务,然后考虑 6502 需要什么,然后是 z80,然后是 486,然后考虑四核 intel 64 位可能涉及什么。处理器/芯片的晶体管数量经常被宣传/吹嘘,因此您也可以从中感受到有多少是您无法从汇编程序中看到的。
I recommend reading the Petzold book "Code". It explains these things as best as possible without the physics/electronics knowledge.
Each bit in the memory, at a functional level, HOLDs either a zero or a one (lets not get into the exceptions, not relevant to the discussion), you cannot delete memory you can set it to zeros or ones or a combination. The arbitrary definition of deleted or erased is just that, a definition, the software that erases memory is simply telling the memory to HOLD the value for erased.
There are two basic types of ram, static and dynamic. And are as their names imply, so long as you dont remove power the static ram will hold its value until changed. Dynamic memory is more like a rechargeable battery and there is a lot of logic that you dont see with assembler or microcode or any software (usually) that keeps the charged batteries charged and empty ones empty. Think about a bunch of water glasses, each one is a bit. Static memory the glasses hold the water until emptied, no evaporation, nothing. Glasses with water lets say are ones and ones without are zeros (an arbitrary definition). When your software wants to write a byte there is a lot of logic that interprets that instruction and commands the memory to write, in this case there is a little helper that fills up or empties the glasses when commanded or reads the values in the glasses when commanded. In the case of dynamic memory, the glasses have little holes in the bottom and are constantly but slowly letting the water drain out. So glasses that are holding a one have to be filled back up, so the helper logic not only responds to the read and write commands but also walks down the row of glasses periodically and fills back up the ones. Why would you bother with unreliable memory like that? It takes twice (four times?) as many transistors for an sram than a dram. Twice the heat/power, twice the size, twice the price, with the added logic it is still cheaper all the way around to use dram for bulk memory. The bits in your processor that are used say for the registers and other things are sram based, static. Bulk memory, the gigabytes of system memory, are usually dram, dynamic.
The bulk of the work done in the processor/computer is done by electronics that the instruction set or microcode in the rare case of microcoding (x86 families are/were microcoded but when you look at all processor types, microcontrollers that drive most of the everyday items you touch they are generally not microcoded, so most processors are not microcoded). In the same way that you need some worker to help you turn C into assembler, and assembler into machine code, there is logic to turn that machine code into commands to the various parts of the chip and peripherals outside the chip. download either the llvm or gcc source code to get an idea of the percentages of your program being compiled is compared to the amount of software it takes to do that compiling. You will get an idea of how many transistors are needed to turn your 8 or 16 or 32 bit instruction into some sort of command to some hardware.
Again I recommend the Petzold book, he does an excellent job of teaching how computers work.
I also recommend writing an emulator. You have done assembler, so you understand the processor at that level, in the same assembler reference for the processor the machine code is usually defined as well, so you can write a program that reads the bits and bytes of the machine code and actually performs the function. An instruction mov r0,#11 you would have some variable in your emulator program for register 0 and when you see that instruction you put the value 11 in that variable and continue on. I would avoid x86, go with something simpler pic 12, msp430, 6502, hc11, or even the thumb instruction set I used. My code isnt necessarily pretty in anyway, closer to brute force (and still buggy no doubt). If everyone reading this were to take the same instruction set definition and write an emulator you would probably have as many different implementations as there are people writing emulators. Likewise for hardware, what you get depends on the team or individual implementing the design. So not only is there a lot of logic involved in parsing through and executing the machine code, that logic can and does vary from implementation to implementation. One x86 to the next might be similar to refactoring software. Or for various reasons the team may choose a do-over and start from scratch with a different implementation. Realistically it is somewhere in the middle chunks of old logic reused tied to new logic.
Microcoding is like a hybrid car. Microcode is just another instruction set, machine code, and requires lots of logic to implement/execute. What it buys you in large processors is that the microcode can be modified in the field. Not unlike a compiler in that your C program may be fine but the compiler+computer as a whole may be buggy, by putting a fix in the compiler, which is soft, you dont have to replace the computer, the hardware. If a bug can be fixed in microcode then they will patch it in such a way that the BIOS on boot will reprogram the microcode in the chip and now your programs will run fine. No transistors were created or destroyed nor wires added, just the programmable parts changed. Microcode is essentially an emulator, but an emulator that is a very very good fit for the instruction set. Google transmeta and the work that was going on there when Linus was working there. the microcode was a little more visible on that processor.
I think the best way to answer your question, barring how do transistors work, is to say either look at the amount of software/source in a compiler that takes a relatively simple programming language and converts it to assembler. Or look at an emulator like qemu and how much software it takes to implement a virtual machine capable of running your program. The amount of hardware in the chips and on the motherboard is on par with this, not counting the transistors in the memories, millions to many millions of transistors are needed to implement what is usually few hundred different instructions or less. If you write a pic12 emulator and get a feel for the task then ponder what a 6502 would take, then a z80, then a 486, then think about what a quad core intel 64 bit might involve. The number of transistors for a processor/chip is often advertised/bragged about so you can also get a feel from that as to how much is there that you cannot see from assembler.
如果您从了解电子学开始,然后从那里开始工作(而不是从复杂的代码开始),这可能会有所帮助。
让我们暂时简化一下。想象一个带有电源、开关和灯泡的电路。如果通过关闭开关来完成电路,灯泡就会亮起。您可以将电路的状态视为 1 或 0,具体取决于电路是否完成(闭合)或未完成(打开)。
大大简化了,如果您用晶体管替换开关,您现在可以使用来自单独电路的电信号来控制灯泡的状态。晶体管接受 1 或 0,并将完成或断开第一个电路。如果将这些类型的简单电路组合在一起,您就可以开始创建门并开始执行逻辑功能。
内存基于类似的原理。
从本质上讲,计算机背面的电源被计算机的组件分解成数十亿个小块。其行为和活动是由微处理器和电路工程师的设计和计划指导的,但最终这一切都是由程序员(或用户)您精心策划的。
It may help if you start with an understanding of electronics, and work up from there (rather than from complex code down).
Let's simplify this for a moment. Imagine an electric circuit with a power source, switch and a light bulb. If you complete the circuit by closing the switch, the bulb comes on. You can think of the state of the circuit as a 1 or a 0 depending on whether it is completed (closed) or not (open).
Greatly simplified, if you replace the switch with a transistor, you can now control the state of the bulb with an electric signal from a separate circuit. The transistor accepts a 1 or a 0 and will complete or open the first circuit. If you group these kinds of simple circuits together, you can begin to create gates and start to perform logic functions.
Memory is based on similar principles.
In essence, the power coming in the back of your computer is being broken into billions of tiny pieces by the components of the computer. The behavior and activity of such is directed by the designs and plans of the engineers who came up with the microprocessors and circuits, but ultimately it is all orchestrated by you, the programmer (or user).
呵呵,好问题!不过有点参与其中!
实际上,主存储器由电容器阵列组成,而不是晶体管,尽管缓存存储器可以使用基于晶体管的SRAM来实现嗯>。
在底层,CPU 实现一个或多个处理 ISA 或指令集架构的状态机。
查找以下电路:
一系列 FF 可以保存当前指令。解码器可以选择要修改的存储器或寄存器,然后状态机可以生成改变某个地址处 FF 状态的信号(使用门)。
现在,现代存储器使用解码器来选择整个行电容器,然后在读取时使用另一个解码器从其中选择一位,并且通过使用状态机来改变一位来进行写入这些位,然后整行被写回。
在现代可编程逻辑器件中实现 CPU 是可能的。如果您从简单的电路开始,现在您可以设计并实现自己的 CPU 来享受乐趣。
Heh, good question! Kind of involved for SO though!
Actually, main memory consists of arrays of capacitors, not transistors, although cache memories may be implemented with transistor-based SRAM.
At the low level, the CPU implements one or more state machines that process the ISA, or the Instruction Set Architecture.
Look up the following circuits:
A series of FFs can hold the current instruction. A decoder can select a memory or register to modify, and the state machine can then generate signals (using the gates) that change the state of a FF at some address.
Now, modern memories use a decoder to select an entire line of capacitors, and then another decoder is used when reading to select one bit out of them, and the write happens by using a state machine to change one of those bits, then the entire line is written back.
It's possible to implement a CPU in a modern programmable logic device. If you start with simple circuits you can design and implement your own CPU for fun these days.
这是您要问的一个大主题:-) 该主题通常称为“计算机组织”或“微体系结构”。如果您想学习,可以按照此维基百科链接开始学习。
That's one big topic you are asking about :-) The topic is generally called "Computer Organization" or "Microarchitecture". You can follow this Wikipedia link to get started if you want to learn.
我对电子或计算机科学没有任何超出基本水平的知识,但我有一个简单的理论可以回答你的问题,而且很可能涉及的实际过程可能是我的答案的非常复杂的表现。
您可以想象逻辑门从您的击键或鼠标点击中获取电信号。
您按下的一系列或一系列按键可能会触发这些逻辑门中的特定电压或电流信号。
现在,当您按下特定模式的按键时,所有逻辑门将产生多少电流或电压值,由这些门和电路的设计决定。
例如。如果您有一种编程语言,其中“print(var)”命令打印“var”,
“print-”键序列将触发一组特定逻辑门中的一组特定信号,从而导致在屏幕上显示“var”。
同样,所有通过按键激活的门都取决于它们的设计。
此外,在桌面上或 IDE 之外的任何其他地方键入“print(var)”不会产生相同的结果,因为 IDE 背后的软件会激活一组特定的晶体管或门,它们会以适当的方式做出响应。
我认为这就是在基础层面上发生的事情,其余的都是层层构建的。
I don't have any knowledge beyond a very basic level about either electronics or computer science but I have a simple theory that could answer your question and most probably the actual processes involved might be very complex manifestations of my answer.
You could imagine the logic gates getting their electric signals from the keystrokes or mouse strokes you make.
A series or pattern of keys you may press may trigger particular voltage or current signals in these logic gates.
Now what value of currents or voltages will be produced in which all logic gates when you press a particular pattern of keys, is determined by the very design of these gates and circuits.
For eg. If you have a programming language in which the "print(var)" command prints "var",
the sequence of keys "p-r-i-n-t-" would trigger a particular set of signals in a particular set of logic gates that would result in displaying "var" on your screen.
Again, what all gates are activated by your keystrokes depends on their design.
Also, typing "print(var)" on your desktop or anywhere else apart from the IDE will not yield same results because the software behind that IDE activates a particular set of transistors or gates which would respond in an appropriate way.
This is what I think happens at the Fundamental level, and the rest is all built layer upon layer.