gpt4 book ai didi

assembly - 如何在 MIPS 中在堆栈上推送和弹出地址

转载 作者:行者123 更新时间:2023-12-02 04:50:10 24 4
gpt4 key购买 nike

我正在为我的编译器类(class)做作业,我一直盯着我生成的 mips(32 位)代码好几个小时,试图找出它有什么问题,但无济于事。生成 mips 代码后,我在讲师提供的 mips VM 上使用 gcc 对其进行编译。我被告知要使用一些 C stdlib 函数,如 printf,我很确定部分代码是正确的,因为(正如我们被指示做的那样)我主要从 gcc 的类似 C 代码的输出中窃取它。

下面是应该的mips代码:

  • 为堆栈上的 2 个整数变量创建空间
  • 分别将它们初始化为 5 和 10(用于测试目的)
  • 通过将它们的绝对地址压入堆栈然后将其弹出并访问它来打印它们。

  • 目前发生的是第二个 printf 似乎打印存储在堆栈上第一个变量空间中的值,而不是第二个变量的值。

    (代码在使用常量整数时完全有效,所以我相信 printf 是完全正确的)
            .data
    printf_string: .asciiz "%d\n"
    scanf_string: .asciiz "%d"

    .text
    .globl main

    main:
    # make space for two ints on stack
    addiu $sp, $sp, -8
    # store return address in a saved register
    # was going to push it onto the stack but until I figure out this issue I'm
    # being lazy and just saving it to a saved register
    move $s0, $ra
    # make a copy of the stack pointer - likely not needed
    move $s1, $sp

    # typically here i loop and initialize the 2 ints on the stack but for now I'm
    # doing it manually so I can figure out this issue with less possible things
    # that could be wrong

    # load some value into the register so I can store it
    li $t7, 5
    # store into first variable
    sw $t7, 0($sp)
    # different so I can tell if printing location works
    li $t7, 10
    # store into second variable
    sw %t7, 4($sp)

    instructions:

    ########################################
    ### CODE BELOW PRINTS FIRST VARIABLE ###
    ########################################

    # appears to work...

    # load standard library pointer and stuff (copied from gcc output)
    # everything below works IF you did something like
    # "WRITE 5" instead of "WRITE a"
    lui $gp, %hi(__gnu_local_gp)
    addiu $gp, %lo(__gnu_local_gp)
    lw $t9, %call16(printf)($gp)
    .cprestore 16
    nop # needed after load word :-/

    # load print_string address - works
    la $4, printf_string
    # Here's where problems start
    # make space for location of visited variable
    addiu $sp, $sp, -4
    # initialize $t0 to top of stack
    move $t0, $s1
    # add offset of variable to $t0
    addiu $t0, $t0, 0
    # store absolute memory address of variable to stack
    sw $t0, 0($sp)

    # load absolute memory address of variable from stack
    lw $t0, 0($sp)
    nop # needed after lw
    # undo stack allocation
    addiu $sp, $sp, 4
    # load MEM[$t0 + 0] into $5 (arg 2)
    lw $5, 0($t0)
    nop
    # finally call printf
    jalr $t9
    nop

    #########################################
    ### CODE BELOW PRINTS SECOND VARIABLE ###
    #########################################

    # appears to print the value stored in the first variable
    # if I add "sw $s5, 4($sp)" here then it DOES work so I'm just very confused

    # everything here should be basically the same as above but with a different
    # offset/address pushed, popped, and accessed


    lui $gp, %hi(__gnu_local_gp)
    addiu $gp, %lo(__gnu_local_gp)
    lw $t9, %call16(printf)($gp)
    .cprestore 16
    nop

    la $4, printf_string
    addiu $sp, $sp, -4
    move $t0, $s1
    addiu $t0, $t0, 4
    sw $t0, 0($sp)

    lw $t0, 0($sp)
    nop
    addiu $sp, $sp, 4
    lw $5, 0($t0)
    nop
    jalr $t9
    nop


    addiu $sp, $sp, 8
    move $ra, $s0
    jr $ra
    nop

    如果有人能找到任何看起来不正常的东西,我将不胜感激!

    最佳答案

    这只是一个建议,而不是一个确定的答案,您可能不会调用 printf有一个地址。我注意到在将参数的地址写入堆栈后,您在调用 printf 之前恢复堆栈指针。 .因此,在这两个示例中,调用 printf 时堆栈指针都指向原始的第一个参数。 ,这可以解释为什么它在两种情况下都打印第一个参数。

    sw      $t0, 0($sp)
    lw $t0, 0($sp)
    nop
    addiu $sp, $sp, 4
    ...
    # finally call printf
    jalr $t9

    关于assembly - 如何在 MIPS 中在堆栈上推送和弹出地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29476021/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com