[英]How do loops with incrementing global variables work without volatile modifier?
I have been working on MSP430G2553 using using the mspgcc compiler and as an introductory program I have begun with blinking an LED. 我使用mspgcc编译器一直在研究MSP430G2553,作为一个介绍性的程序,我已经开始使用闪烁的LED。 The code that I have used is as follows: 我使用的代码如下:
#include <msp430.h>
unsigned int i;
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR |= 0x01; //Set P1.0 to output
for(;;)
{
P1OUT ^= 0x01;
i=0;
while(i<50000)
{
i++;
}
}
}
where while loop does the work of providing delay. while循环在哪里提供延迟的工作。
I thought that since the above while loop in which i
increments from 0 to a certain value, why can't I use a decrementing loop. 我认为,由于上面的while循环,其中i
从0递增到某个值,为什么我不能使用递减循环。 So I tried the following code. 所以我尝试了以下代码。
#include <msp430.h>
unsigned int i;
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
P1DIR |= 0x01; //Set P1.0 to output
for(;;)
{
P1OUT ^= 0x01;
i=50000
while(i>0)
{
i--;
}
}
}
This code didn't work and on finding the reason, I came to know that the global variable i
needs to be provided with "volatile" so as to prevent the optimization of compiler because here the value of i
can change at any time. 这段代码没有用,在查找原因后,我开始知道全局变量i
需要提供“volatile”以防止编译器的优化,因为这里i
的值可以随时改变。
My question is in the first case also the value of i
was changing from 0 to 49999 then why didn't we use "volatile" modifier in that case? 我的问题是在第一种情况下, i
的值也从0变为49999,那么为什么我们在这种情况下不使用“volatile”修饰符呢?
The assembler code for each of the cases above is as follows: 上述每种情况的汇编代码如下:
Case 1 (Incrementing loop) 案例1(递增循环)
main:
40B2 5A80 0120 MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
P1DIR |= 0x01; //Set P1.0 to output
D3D2 0022 BIS.B #1,&Port_1_2_P1DIR
P1OUT ^= 0x01;
$C$L1:
E3D2 0021 XOR.B #1,&Port_1_2_P1OUT
i=0;
4382 0200 CLR.W &i
while(i<50000)
90B2 C350 0200 CMP.W #0xc350,&i
2FF8 JHS ($C$L1)
i++;
$C$L2:
5392 0200 INC.W &i
90B2 C350 0200 CMP.W #0xc350,&i
2FF2 JHS ($C$L1)
3FF9 JMP ($C$L2)
Case 2 (Decrementing loop) 案例2(减少循环)
main:
40B2 5A80 0120 MOV.W #0x5a80,&Watchdog_Timer_WDTCTL
P1DIR |= 0x01; //Set P1.0 to output
D3D2 0022 BIS.B #1,&Port_1_2_P1DIR
P1OUT ^= 0x01;
$C$L1:
E3D2 0021 XOR.B #1,&Port_1_2_P1OUT
i=50000;
40B2 C350 0200 MOV.W #0xc350,&i
while(i>0)
9382 0200 TST.W &i
27F8 JEQ ($C$L1)
i--;
4382 0200 CLR.W &i
3FF5 JMP ($C$L1)
Briefly, the volatile
qualifier tells the compiler an object has side-effects beyond its "vision". 简而言之, volatile
限定符告诉编译器一个对象具有超出其“视觉”的副作用。 So it must not optimise out accesses to it. 所以它不能优化对它的访问。
Without this the compiler is free to optimise-out the whole loop if it can proof this will not change the observable behaviour of the program. 如果没有这个,编译器可以自由地优化掉整个循环,如果它可以证明这不会改变程序的可观察行为 。 Note that this is not guaranteed and in your case the compiler seems to recognise one code pattern, but not the other. 请注意,这不能得到保证,在您的情况下,编译器似乎识别出一种代码模式,而不是另一种代码模式。 But you must not rely on this (and whoever wrote that code lacks fundamental coding practice). 但是你不能依赖于这个(而且编写代码的人缺乏基本的编码实践)。
In both cases, volatile
is necessary though to be on the safe side. 在这两种情况下,虽然为了安全起见,但volatile
是必要的。 Note that the compiler still might be able to optimise the code; 请注意,编译器仍然可以优化代码; best is to additionally put a NOP
assembler intrinsic into the loop. 最好的是另外将NOP
汇编器固有地放入循环中。
Note: see the generated Assembler code. 注意:请参阅生成的汇编程序代码。 It is likely the optimised code will include something like i = 0
instead of the loop or just leave i
at the default value for static variables (which is 0
, too). 优化代码可能包含类似i = 0
而不是循环的东西,或者只是将i
保留为静态变量的默认值(也是0
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.