首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MIPS - MIPS如何为堆栈中的数组分配内存?

MIPS - MIPS如何为堆栈中的数组分配内存?
EN

Stack Overflow用户
提问于 2013-10-27 06:11:15
回答 3查看 37.3K关注 0票数 15

我对MIPS汇编语言非常陌生,目前正在上一门关于计算机体系结构的课程,其中有很大一部分是关于MIPS编码的。我在过去学习过其他几种高级编程语言(C、C#、Python),因此对编程有一定的了解。

这里我的问题特别问: MIPS如何为堆栈中的数组分配内存?我希望回答这个问题能让我对MIPS有更好的整体理解,因为我仍然对MIPS语言及其体系结构的概念有很多了解。我也不太明白指针在这方面是如何工作的……

如果有人能抽出时间来帮助这个困惑的学生,那就太好了!:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-27 06:37:59

好吧..。您应该知道,像C一样,MIPS本质上有三种不同的内存分配方式。

考虑下面的C代码:

代码语言:javascript
复制
int arr[2]; //global variable, allocated in the data segment

int main() {
    int arr2[2]; //local variable, allocated on the stack
    int *arr3 = malloc(sizeof(int) * 2); //local variable, allocated on the heap
}

MIPS程序集支持所有这些类型的数据。

要在数据段中分配int数组,您可以使用:

代码语言:javascript
复制
.data

arr: .word 0, 0 #enough space for two words, initialized to 0, arr label points to the first element 

要在堆栈上分配int数组,您可以使用:

代码语言:javascript
复制
#save $ra
addi $sp $sp -4  #give 4 bytes to the stack to store the frame pointer
sw   $fp 0($sp)  #store the old frame pointer
move $fp $sp     #exchange the frame and stack pointers
addi $sp $sp -12 #allocate 12 more bytes of storage, 4 for $ra and 8 for our array
sw   $ra  -4($fp)

# at this point we have allocated space for our array at the address -8($fp)

要在堆上分配空间,需要一个系统调用。在spim模拟器中,这是system call 9

代码语言:javascript
复制
li $a0 8 #enough space for two integers
li $v0 9 #syscall 9 (sbrk)
syscall
# address of the allocated space is now in $v0
票数 25
EN

Stack Overflow用户

发布于 2018-10-01 04:24:24

与其他archs不同的是,MIPS没有推入或弹出寄存器/立即指令。因此,您依赖于自己管理堆栈。这实际上是在mul/div之外的大多数arch中注意到的,其中寄存器没有特定的用途,只是建议使用它的方式。现在,如果你想如何使用它,如果你试图与C语言集成,你可能会破坏一些东西。

为了将某些内容推送到堆栈,您需要使用存储指令。这些是sb, sh, sw, swl, swr。字节、半个、字、左字、右字。

代码语言:javascript
复制
addiu $sp, $sp, -4   # push stack 1 word
sw $t0, 0($sp)       # place item on newly pushed space

为了从堆栈中弹出一些东西,你只需要用addiu来减少它的增量即可。但是,您可能希望使用lb, lh, lw, lwl, lwr从其中加载数据。

代码语言:javascript
复制
lw $t0, 0($sp)
addiu $sp, $sp, 4   # pop stack 1 word

下面是一个使用两个单词push的例子。

代码语言:javascript
复制
addiu $sp, $sp, -8  # allocate two words
sw $t0, 0($sp)      # push two registers t0 t1
sw $t1, 4($sp)

lw $t1, 4($sp)      # pop two registers t0 t1
lw $t0, 0($sp)
addiu $sp, $sp, 8   # deallocate two words

下面是一个用于返回地址的示例,这样调用非叶函数就不会把您搞得一团糟。

代码语言:javascript
复制
# grab us a quick string
.data
example_str: .asciiz "hello world :^)"

# grab us a function
.text
    .globl example
    .type test, @function
test:
    addiu $sp, $sp, -4  # push stack for 1 word
    sw $ra, 0($sp)      # save return address
    
    la $a0, example_str # call puts and give it a string
    jal puts
    nop
    
    lw $ra, 0($sp)      # load return address
    addiu $sp, $sp, 4   # pop stack for 1 word
    
    jr $ra              # return from function to caller
    nop

下面是一个在一行中推送多个元素的示例。当然,弹出是相反的。

代码语言:javascript
复制
.data
example_arr: .word 0, 0, 0, 0

.text
addiu $sp, $sp, -16
la $t0, example_arr
lw $t1, 0($t0)
sw $t1, 0($sp)
lw $t1, 0($t0)
sw $t1, 4($sp)
lw $t1, 0($t0)
sw $t1, 8($sp)
sw $t1, 12($sp)

下面是一个使用malloc/calloc的示例。

代码语言:javascript
复制
# grab us a function
.text
    .globl example
    .type test, @function
test:
    addiu $sp, $sp, -4  # push stack for 1 word
    sw $ra, 0($sp)      # save return address
    
    li $a0, 4           # allocate 4*4 bytes (16)
    li $a1, 4
    jal calloc
    nop
    
    addiu $sp, $sp, -4  # push stack for 1 word
    sw $v0, 0($sp)      # save calloc'd buffer
    
    move $t0, $v0       # get the buffer into a temp
    li $t1, 1           # fill some temps with numbers
    li $t2, 2
    li $t3, 3
    li $t4, 4
    sw $t1, 0($t0)      # save some temps to buffer
    sw $t2, 4($t0)
    sw $t3, 8($t0)
    sw $t4, 12($t0)
    
    ... do stuff with the buffer ...
    
    lw $a0, 0($sp)      # pop buffer from stack
    jal free            # run it through free
    nop
    addiu $sp, $sp, 4   # don't forget to decrement
    
    lw $ra, 0($sp)      # load return address
    addiu $sp, $sp, 4   # pop stack for 1 word
    
    jr $ra              # return from function to caller
    nop

正如我前面提到的,没有任何东西有明确定义的特定用途,所以如果您愿意,您也可以使用自己的堆栈,而不使用$sp。我展示了使用$t*作为$s*的示例。例如,在强制每个函数拥有自己的堆栈或你能想到的其他用例的情况下,这是有效的。例如,Lua (https://lua.org)在某种程度上做到了这一点。但是,不是MIPS。多个堆栈是可爱的,特别是在处理多个目标时。

编辑:我意识到我遗漏了堆栈帧指针。请注意,如果您的代码与用C编写的代码相链接,则应正确处理堆栈帧指针。

票数 2
EN

Stack Overflow用户

发布于 2021-03-28 16:43:07

在MIPS中,我们手动管理堆栈,因此我们使用存储指令“sb sh sw swl swr”

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19612459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档