마이크로칩 8월
This page was machine-translated and may differ from the original. View original

[Serial] ST Yuji Kawano Engineer ⑦ - The Language of MCU, 'C'

Google 우선 소스Published2021.11.09 14:02
The language of the MCU, 'C'

Very convenient to write regardless of CPU
PC compiler C machine language automatic translation

[Editor's Note] When people think of semiconductors, they usually think of familiar semiconductors like computer CPUs and memory. Conversely, MCUs (Micro Controller Units), the core semiconductors that power electronic devices, are widely used in virtually every electronic device we encounter, yet they remain relatively unfamiliar to the general public. Recently, MCUs have been making headlines due to the semiconductor shortage, drawing public attention. Therefore, this magazine has prepared a series of articles by Yuji Kawano, Manager at STMicroelectronics, a company specializing in MCU semiconductors, to provide an in-depth look at MCUs.

■ You must master a programming language that can replace binary patterns.


MCUs execute instructions stored as binary (0/1) patterns in memory (e.g., ROM). However, binary instructions are not user-friendly, as their meaning is difficult for humans to understand. Therefore, programs must be written using a language system that can replace specific binary patterns. This language system is called a programming language. It is essential for programmers to master a programming language to write MCU programs. There are many different types of programming languages, and in this article we will look at a few of them.

■ Common language 'C' that can be used on all MCUs

As explained in 'Part 3. What is a CPU?', the instructions that instruct the CPU to perform operations are read from ROM in the form of binary patterns of 0 and 1. Ultimately, these binary (0/1) patterns must be generated somehow, but it is very difficult to tell at a glance which pattern is which instruction. Therefore, names are given to individual binary patterns, and programs are written using these names. Instructions composed of binary patterns are called machine language, and the names assigned to the binary patterns used in machine language are called assembly language (or mnemonic language). For example, addition is defined as 0000 0001 in 'Part 3. What is a CPU?', but if this pattern is called ADD here, then 0000 0001 is the addition instruction written in machine language, and ADD is the instruction written in assembly language.

MCU developers determine the machine language and assembly language for their respective MCUs. Therefore, each MCU may use a different language, and learning the assembly language of the MCU they intend to use is essential. Every time an MCU is replaced with a different one, programmers must learn the assembly language of the new MCU.

For programmers, it can't be too time-consuming. After examining high-level computer programming languages (e.g., Fortran, BASIC), C was selected as a common language that could be used across all MCUs.

C was initially adopted because its descriptive style made it suitable as a language for MCUs, but it is now widely used in PCs, MCUs, and mainframe computers.



▲Figure 1: Example of machine language



Let's look at how to represent the instruction 'Add 1 to the value in register 8 and store the result in register 8' in machine language using the Cortex-M3 CPU of ST's STM32. The pattern used to represent such instructions is [1111 0001], which means 'Add the value in the general register to a 12-bit numeric value and store the sum in the general register.' This is followed by the binary number [0000 1000], which is the number of the general register where the result of the addition will be stored. In this case, that number is 8 (register 8). Since the number being operated on is in register 8, another [0000 1000] follows. The last pattern to be added is the number '1' ([0000 0001]). Adding all these patterns together results in [1111 0001 0000 1000 0000 1000 0000 0001]. This binary pattern is a machine language instruction that says, 'Add 1 to the value in register 8 and store the result of the addition in register 8' (Figure 1). A machine language pattern stored in memory (e.g., ROM) is called an object.
Programs written in programming languages must be translated into machine language before the MCU can execute them.



▲Figure 2: Example of assembly language



Machine language consists of binary patterns, making it extremely difficult for humans to manipulate this format. Therefore, programs are written using a mnemonic language that corresponds roughly one-to-one to machine code. This mnemonic language is called assembly language.

Now, let's look at some assembly language. In the instruction above, "Add 1 to the value in register 8 and store the result in register 8," the first [1111 0001] indicates addition, which can be named ADD.W. This type of representation is a mnemonic. Register 8, a general-purpose register, is represented as R8. The mantissa (the number being added) is represented as #1 (# is commonly used to represent numbers in decimal). Adding all of these mnemonics together gives ADD.W R8 R8 #1, which is the assembly language version of the machine language we looked at at the beginning (Figure 2).

The four arithmetic operations used by the Cortex-M3 are ADD (addition), SUB (subtraction), MUL (multiplication), and SDIV (division). The logical operations are AND (logical AND), ORR (logical OR), and EOR (exclusive OR). Instructions for "jumping" within a program include BW (unconditional branch) and BL (conditional branch). Also, the instruction to perform no operation is NOP (short for "no operation").

The mnemonic portion of a machine language instruction that specifies the operation to be performed is called the "operation code (abbreviated as "opcode")." The address and data values of the machine language instruction that follows the opcode are called "operands." Finally, the process of translating assembly language into machine language is called "assembling."

Mnemonics simplify programming to a certain extent. However, because there is a one-to-one correspondence between mnemonics and machine language instructions, they remain challenging to use. Considering this, C, a high-level computer language, was adopted for MCU programming.

Assembly language and machine language are CPU-specific, so programs written in these languages cannot be used on other CPUs. However, C can be written regardless of the CPU, making it very convenient. For this reason, C is currently a widely used CPU language.

For a more detailed explanation of commands written in C, please refer to the numerous textbooks available on the market.



▲Figure 3: Comparison of C with machine language and assembly language



Next, let's examine the relationship between C and assembly language. But before that, let's first look at a technique for repeating NOP 500 times using a C while statement. See Figure 3. The program shown here first defines a variable m, then replaces m with 0, and adds 1 to m (++m) every time a NOP is executed (__asm("nop");). Then, when m finally reaches 500, it breaks out of the while loop (while (m<500)). Figure 3 shows, from left to right: how this program is expressed in C, the ROM address where the machine instructions are stored, the machine instruction (in hexadecimal), the assembly language instruction, and a description of each instruction. Here, ??main_5 is the name given to the address 0x80001d4. Similarly, ??main_4 is the name of the address 0x80001e0. Assembly language does not deal with addresses directly, but rather uses names given to addresses to write to them.

First, m, defined by int, is assigned to R8. Then, m=0 puts 0 in R8. CMP.W compares R8 to 500. If R8 is greater than or equal to 500, BGE.N causes the program to branch to ??main_4. However, since R8 is 0 here, there is no branch and it goes to ??main_5. ??main_5 adds 1 to R8 and executes a NOP. Then, CMP.W compares R8 to 500 again. This time, if R8 is less than 500, BLT.N causes the program to branch to ??main_5. Therefore, R8 starts at 0 and increments by 1, 2, 3, and so on. When m reaches 500, the program jumps to ??main_4 instead of branching to ??main_5. This program repeats the NOP instruction 500 times.

This image shows how easy it is to read C. Assembly language is much easier to read than machine language, but you still need to know mnemonics to understand it. However, PC compilers automatically translate C into assembly language and then translate it back into machine language, so programmers only have to write programs in C.

You might even dare to say that knowing only C allows you to write programs for MCUs. Even so, engineers need to understand how MCUs actually execute given programs.
본 기사에 대한 정정·반론·추후보도 청구는 보도 청구 안내를, 그간 게재된 보도문은 정정·반론보도 모아보기를 참고해 주세요.
명세환 기자
명세환 기자