C51 optimization design loop statement

Publisher:AngelicHeartLatest update time:2015-07-22 Source: 51heiKeywords:C51 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
C51 has three loop statements, while, do-while and for. These three loops can be used to handle the same problem and can basically be replaced by each other. However, since C51 is a compiler for 51 assembly language, if you do not pay attention to the characteristics of 51 assembly instructions, different programming methods may result in different program performance (execution speed and code length). Take the calculation of 1+2+3+...+9+10 as an example, and make a comparison below.
Procedure 1:
unsigned char i;
unsigned char sum;
for(i=1,sum=0;i<11;i++)
{
sum+=i;
}
The assembly code is:
C:0x0003 7F01 MOV R7,#0x01
C:0x0005 E4 CLR A
C:0x0006 FE MOV R6,A
C:0x0007 EF MOV A,R7
C:0x0008 2E ADD A,R6
C:0x0009 FE MOV R6,A
C:0x000A 0F INC R7
C:0x000B BF0BF9 CJNE R7,#0x0B,C:0007
Code length (bytes): 11, execution cycle (machine cycle): 63

Procedure 2:
unsigned char i;
unsigned char sum;
for(i=10,sum=0;i;i--)
{
sum+=i;
}
The assembly code is:
C:0x000F 7F0A MOV R7,#0x0A
C:0x0011 E4 CLR A
C:0x0012 FE MOV R6,A
C:0x0013 EF MOV A,R7
C:0x0014 2E ADD A,R6
C:0x0015 FE MOV R6,A
C:0x0016 DFFB DJNZ R7,C:0013
Code length (bytes): 9, execution cycle (machine cycle): 53

Procedure 3:
unsigned char i=11;
unsigned char sum=0;
while(i--)
{
sum+=i;
}
The assembly code is:
C:0x0003 7F0A MOV R7,#0x0B
C:0x0005 E4 CLR A
C:0x0006 FE MOV R6,A
C:0x0007 AD07 MOV R5,0x07
C:0x0009 1F DEC R7
C:0x000A ED MOV A,R5
C:0x000B 6005 JZ C:0012
C:0x000D EF MOV A,R7
C:0x000E 2E ADD A,R6
C:0x000F FE MOV R6,A
C:0x0010 80F5 SJMP C:0007
Code length (bytes): 15, execution cycle (machine cycle): 130

From the above three different programs, we can see that the calculation results are all 0x37 (55), but the shortest code is 9, the longest code is 15, the fastest speed is 53, and the slowest speed is 130. It can be seen that the performance of the three programs is quite different.

How to write loop code with small space and high running efficiency? To write excellent loop code in C51 compilation environment, you must be familiar with the instruction system of 51 assembly language. Observe program 2, the loop control instruction uses DJNZ loop transfer instruction, which completes both counting and loop judgment operations at the same time, and only occupies two bytes. It is the most efficient loop instruction in the 51 instruction system. Therefore, when designing loop programs, C51 should use DJNZ in loop programs as much as possible. Of course, the number of loops of DJNZ instruction is fixed, and it is mainly used in the case of a fixed number of loops.

One of the biggest features of the DJNZ instruction is the decrement count, so the loop program must use the decrement method to compile the DJNZ instruction, such as the above program 2. Another feature of the DJNZ instruction is to decrement first and then judge, so the design of the loop program must also adhere to the principle of decrement first and then judge, otherwise the DJNZ instruction cannot be obtained, such as the above program 3. If program 3 is rewritten as:
unsigned char i=10;
unsigned char sum=0;
while(i)
{
sum+=i;
i--;
}
, the same assembly code as program 2 can be obtained. If there are other operations after i--, for example, change it to:
unsigned char i=10,j=0;
unsigned char sum=0;
while(i)
{
sum+=i;
i--;
j++;
}
also cannot get DJNZ assembly instruction, that is to say, during the execution of loop statement, decrement and judgment must be continuous, and decrement comes first and judgment comes later. For while loop, when decrement and judgment are combined into one step, while(--i) should be used. According to the above, do-while loop can also assemble DJNZ instruction, which will not be listed one by one.

However, when the loop variable is not completed by a constant assignment statement, but comes from another variable, the for and while statements cannot generate DJNZ instructions no matter what control flow they use, because both loops are control logics that are judged first and then executed, and the execution process of DJNZ is to execute the loop body first and then make loop judgments. According to the control flow of DJNZ, only the do-while statement meets this condition, so when the number of loops is not a constant but a variable, the do-while loop statement must be used.

In summary, if you want to use the DJNZ instruction to improve program efficiency, you should adhere to the following three principles when designing loop programs:
① Use decrement counting;
② Decrement first and then judge, and the decrement and judgment are performed continuously;
③ When the number of loops is a variable, use a do-while loop.
The 8051 microcontroller has two loop instructions, namely DJNZ Rn, rel and DJNZ direct, rel. For basic microcontrollers, the execution time of both is 2 machine cycles, but the instruction length of the two is different. The former occupies 2 bytes and the latter occupies 3 bytes. The loop program also involves the initialization operation of the loop variable. For the former, use MOV Rn, #XX, 2 bytes per cycle, and for the latter, use MOV direct, #XX, 3 bytes 2 cycles. Taking a single-layer loop as an example, using a working register saves 2 bytes and 1 cycle compared to a direct address. In addition, the more important performance difference between the two is that the latter requires an additional memory unit to be allocated. Because program modules usually use working registers as local variables, using working registers as loop variables will not increase memory usage. In short, using working registers as loop counters is an important principle that should be adhered to when designing loop programs.

Generally, the C51 compiler assigns the number of loops to the working register, such as
unsigned char i;
for(i=100;i;i--)
{
dosomething();
}

However, the result of C51 compilation is often unsatisfactory when one of the following situations occurs:
① The function dosomething is an externally defined C language function;
② Function dosomething is an external function with C language interface, which is implemented in assembly language and can be called by C program.
In the above two cases, loop variable i is stored in memory unit, that is, direct addressing is adopted. For local variable i, C51 compiler adopts direct address storage. The reason is that it is based on the assumption that, without any special treatment, C51 assumes that external function occupies all working registers. Therefore, these occupied registers cannot be modified outside the loop. C51 can only allocate loop control variables in memory address units. However, if only a few working registers are used in the loop body statement or even no working registers are used at all, the compiler still processes according to this assumption, then the compiler cannot show its efficiency. Fortunately, C51 provides a pseudo-instruction REGUSE to make up for this defect. The REGUSE pseudo-instruction is used to tell the compiler which registers or special function registers SFR are occupied by a function or subroutine. The compiler may allocate loop variables to registers not occupied by the loop body according to the register occupation information provided by the function, thereby achieving the purpose of optimizing the design.

In addition, one switch must be turned on, namely Global Register Coloring, by checking Project - Options for Target - C51 - Global Register Coloring.

In case ①, you should add code to the source file where the function dosomething is located (assuming that the function occupies A and B):
#pragma asm
$REGUSE dosomething(A,B)
#pragma endasm
After recompiling the project, you can see in the assembly window that the loop variable has used the working register.
In case ②, since it is an assembly program, you only need to add one line of code (assuming that the subroutine occupies A and B):
$REGUSE dosomething(A,B)
It can also be observed that the loop variable has been changed to the working register.

It should be noted that the register occupation mentioned here refers to the possibility or certain destruction of these registers during the execution of the function or subroutine, that is, the execution of write operations, and read-only registers should not be treated as occupied. In addition, the working registers used for parameter passing do not need to be specified.

Keywords:C51 Reference address:C51 optimization design loop statement

Previous article:ADC0804+LED digital tube displays analog value 0~255
Next article:51 MCU bus driver

Recommended ReadingLatest update time:2024-11-15 14:55

Compressed BCD code addition program of C51 single chip microcomputer
Assume that both the augend NA and the addend NB are three-byte compressed BCD codes, which are stored in the internal RAM units 20H~22H and 30H~32H, respectively, with the low digit first and the high digit last. It is required to calculate the sum of the two numbers and store the sum in the internal RAM units 3FH~42
[Microcontroller]
#C51 serial communication 2-#a string of data#timed interrupt to achieve timeout reception
1. Scenario Realize the reception of a string of data of non-fixed length and return the corresponding data (the basic framework of data parsing) 2. Programming Implementation 1. Design thinking With the help of T0 timer, continuously count +1 After receiving a frame of data (1 Byte), the serial port interrupt servi
[Microcontroller]
#C51 serial communication 2-#a string of data#timed interrupt to achieve timeout reception
Some insights on self-study of C51 microcontroller for reference only
     I have been learning C51 for more than half a month. In this short half month, although I did not study every day, at least the time I invested was proportional to the number of days. Fortunately, with the knowledge of C language and assembly as a foundation, learning C51 is still quite easy. In this half month, t
[Microcontroller]
Design of C51 single chip microcomputer in motor speed measurement simulation system
The simulation system of the single-chip microcomputer motor speed measurement system uses the T1 counter in the single-chip microcomputer to count the speed pulses. Timer T1 works in the external event counting mode to count the speed pulses; T0 works in the timer mode. The count value is read once every 1 s. This va
[Microcontroller]
Design of C51 single chip microcomputer in motor speed measurement simulation system
C51 Programming 24-Application (ESP-01S WIFI module and computer communication)
In order to realize transparent transmission between the computer and the microcontroller, we must first understand the WiFi module. Test whether the wifi module is normal Use a serial cable to connect to the wifi module serial port. Connect the CH340G serial cable TX to the wifi module RX, and connect the CH340G se
[Microcontroller]
C51 Programming 24-Application (ESP-01S WIFI module and computer communication)
Keil c51 serial port debugging
/*  Keil c51 platform simulates debugging of c51 serial port program. The program running results can be observed on the keil c51 serial window, and parameters can be input on the PC keyboard. c51 provides some standard serial input and output functions. When calling the input and output functions, the user program
[Microcontroller]
How does Keil C51 support double data pointers and what are the special requirements?
In the 8051 system, the data pointer DPTR is used as a special 16-bit register for addressing the 64 KB XDATA or CODE space. It is usually used as a 16-bit pointer pointing to a constant table. Double data pointers can improve performance when two 16-bit pointers are used at the same time. As an enhanced feature, ther
[Microcontroller]
How does Keil C51 support double data pointers and what are the special requirements?
How to access a certain address unit in each space in C51?
In C51 , how to access a certain address unit in DATA space, PDATA space, XDATA space, CODE space? A: Macros that access memory using pointers When using it, you need to use the preprocessing command to include the header file into the file in the form of: #include . (1) Byte-by-byte access to memory macros
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号