我试图了解编译器如何引用自动变量。我的参考点是带有PIC32MZ编译器的XC32微控制器。
到目前为止,我理解全局变量和静态变量是如何工作的。编译器将它们放置在内存中,然后将地址和大小硬编码到代码中。说明中将包含地址。因此,像c=a+ b这样的操作,如果它们都是全局的,则类似于。(数独大会)
将地址移动到工作寄存器。将b的地址移动到另一个工作寄存器。添加两个工作寄存器。将结果移到c的地址。
如何处理自动变量?
从读取XC32编译器手册开始,自动变量将存储在堆栈中。堆栈的末尾由堆栈指针跟踪。它没有提到以后如何引用它们。如果变量在内存中的位置发生变化,指令将包含什么地址或命令?
有了动态记忆,这个想法就很有意义了。返回malloc是指向新变量位置的指针,该指针存储在一个已经存在的变量中。
发布于 2018-10-17 15:47:57
通过查看我编写的一些代码的反汇编,我找到了我正在寻找的答案。总体想法和预期一样,但我发现细节令人惊讶。
下面是函数开始和结束的一个小片段。
功能开始
0x9D005640: ADDIU SP, SP, -56
0x9D005644: SW RA, 52(SP)
0x9D005648: SW S7, 48(SP)
0x9D00564C: SW S6, 44(SP)
0x9D005650: SW S5, 40(SP)
0x9D005654: SW S4, 36(SP)
0x9D005658: SW S3, 32(SP)
0x9D00565C: SW S2, 28(SP)
0x9D005660: SW S1, 24(SP)
0x9D005664: SW S0, 20(SP)功能结束
0x9D0057CC: LW RA, 52(SP)
0x9D0057D0: LW S7, 48(SP)
0x9D0057D4: LW S6, 44(SP)
0x9D0057D8: LW S5, 40(SP)
0x9D0057DC: LW S4, 36(SP)
0x9D0057E0: LW S3, 32(SP)
0x9D0057E4: LW S2, 28(SP)
0x9D0057E8: LW S1, 24(SP)
0x9D0057EC: LW S0, 20(SP)
0x9D0057F0: JR RA
0x9D0057F4: ADDIU SP, SP, 56在开始时,堆栈指针(SP)被递增,以便在堆栈上有更多的空间。由于堆栈从上面的地址开始并向下移动,因此从堆栈指针中减去56来移动它是有意义的。这是通过使用ADDIU命令并添加一个负值来完成的。
接下来是令人惊讶的部分。SW命令将数据从工作寄存器移动到存储器。可以看到,S0是通过S7复制的。从MIPS文档中可以看出,在使用S工作寄存器之前,需要清空它们。然后,此行为与文档保持一致。
SW命令将数据从工作寄存器移动到存储器地址。这就是我的问题得到回答的地方。例如,列出的地址是20(SP)。这意味着SP + 20。然后这种机制允许对相对于SP的数据进行寻址。通过添加到SP,这会相对于堆栈指针将数据地址移动到堆栈中。20( SP )例程类似于子命令,因为核心在执行SW之前计算SP+ 20。
然后,当函数执行其操作时,它使用现在自由工作的电阻器。
最后,当操作完成后,位于堆栈中的数据将使用LW命令移回工作寄存器中。类似于SW命令,堆栈中的寻址是用相对偏移量完成的。要结束函数56,将其添加回堆栈指针,以释放正在使用的内存。
https://stackoverflow.com/questions/52700116
复制相似问题