在 mips32 中表示一个结构

represent a struct in mips32

我正在为考试学习 Mips32,最近我在徘徊如何在 mips 中翻译 c 结构。 总的来说,我对 mips 和汇编代码还比较陌生,但我已经尝试收集我所有的知识来制定解决方案。

假设我有一个简单的 C 结构:

struct Student
{
    int id;
};

int main()
{
    struct Student student;
    student={111111};
    return 0;
}

我的想法是将所有数据存储在堆栈中,就像这样:

sub $sp,$sp,4
li  $t1,111111
sw  $t1,($sp)

如果我有多个学生,我只需创建一个将参数存储在堆栈中的例程。 但是我有一个问题,我怎样才能跟踪所有的学生? 也许有一个帧指针?

我不知道这是否是在 mips 中表示结构的合适方式,如果有更好的解决方案,请告诉我。

您的数据可以是本地的、静态的或动态分配的。没有一个规则。 参见:https://godbolt.org/z/gfDVD8

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

typedef struct
{
    int x;
    int y[4];
    char name[23];
}MYSTRUCT_t;



MYSTRUCT_t my_global_struct[10];

void my_global_struct_foo(void)
{
    for(size_t pos = 0; pos < 10; pos++)
    {
        my_global_struct[pos].x = rand();
        my_global_struct[pos].y[0] = my_global_struct[pos].x / 2;
        my_global_struct[pos].name[4] = my_global_struct[pos].y[0];
    }
}

void my_static_struct_foo(void)
{
    static MYSTRUCT_t my_static_struct[10];

    for(size_t pos = 0; pos < 10; pos++)
    {
        my_static_struct[pos].x = rand();
        my_static_struct[pos].y[0] = my_static_struct[pos].x / 2;
        my_static_struct[pos].name[4] = my_static_struct[pos].y[0];
    }
}

void my_local_struct_foo(void)
{
    volatile MYSTRUCT_t my_local_struct[10];

    for(size_t pos = 0; pos < 10; pos++)
    {
        my_local_struct[pos].x = rand();
        my_local_struct[pos].y[0] = rand();
        my_local_struct[pos].name[4] = rand();
    }
}

I have a problem though, how can I keep track of all the students? maybe with a frame pointer ?

您不需要框架指针来跟踪所有学生。此外,跟踪它们的问题并不是它们是结构体所独有的——您在跟踪许多整数时也会遇到同样的问题。更进一步,跟踪许多项目的问题也不是组装所独有的。

您需要的是每个项目的单独变量(通常不切实际,尤其是当项目数量可变时),或者数据结构:某种集合,例如例如,数组或链表。


在 C 中每个单独的局部变量都需要不同的名称,并且在汇编中每个变量在堆栈帧中都会有不同的 offset/location。所有的堆栈 space 将在一条指令中分配,并且它们都通过它们与堆栈指针的各自偏移量进行引用。

如果您愿意,可以使用帧指针,但由于使用 MIPS,函数堆栈帧的堆栈 space 全部在 function prologue 中的一条指令中分配,堆栈指针不会否则在函数体期间移动 - 这意味着各个变量保持与堆栈指针的恒定偏移量。


如果出现以下任一情况,帧指针可能会有所帮助:

  • 机器不能很好地进行堆栈相对偏移,但可以轻松进行帧指针相对偏移,或者,
  • 机器需要频繁的推送和弹出来移动堆栈指针,这会改变访问堆栈帧中相同位置所需的偏移量——无论推送和弹出如何,帧指针都保持不变。 (推送和弹出可用于参数传递,and/or临时存储,如果 CPU 寄存器不足,例如在表达式计算期间。)
  • 函数动态分配堆栈 space,例如通过 C 的 alloca.

一般来说,前两个不适用于 MIPS,因此函数通常不需要帧指针。


或者,您可以使用数组等数据结构来跟踪许多项目。数组本身需要由一个变量引用(在 C 中是一个名称,在汇编中是一个偏移量)——但至少只有一个变量,不管要跟踪多少项。然后您可以通过索引来访问各个元素。 (索引涉及计算元素的地址,并取决于元素的大小,但对于 int 数组与 struct 数组的其他操作相同。)

这里的一个好主意是用 .space 分配一些 space ,然后通过 .align n 指令对齐它(注意 MIPS 需要字对齐),然后加载您的 "main:" 中此内存区域的地址。

假设您要为 10 名学生分配 space:

std_struct: .align 2
           .space 40   # 10students, 1 word=4 bytes each
.text

main:

la $s0, std_struct #now everything should be parsable via $s0 register