Programming code tells the computer to do something, but what makes the code actually mean anything to the computer?

1.20K views

Programming code tells the computer to do something, but what makes the code actually mean anything to the computer?

In: Engineering

36 Answers

Anonymous 0 Comments

The computer’s built so that coded patterns of 1’s and 0’s physically open / close different paths for electricity, to make it do different things. These coded patterns are called “machine code.”

The details of exactly what patterns are available, and what they mean, can be different for different models, brands, or kinds of computers. A CPU manufacturer typically publishes a manual with a complete specification of the patterns.

Working directly with the coded patterns the computer actually uses is inconvenient for human programmers. It would also be more efficient if the same program could be used on multiple models / brands / kinds of computers.

So people created programs (compilers, interpreters, shells, JIT’s) that allow the computer to “understand” English-like commands. This involves a “translation” process, sort of like translating from German to Italian. (Except the computer is, well, a computer, so it expects programmers to use perfect spelling and grammar, but will happily translate a buggy or completely nonsensical program as long as it’s grammatically correct.) It can be done in a few ways:

– A compiler works like translating a novel. A long program’s translated all at once, then the result’s saved in a file that the computer can run.
– An interpreter analyzes one “sentence” (line of code) at a time, runs that one, then moves on to the next. Sort of like translating a novel out loud as you read it.
– A shell lets you type a line of code, immediately runs it, then shows you the result. Sort of like when a businessman or government official goes to a foreign country, they might bring a human translator who translates each sentence immediately when they say it.

Anonymous 0 Comments

I’m sure someone can explain it better but:

At the most basic level, a computer is just a set of transistors. They are switches that can be “on” and “off”, which are translated to 1 and 0 respectively.

What programs do is they give define the context for what patterns of 1s and 0s mean in different scenarios. For example: 01000001 in binary is the decimal number 65. It can also be the uppercase letter “A”. It all depends on the context provided by the “header record” in the program which explains to the computer which way to interpret that specific pattern.

Programming languages offer a necessary shortcut that allows programmers to write many instructions with minimal effort. If all programmers had to write binary there wouldn’t be many of us around

Anonymous 0 Comments

A lot of people are giving you metaphors, or just repeatedly using the phrase ‘the computer interprets’ as though no matter how deep you drill down there is some sort of ineffable, intelligent gremlin that performs the magic of understanding.

So, here is what’s done. It may be a bit harder to follow than ELI5 ought to be, but it should actually answer the question in as simple a form as I can make it.

The most basic kind of process that would resemble a computer is an arithmetic processing unit. But we’ll focus on an even more basic kind of processor than that – something that just lets us store numbers in memory, and add them together. We’ll do this with 4-bit numbers.

What you need to make this device is an adder circuit, and a bunch of memory circuits. You can look up how to make these from logic gates – but all you need to understand is their basic input-output behavior.

For an 4-bit adder, you’ll have 8 input lines which you can make high or low (first 4 represent first number, last 4 represent second number) and 4 output lines, which will represent their sum (with any carry-over truncated.) This circuit acts more or less instantly – whatever you assert on the input lines, the output will automatically match.

For an 4-bit memory circuit, you have 5 input lines. You have 4 input lines which you assert as high or low to represent your number. And then you typically have a one more input line which, when asserted, will ‘store’ each of these bits, so that the 4 output lines match the current value of each of the 4 input lines, and will continue to output them until they get another ‘store’ command. Without that ‘store’ command the memory slot will just ignore the current inputs.

To make our super-dumb calculator, you’ll arrange these kinds of circuits together as shown in the following diagram, with 4-wire buses (4 wires in parallel that link outputs of circuits to inputs of others). The horizontal and vertical lines represent these buses. The sideways arrows -> represent ‘gates’. A gate is just an electrically-controlled switch. Not drawn are a bunch of single wires connected to these gates. If that wire goes ‘high’ the gate is opened. If the wire is ‘low’ the gate is closed. I’ll mention what the ARB is for in a minute. We’ll attach the input to our gates at the memory-inputs to the memory’s ‘store’ function as well, so when the gate is opened it’ll store the value.

>|||| -> memory 0—Adder……|||| <- ARB 1
|||| ——————Adder –>|||| <- ARB 2
||||……………………………….|||| <- ARB 3
||||……………………………….|||| <- ARB 4
|||| <- memory 1 <———–||||
|||| <- memory 2 <———–||||
|||| <- memory 3 <———–||||
|||| <- memory 4 <———–||||
|||| <- memory 5 <———–||||

So how would we use this to do operations?

Well, let’s say we want to add the numbers 3 and 5 together. For now let’s just say that the value of 3 (0011) is stored in memory slot 1 and the value of 5 (0101) is stored in memory slot 2. So how do we do that?

Well, they have a single set of 4 wires along the left-hand side attached to the outputs of all the memory slots. If we ‘open the gate’ at the memory 1 output, then the value of 3 (0011) will spread across the four wires. It will run up against the input to the adder, and the input to the memory 0 slot. We can’t also open up the gate at the memory 2 output, because that would put both the values of 3 and 5 (0011 and 0101) on the bus at the same time, so you’d probably get a random result, or the superposition of the two (0111 = 7). So we can’t just open both gates and let them flow into the adder. And two 4-wire buses would be inefficient, since we’d need two gates for each memory circuit, one to connect it to each of the two buses.

That’s why memory slot 0 is there. We open the gate from mem1, which will deliver its value (0011=3) to the adder and the input of memory 0. Then we open the gate on memory zero input (which is also tied to the ‘store’ line) so the value in mem1 gets delivered to and stored in mem0. Now the value that was in memory slot 1 is continually being input to the adder via the memory 0 output.

So, then we close the gate leading from memory 1 to the left bus, and we close the gate leading into memory 0 so it won’t get overwritten with a new value. Then we open the gate on the output of memory 2, so that the value there (0101=5) flows directly into the Adder’s second input. With this gate open connecting memory 2 to the adder, and memory 0 deliverying memory 1’s value to the adder, the output of the adder will be the sum of the values in memory 1 and memory 2 (1000 = 8). This value will be output constantly at the output of the adder.

If we open the gate on the output of the adder, and open the gate to the input of memory slot 3, then the sum will get stored in memory slot 3. Thus we will have added two values and stored the result.

Going back to the ARB thingy – we need a way to place our desired values into memory in the first place. How do we get the values of 3 and 5 into memory slots 1 and 2 to begin with? We have to put them there. So ARB_IN is actually just a source of high voltage connected to the 4-wire bus with 4 individual gates. We open or close those gates to place a total value on the bus, and then open the input of a single memory slot to store the value. So to store the value 3 in memory 1, we open the memory 1 input gate, and then open ARB_In gates 3 and 4 while leaving 1 and 2 closed (0011 = 3). We do a similar thing to place the value 5 (0101) in memory 2. Thus, we can input ARBitrary values into arbitrary memory by opening the right combination of gates. This is also why we need a gate on the adder output – so we can block off the result constantly flowing out of it if we want to put an arbitrary value on the memory input line instead.

So this really just breaks down into 4 steps. Leaving all other gates closed:
>1) Open gate mem1_in, ARB gate 3, and ARB gate 4
2) Open gate mem2_in, ARB gate 2, and ARB gate 4
3) Open gate mem1_out and mem0_in
4) Open gate mem2_out, adder_out, and mem3_in

This will:
>1) store the value 3 (0011) into memory slot 1
2) store the value 5 (0101) into memory slot 2
3) store the value in mem1 into mem0
4) deliver the value in mem2 to the adder, adding it with mem0 and storing it in mem3

This is our program. *This* is what we need to tell the computer to do, at the most basic, fundamental level. Build it so that we can make it do different, useful things by opening and closing gates, and then tell it what gates to open and close in what order to make something happen. So what does this *program* look like when written for the computer? Well, we have 16 total gates. We’ll label them 0-9 and the remaining six A-F.

>0) ARB 4
1) ARB 3
2) ARB 2
3) ARB 1

>4) mem0_in
5) mem1_in
6) mem2_in
7) mem3_in
8) mem4_in
9) mem5_in

>A) mem1_out
B) mem2_out
C) mem3_out
D) mem4_out
E) mem5_out

>F) adder_out

So our 4 instructions above become:
>1) open gates 5, 1, and 0
2) open gates 6, 2, and 0
3) open gates A and 4
4) open gates B, F, and 7

These gates are all blocking (no signal gets through) if they receive a low voltage (0) and are connecting if they receive a high voltage (1). So that’s exactly what our instruction looks like. Our instruction is formatted as 16 high/low signals delivered to the gates in the format of:

>FEDC BA98 7654 3210

(spaces added to make it easy to identify individual bits)

So our 4 instructions, finally, in fundamental ‘machine code’ are:
>1) 0000 0000 0010 0011
2) 0000 0000 0100 0101
3) 0000 0100 0001 0000
4) 1000 1000 1000 0000

That’s it. That’s the machine code. There’s no interpretation going on. There’s no Gremlin. These are the physical instructions that make the machine go. You could deliver these instructions, say, in the form of a punch-card. Have a cardboard card with lines of 16 perforated holes that can be punched out. Place it between a piece of metal with high voltage, and a line of 16 spring-loaded contacts each attached to a gate. Any holes that are punched out will let the contacts connect to the plate, delivering voltage to their individual gate. Perform each instruction by pushing the card through, to the next line so all 4 lines occur in-sequence (with all gates closed in between to prevent any instruction mixing).

All computers are just [much] more complicated combinations of this fundamental mechanism. No matter how many layers of abstraction there are, at some point the system just turns into ‘telling which gates to be open and closed for each step to occur”. And the computer doesn’t have to ‘interpret’ anything. At the fundamental level, the instruction *is* the set of signals that electro-mechanically open and close the gates.

If you read through all this, well done. Let me know if it was helpful, or if any part was unclear.

Anonymous 0 Comments

People explained how the language (Java, C, Python, Ruby, etc.) Become Machine languages that are 0s and 1s. To make this go even lower without getting deep it’s just electrical impulses in a specific order that the computer understands doing this trillions of times in a few seconds

Anonymous 0 Comments

There is a process called compiling that turns people code into machine code. Machine code is very basic commands stored in binary. The computer interprets the 0’s and 1’s of binary as high and low voltages which act as inputs to an electrical circuit that operates the device.

Source: am a computer engineering student and Minecraft redstone engineer

Anonymous 0 Comments

Machine doesn’t “understand” anything. It just ends up being a series of circuits, gates and switches that go on and off in whatever series we want. And we in turn create “meaningful” states to put the machine in. As short of an answer I can think of.

Anonymous 0 Comments

The basic building blocks are gates, where you can have AND gate and an OR gate. Both take 2 signals and give a result.

A signal is just a voltage, so ‘1’ is more than 2 volts, and ’0’ is less than 2 volts, and 1 signal is called a bit.

Out of these basic building blocks you can make an addition / subtraction/multiplication/division operations for 2 Sets of 64 bits that is.

but when do you use which operation? You build a block that takes 2 extra bits, and you basically can decide that 00 is for addition, 01 for subtraction, and so on, meaning the 4 blocks all have access to whatever is the storage of the 2 64 bits, but you select which operation you want with the 2 bits.

So now you have a list of operations that work on 2 sets of 64 bit numbers that you can reference.

Instead of hardcoding the bits, you can create a compiler that converts certain words into certain operations so instead of ‘00’ for addition, you can give it the word ‘ADD’ and then the 2 sets of bits you want to add.

When you have this basic compiler, you can then extend it to make more complex things like ’if’ and ‘for’ loops, and you can save many commands together as a single command (functions).

So what gives the program meaning? People made the design decisions by making the building blocks, and listing the available blocks, and then designing a compiler that can select and extend those building blocks.

Anonymous 0 Comments

There is a free course available called “From Nand to Tetris” and it teaches you how to build a Tetris game from scratch, and by scratch I mean Nand gates, which are (one of) the most elemental electrical circuits. It teaches you how to assemble these gates into building blocks of a cpu, and then machine code, assembly, a compiler and an operating system right up to a working Tetris game. It is fascinating and makes you really understand what is going on.

Anonymous 0 Comments

You can think of the computer as consisting of TWO parts. The Central Processing Unit and the Memory. Programmers put their code into the memory and you can look at it like a list that goes top to bottom. The CPU then gets fed that information and writes new stuff to that memory. How does that happen? With the pins! When you look at your CPU it has all these connections to the surface it gets placed on and now all you have to do is send some electricity to those pins. The CPU is constructed in such a way that if you send electricity to certain pins they will then redirect that electricity to other pins which you then can send back to the memory.

Anonymous 0 Comments

Computer’s processor (CPU) has a built in instruction set. It performs relatively simple things like “add two numbers together” or “reserve x amount of space in memory”. A programming language allows to input something closer to human language, though still quite cryptic to the uninitiated, and a compiler then takes this input and converts it into instruction sets, written in binary (0s and 1s) that the CPU can understand.

Programs then operate on data held in memory to make things happen.