# Who converts binary/machine code to electrical signals and how?

I went through lots of blogs and posts but could not exactly figure out how the machine code is converted to electrical signals?

Any software program is compiled to machine code which is nothing but lots of 1s and 0s. 1 means high voltage e.g 5V and 0 means comparatively low voltage e.g. 0V or ground, what's the component which understands that okay I got 1(one) so I need to step up up the voltage to 5V and for 0(zero) I need to step down to lower voltage level and how it does that?

• Try to find a textbook on logic design. Commented Jun 7, 2015 at 16:10
• Sorry, this wasn't meant to be mean or anything -- you said you read about this matter in blogs and post, and I just thought you may find the answers if you target your reading for "logic design" posts. This was supposed to be a simple pointer. Sometimes just knowing the right buzzword is the key to getting the information. Commented Jun 8, 2015 at 19:36

In old computer you actually had a row of switches on the front panel that would allow entering 1s and 0s directly by hand in the registers of the machines. But this is no longer done.

You never have 1s and 0s, unless you ask the machine to print its internal information as a sequence of 1s and 0s. All information is already in the machine encoded as voltage, or magnetic orientation, or hole in a physical substrate, or some other physical form. Various devices can perform the translation between these form: magnetic heads, laser beams, electro-mechanical devices, electronic circuits,etc.

Some form are better adapted at memorizing or transmission by various means, while other (electrical signal notably) are better adapted at processing, usually by complex systems of logical gates (and, or, not, xor ...) and micro-memories (registers).

In general, binary/machine code is no longer entered by human beings, but produced by a program (usually a compiler) by the computer itself, or by another computer and then imported on some memory support or by network. However, human beings can ask to have it printed as 1s and 0s to check what the computer is using or producing. However this requires transforming the single bit 0 or 1 in the computer as a stream of bits to be interpreted by the printer as a request to print an actual drawing (on screen or paper) od the symbol representing a 0 or a 1.

It is hard to give more details without your being more specific regarding the source form and target form of the conversion. But it is most often from binary to binary, with a different physical representation.

• Thanks for great explanation! Very first computer was hard wired to perform predetermined calculations then punch cards came in punch cards were also kind of physical input to computer, you have to tell computer what to do. This evolution continued and people realise the need of where computer could perform some stored instructions automatically without human intervention, eventually EDSAC became the first computer which could execute stored instructions. Could you explain about how stored instructions are executed by a computer? Commented Jun 8, 2015 at 2:36
• @devgr Well, I am not a specialist, and CPU design is a whole field by itself. Furthermore there is a variety of techniques, depending on whether things are done serially or in parallel, on whether it is synchronous or asynchronous, and others I would not know. An instruction is a sequence of bits with several fields corresponding to op-code or address/value or flag. It is loaded in a register (row of circuit locations that have a "stabilized" voltage corresponding to 0 or 1. The points for each field are connected to circuits supposed to act according to the field content at a clock signal. Commented Jun 8, 2015 at 10:38
• If the instruction has an "add register" op-code, with two registers addresses, then the circuitry will be activated so as to direct the content of the registers towards the adder entry point, and activate the adder circuitry, the result being stored in a standard result register (for example). I am making this up to give you an example. It varies according to designs, and my example is probably very naive Commented Jun 8, 2015 at 10:43

The question is asking there must be something between the machine code and the electric signal in the computer. For example, a program written in C++ is compiled into machine code first, then it is converted into electrical signal so that the computer can really "execute" the program. As the computer does not understand the machine code, what is the component really change machine code to electronic signal?

Some answers mentioned the input process from keyboard, but that does not really answer the question. I think if anybody who can explain step by step the execution process of an .exe file on a Windows computer will be able to provide more valuable details.

• Interesting comment, but it is good to indicate when your answer is just a comment and not a full answer. Maybe you an include a note at the top of this answer that says "Not a full answer"? Commented Jun 18, 2020 at 2:36
• Yeah, the answers aren't really answering the question. I've been looking for an answer for a while too but people just keep reiterating what binary code is and what it represents. Commented May 7, 2021 at 6:51

The CPU

What is important to understand is that the CPU comes with a predefined instruction set that it can handle. For example, x86-64 CPUs have a defined set of instructions that they can operate on.

The CPU has a data bus and an address bus. The buses are only pins under the processor and they are connected to metallic lines that are directed towards the pins of the DIMM (Dual Inline Memory Module) or RAM which contains DRAM chips.

The CPU pins (under the CPU) are detailed here https://www.intel.com.br/content/dam/doc/datasheet/core-i5-600-i3-500-pentium-6000-datasheet-vol-1.pdf in the last chapter. Below is an image which shows the upper-left quadrant.

In the upper-left quadrant, you have some SA_DQ pins which are the DDR3 data pins. These pins will be connected by the data bus to the data pins of the RAM memory module's pins. You have something similar for the address pins.

On the address pins is placed an address (0 or 1 on each line). This address will be decoded by the DIMM which will open a path to the DRAM memory cells containing the content at that address. A DRAM memory cell looks like below.

The DRAM cell consists of one transistor controlling the flow of charge and one capacitor containing the charge. Each DRAM cell is one bit of information. You could think of it as if the charge would flow from the capacitor to the CPU register and then the CPU would do operations on the register and then charge back some other capacitors. In reality, it is a bit more complex but you get the point.

For example, you could have the Intel syntax assembly instruction

mov rax, [0x1234]


To understand better how the computer works, you should look at booting because a lot happens there.

Booting

CPUs have reset pins. The reset pins are used by the BIOS to initialize the CPU when you start the computer. The CPU is manufactured to put a certain address in its RIP register when you reset it (the reset vector). The RIP register is the instruction pointer. It contains the address of the next instruction to be fetched, decoded and executed. The CPU will thus execute its first instruction at the reset vector. It is the job of the motherboard to make sure that, at this address, is hardwired the BIOS's first instruction. The BIOS will thus be executed as the first program (software) of the computer. It will start sending instructions to the CPU and tell it to write some stuff in RAM like the ACPI tables.

The ACPI tables are located in predefined conventional locations in RAM that the OS will look for. The OS will then interpret these tables to determine what is plugged in the computer. Like what PCI slots there is, what USB controller and what IOAPIC.

Today most computers boot with UEFI. The BIOS will initialize everything and then jmp to the first instruction of the UEFI program. The UEFI program will set up long mode and paging then execute a UEFI app in a predefined directory on a FAT32 partition. The hardware/firmware manufacturer provides the UEFI program while the OS/software manufacturer provides the UEFI app that the UEFI program will launch. The hard-disk needs to be partitioned with GPT so that the UEFI program embedded in the motherboard can interpret the partitions and jmp to a UEFI app in a certain directory. The OS manufacturers often provide an ISO file which is basically an image of the hard-disk byte by byte. When you burn an ISO to disk, you simply use software to write that ISO byte by byte to the disk as an exact copy.

USB

I think that to understand computers better, you should look at how USB works because most of what happens comes from there (keyboard/mouse). Today, USB is controlled by an Intel's xHCI (https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/extensible-host-controler-interface-usb-xhci.pdf). The xHCI is responsible to trigger interrupts when an event happens like when you press a keyboard key. At the hardware level, one (or some) pin of the xHCI is hardwired to the IOAPIC(s) of the processor. The IOAPIC is responsible to trigger an interrupt at the local APIC of one specific CPU core. The IOAPIC can be programmed to trigger certain local APICs depending on where the interrupt happened (what interrupt pin). The OS will determine what pin of the IOAPIC is connected to what by looking at the ACPI tables in RAM at boot. For example, it may find that the xHCI controller is connected to pin 12 of the IOAPIC. It will thus program that pin to fire a certain interrupt number in a specific local APIC.

The CPU has an IDT (interrupt descriptor table). The IDT is a table present in RAM which indicates some information to the processor on what to do with what interrupt number. For example, if the xHCI on pin 12 triggers an interrupt, the OS could decide to map it to interrupt number 10. The processor will thus look in its LIDT register, which stores the physical address of the IDT in RAM, and will jump to the handler of interrupt 10. The handler of interrupt 10 will do something depending on what was connected to this USB plug which has been determined at boot by querying this information from the xHCI.

For a keyboard keypress in hardware, the steps are the following:

1. The keyboard key is pressed.

2. The 5 volts provided by the USB port to the keyboard is used as the voltage to trigger a pin on the xHCI.

3. The xHCI then triggers a pin on the IOAPIC to interrupt the CPU.

4. The CPU looks in its LIDT register for the address of the IDT.

5. It fetches the information of the IDT from RAM (or from its cache most probably).

6. It jumps to the handler of the interrupt number that was programmed by the OS for that interrupt pin.

7. The handler uses a GetReport request to the HID USB device (https://wiki.osdev.org/USB_Human_Interface_Devices) to gather the info on what happened.

8. The HID device responds with a serial packet containing the information.

9. The OS interprets that info and sends to the application, which currently has focus, a message stating that a key was pressed. For example, on Windows 10, every application running is polling a message queue in a loop. When a message arrives (in the form of an int or a macro in C/C++), the message is switched for several messages until the right message is found and then handled by the application. The minimal Windows 10 window application looks like below (in C++).

#include <windows.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg)
{
case WM_DESTROY: //The user closed the application
PostQuitMessage(0);
return 0;

case WM_PAINT: //Message sent when the window is painted at app launch
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow){
// Register the window class.
const wchar_t CLASS_NAME[]  = L"Window";
WNDCLASS wc = { };
wc.lpfnWndProc   = WindowProc;
wc.hInstance     = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);

// Create the window.
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);

// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}



Every application in any language will be translated to something similar after being compiled. It doesn't matter if it is C# or C++ it will use the same API provided by Microsoft to create the window and show controls like buttons. As you can see the application goes into an infinite loop until GetMessage() returns a certain value which tells the app to close (when you close the app). In the meantime, it is receiving messages probably from the USB keyboard/mouse that the interrupt handler will translate to a message and then place the message at the end of the message queue of the application which currently has focus. Even a console application is a window application. The window is the console and your application is just running in a background thread of the console application which itself has a message queue.

Screen

Where you get things wrong I think is when you look at an abstract screen and think it is all magical. In the end, it's the other way around. From boot time to shutdown of the computer, everything is just electrical signals in the computer. The screen is just a representation of what is happening in the computer that software/OS developers determined.

At the hardware level, the screen is often controlled today by a graphics card. Even one which is embedded in the CPU. The graphics card can be accessed using the PCI bus and certain memory mapped registers. Memory mapped registers are hardwired to pins on the graphics card. When you set the address bus to the addresses of memory mapped IO (MMIO), what you output on the data pins (data bus) will be written to the graphics card registers. This way, you can send commands to the different hardware or read data from the hardware connected to PCI. It works the same way for the IOAPIC and the xHCI USB controller.

Using these registers, you can set the address of the framebuffer (Video RAM). The graphics card often has memory within itself to store video data. It is pretty complex and often graphics cards are provided along with their drivers. For example, NVIDIA graphics cards are closed source and there have been attempts to support them on Linux with the Nouveau driver which have been a complete failure. In the end, NVIDIA provided graphics card drivers for Ubuntu Linux and maybe some other distributions (since a driver for Linux should work on Linux). I don't know about the specifics.

The framebuffer will be read at certain rates by the graphics card and the screen refreshed. VGA works similarly but outside the PCI bus. It has separate controllers which is even emulated with today's more recent hardware. The framebuffer works by writing to some addresses in RAM, but writes the data to Video RAM instead which is separate memory.

Compilation

When you write a program in C/C++ (high level languages). You use a lot of abstract human/machine interfaces like the screen, keyboard and mouse. What you write is simply encoded as ASCII/UTF-8 in the machine at all time and stored in a text file. A .c/.cpp file is just a text file with a different extension. The .c/.cpp file will be iterated by the compiler and translated to machine code following the convention that the CPU provides for instruction encoding. It will then be placed in a file with a certain extension and a certain conventional format. For example, on Windows 10 the .exe files are executables. These executables store the virtual addresses at which the code should be placed in memory so that the different execution paths reference each other properly. By execution paths I mean the different functions, ifs, loops etc. In assembly it takes the form of relative jmps to certain virtual addresses. For example, you could have the main function executed at first from virtual address 0x401000. Then the foo() function will be placed at virtual address 0x400000. When you call that function, the CPU will execute something like jmp 0x400000 but it will be relative to the current position in the code (a short jump). In reality it will be more like jmp -0x1000 as depicted in the bochs emulator. Again assembly is just an abstract representation of machine code which has a more direct relationship to it than C/C++. What I mean by that is that you can easily go from assembly to machine code while compiling C/C++ to machine code takes more steps.

Launching an executable on Windows has many steps which could look like the following in hardware:

1. The user presses a mouse button while having the file explorer opened and with the mouse on the executable's icon.

2. The xHCI receives an electrical signal and triggers its interrupt line to the IOAPIC.

3. The IOAPIC fires a certain interrupt number to the local APIC it was programmed to.

4. The local APIC checks the IDT for the address of the handler for that interrupt number.

5. The local APIC changes the RIP register to that address which makes the CPU jump to the handler.

6. The CPU keeps doing its fetch, decode and execute cycle as usual and executes the handler.

7. The handler will send a message to the message queue of the file explorer.

8. The file explorer will eventually handle that message which will prompt it to determine what what pressed (what file).

9. The file explorer will then launch that application using system calls. The kernel will load some parts of that file (or the whole file) to RAM. The kernel will use IO port registers of the DMA controller. The DMA controller will load the data from disk placing the data in RAM. Once done, the hardware (hard-disk) will fire an interrupt.

10. The OS will then know it's time to launch that application. The OS will interpret the .exe file which is now in RAM and set up the page tables and other structures for the new process taking place.

11. The OS will put that application in its processes queue and eventually, will make the CPU jump to the first instruction of that process.

12. The CPU will then be executing the new process instruction by instruction.

You don't "convert" a zero to low voltage: a zero is low voltage. Whenever a logic component is at low voltage, we call that state "zero". Likewise, when a component is at high voltage, we call that state "one". Zeroes and ones exist only as voltage levels.

• As a programmer we write softwares using any language in a text editor not build circuits. So when this code is compiled you can feed this code to machine so that it performs required operation using physical components like transistors and diodes etc. which only understand voltage levels. So some component is switching the voltage levels according to the code you wrote. What's that component? Commented Jun 7, 2015 at 8:35
• The computer knows nothing except voltage levels. Even when you press a key, that changes voltage levels. "Zero", "one", "a Java program" and so on are all just the meanings that we assign to those voltage levels or sequences of voltage levels. The component that switches voltage levels according to the voltage levels you call code is the CPU. Commented Jun 7, 2015 at 9:26

There is nothing to convert, the moment you press a key your keyboard sends a signal containing the information about the pressed key (imagine a switch being turned on for the duration of the keypress, this is interpreted by a microchip), this information is already voltage and the cpu or other components work with that. So the only points where such a conversion is necessary are IO devices, if the device in question sends analog data this would be done by an AD Converter.

Maybe you are reffering to the state transion 1->0 or 0->1 itself ? Well, at the lowest level this is done with transistors, for example in NMOS logic you could build a NOR gate like this:

see NMOS, CMOS, MOSFET if you want to know more about it.

• I liked this answer because there is a circuit in it! A picture is worth more than a thousand words. The explanation is also good, so I've awarded a bounty to this answer. Commented Mar 3, 2021 at 6:00

Your machine code is not "converted" into electrical signals at all. It is a set of electrical signals. The fact that you see numbers and letters on your screen is irrelevant, all of that data is simply the processing of very precisely arranged electrical signals under a strict set of rules.

The text / code you are looking at on your display right now is a view of the underlying voltages residing on Memory ; therefore, if it’s not a voltage on memory, it’s never on screen.

Text/code is a view of voltages

To compile source code means cover underlying voltages to different voltages and view the resulted voltages as compiled code/text

• The question asks who compiles the source code. Commented Sep 18, 2019 at 18:49
• The Central Processing Unit - the CPU. Commented Sep 20, 2019 at 2:09

I’m afraid you are looking at things from the wrong level. There’s a highest level that we usually look at here: Algorithm design. Next level: High level programming languages. Below that: Assembly languages and machine code. Below: Processors. Below that: Logic design. Building things from and/or/nand gates. Out Next level: Transistors. And that’s where actual electricity comes in; voltages, currents, capacitors etc.

Very few people know and very few people care about details as low as this.

Every thing you write on a text editor, first, it is stored in a memory (electric signals generated from the keybord) no matter in which code (ascii,...). From memory, those signals are fed into the computer monitor and you can see the source code you are typing. Then, you run your compiler (or assembler) that reads the source code in memory (electric signals) and converts it to machine code, storing those transformed electric signals in another region of the memory (electric signals again). When the cpu reads the machine code, what it sees are electric signals. There is no logic levels, so there is no need to convert logic level in voltage level.

• I don't think this answers the question. Commented Jul 5, 2016 at 8:20

Actually voltage signals work with themselves in voltage layer(involve cpu,memory,input,output,...) ,and we can see the meaning of voltages signals in binary codes or c code or other language at pc monitor.

Basically, it is the data bus between the processor and the RAM that does this conversion from logic state to real voltage that can be measured with an instrument like a scope and logic analyzer. Modern computers are difficult to design and verify because the frequency is so high, the voltages decreased to lower values such as 3.3 volt or 1.8 volt. Furthermore, the cache memory inside modern processors prevent to probe the data bus after the first reading. But there is no magic trick. Every features are clearly described by each processor companies. There is option to disable the cache, forcing the CPU to access the RAM chip every time data is needed. This is very useful for hardware diagnostic. It could also resolve complex multi core cache corruption problem.