调整mips-gcc输出以在不使用脚本的情况下使用MARS

bnlyeluc  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(99)

mips-gcc 生成的MIPS汇编代码几乎可以在MARS_ MIPS模拟器上运行,但还不完全可以。举例来说:

  • 编译器生成“j $31”而不是“jr $31”
  • 编译器将 .align 指令放在文本段中,这是MARS不允许的。

此外,生成的程序集没有完全设置好,因此它将正确启动和停止(即,最后没有 syscall 10)。
这些问题似乎都可以通过一个简单的脚本轻松解决;但在我重新发明轮子之前我想知道
1.有没有什么gcc标志可以解决这些问题?
1.是否有一个现有的程序可以修复 mips-gcc 的输出,以便它可以在火星上运行?
(FWIW,我在GCC 3.3.6和4.6.1中都看到了相同的行为。)

sg3maiej

sg3maiej1#

是否有任何GCC标志将使这些问题中的一些消失?
简单的回答是否定的。MARS使用自定义系统调用,并且在调用约定上有很大的不同。
是否有一个现有的程序,将修复mips-gcc的输出,使其将在火星上运行?
我不知道有什么自动转换的方法。您只能手动执行此操作。我真的做过了。
大致上,我遵循了以下步骤:
1.使用Godbolt(编译器资源管理器)获取代码的美化的原始程序集。他们不使用特定的GCC选项来获得这个根据this的祝福视图,所以我没有提到任何GCC命令,但是你可以设置它的本地副本。
1.根据 * SYSCALL functions available in MARS * 替换所有系统调用及其调用约定
1.替换/添加所需的段标签(如 .text.data 等)沿着所需的数据。
1.如果有main函数(标签),请在.text之后添加j main
1.(或者,您可以重命名寄存器以提高可读性,因为正如Peter Cordes在评论中提到的,GCC for MIPS不支持参数-mregnames
这是我举的一个例子。它缺少 main,因为它本来是作为一个库使用的:
C代码:

#include <stdio.h>

#include <stdlib.h>

typedef struct node Node;

struct node {
    int data;
    struct node *left;
    struct node *right;
};

Node *new_node (int data) {
    Node *ret = malloc (sizeof (Node)); ret->left = NULL;
    ret->data = data;
    ret->left = NULL;
    ret->right = NULL;

return ret; }

void link (Node *parent, Node *left, Node *right) {
    parent->left = left;
    parent->right = right;
}

int depth (Node *root) {

    if (root == NULL) {
        return -1;
    }

    int left = depth (root->left);
    int right = depth (root->right);

    return 1 + (left > right? left : right);
}

int even_level_max (Node *root, int level) {

    if (root == NULL) {
        return 0x80000000;
    }

    int left = even_level_max(root->left, level + 1);
    int right = even_level_max (root->right, level + 1);
    int greater = (left > right) ? left : right;

    if (level % 2 == 0) {
        return (greater > root->data)? greater : root->data;
    } else {
        return greater;
    }
}

字符串
Godbolt代码:

new_node:
        addiu   $sp,$sp,-40
        sw      $31,36($sp)
        sw      $fp,32($sp)
        move    $fp,$sp
        sw      $4,40($fp)
        li      $4,12                 # 0xc
        jal     malloc
        nop

        sw      $2,24($fp)
        lw      $2,24($fp)
        nop
        sw      $0,4($2)
        lw      $2,24($fp)
        lw      $3,40($fp)
        nop
        sw      $3,0($2)
        lw      $2,24($fp)
        nop
        sw      $0,4($2)
        lw      $2,24($fp)
        nop
        sw      $0,8($2)
        lw      $2,24($fp)
        move    $sp,$fp
        lw      $31,36($sp)
        lw      $fp,32($sp)
        addiu   $sp,$sp,40
        jr      $31
        nop

link:
        addiu   $sp,$sp,-8
        sw      $fp,4($sp)
        move    $fp,$sp
        sw      $4,8($fp)
        sw      $5,12($fp)
        sw      $6,16($fp)
        lw      $2,8($fp)
        lw      $3,12($fp)
        nop
        sw      $3,4($2)
        lw      $2,8($fp)
        lw      $3,16($fp)
        nop
        sw      $3,8($2)
        nop
        move    $sp,$fp
        lw      $fp,4($sp)
        addiu   $sp,$sp,8
        jr      $31
        nop

depth:
        addiu   $sp,$sp,-40
        sw      $31,36($sp)
        sw      $fp,32($sp)
        move    $fp,$sp
        sw      $4,40($fp)
        lw      $2,40($fp)
        nop
        bne     $2,$0,$L5
        nop

        li      $2,-1                 # 0xffffffffffffffff
        b       $L6
        nop

$L5:
        lw      $2,40($fp)
        nop
        lw      $2,4($2)
        nop
        move    $4,$2
        jal     depth
        nop

        sw      $2,24($fp)
        lw      $2,40($fp)
        nop
        lw      $2,8($2)
        nop
        move    $4,$2
        jal     depth
        nop

        sw      $2,28($fp)
        lw      $3,24($fp)
        lw      $2,28($fp)
        nop
        slt     $4,$2,$3
        beq     $4,$0,$L7
        nop

        move    $2,$3
$L7:
        addiu   $2,$2,1
$L6:
        move    $sp,$fp
        lw      $31,36($sp)
        lw      $fp,32($sp)
        addiu   $sp,$sp,40
        jr      $31
        nop

even_level_max:
        addiu   $sp,$sp,-48
        sw      $31,44($sp)
        sw      $fp,40($sp)
        move    $fp,$sp
        sw      $4,48($fp)
        sw      $5,52($fp)
        lw      $2,48($fp)
        nop
        bne     $2,$0,$L9
        nop

        li      $2,-2147483648                  # 0xffffffff80000000
        b       $L10
        nop

$L9:
        lw      $2,48($fp)
        nop
        lw      $3,4($2)
        lw      $2,52($fp)
        nop
        addiu   $2,$2,1
        move    $5,$2
        move    $4,$3
        jal     even_level_max
        nop

        sw      $2,24($fp)
        lw      $2,48($fp)
        nop
        lw      $3,8($2)
        lw      $2,52($fp)
        nop
        addiu   $2,$2,1
        move    $5,$2
        move    $4,$3
        jal     even_level_max
        nop

        sw      $2,28($fp)
        lw      $3,24($fp)
        lw      $2,28($fp)
        nop
        slt     $4,$2,$3
        beq     $4,$0,$L11
        nop

        move    $2,$3
$L11:
        sw      $2,32($fp)
        lw      $2,52($fp)
        nop
        andi    $2,$2,0x1
        bne     $2,$0,$L12
        nop

        lw      $2,48($fp)
        nop
        lw      $3,0($2)
        lw      $2,32($fp)
        nop
        slt     $4,$2,$3
        beq     $4,$0,$L10
        nop

        move    $2,$3
        b       $L10
        nop

$L12:
        lw      $2,32($fp)
$L10:
        move    $sp,$fp
        lw      $31,44($sp)
        lw      $fp,40($sp)
        addiu   $sp,$sp,48
        jr      $31
        nop


转换后的Mars代码:

# Registers:
# a : store results
# t : temporaries
# s : saved
# k : kernel

.text:

j main

new_node: #Node *new_node (int data)
        # prologue
        addiu   $sp,$sp,-40
        sw      $ra,36($sp)
        sw      $fp,32($sp)
        move    $fp,$sp

        sw      $a0,40($fp) # fp[40] = data

        li      $v0, 9
        li      $a0, 12
        syscall
        sw      $v0,24($fp) # fp[24] = sbrk ( sizeof (Node = 12) )

        lw      $v0,24($fp)
        lw      $v1,40($fp) # data = fp[40]
        sw      $v1,0($v0) # ret[0] = data;

        lw      $v0,24($fp)
        sw      $zero,4($v0) # ret[4] = NULL;

        lw      $v0,24($fp)
        sw      $zero,8($v0) # ret[8] = NULL;

        # epilogue
       lw      $v0,24($fp)
        move    $sp,$fp
        lw      $ra,36($sp)
        lw      $fp,32($sp)
        addiu   $sp,$sp,40
        jr      $ra
        nop

link: # int depth (Node *root)
        # prologue
        addiu   $sp,$sp,-8
        sw      $fp,4($sp)
        move    $fp,$sp

        #store arguments
        sw      $a0,8($fp)
        sw      $a1,12($fp)
        sw      $a2,16($fp)

        #parent -> left = left;
        lw      $v0,8($fp)
        lw      $v1,12($fp)
        sw      $v1,4($v0)
        sw      $a1,4($a0)

        # parent -> right = right
        lw      $v0,8($fp)
        lw      $v1,16($fp)
        sw      $v1,8($v0)
        sw      $a2,8($a0)

        # epilogue
        move    $sp,$fp
        lw      $fp,4($sp)
        addiu   $sp,$sp,8
        jr      $ra
        nop

depth: # int depth (Node *root)
        # prologue
        addiu   $sp,$sp,-40
        sw      $ra,36($sp)
        sw      $fp,32($sp)
        move    $fp,$sp

        sw      $a0,40($fp) # fp[40] = root
        lw      $v0,40($fp)

        bne     $v0,$zero,L5
        li      $v0,-1
        b       L6 #if (root == NULL) return -1;

L5:
        lw      $v0,40($fp)
        lw      $v0,4($v0)
        move    $a0,$v0 # a0 = root -> left
        jal     depth # depth(a0)
        sw      $v0,24($fp) # fp[24] = depth(a0)

        lw      $v0,40($fp)
        lw      $v0,8($v0)
        move    $a0,$v0 # a0 = root -> right
        jal     depth # depth(a0)
        sw      $v0,28($fp) # fp[28] = depth(a0)

        lw      $v1,24($fp) # v0 = right
        lw      $v0,28($fp) # v1 = left

        slt     $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
        beq     $a0,$zero,L7

        move    $v0,$v1 # executed when v1 > v0
L7:
        addiu   $v0,$v0,1 # executed when v0 < v1
L6:
        # epilogue
        move    $sp,$fp
        lw      $ra,36($sp)
        lw      $fp,32($sp)
        addiu   $sp,$sp,40
        jr      $ra

even_level_max:
        # prologue
        addiu   $sp,$sp,-48
        sw      $ra,44($sp)
        sw      $fp,40($sp)
        move    $fp,$sp

        sw      $a0,48($fp) # fp[48] = root
        sw      $a1,52($fp) # fp[52] = level
        lw      $v0,48($fp)

        bne     $v0,$zero,L9
        li      $v0, 0x80000000
        b       L10 # if (root == NULL) return 0x80000000;

L9: # root != NULL
        lw      $v0,48($fp)
        lw      $v1,4($v0) # v1 = root -> left
        lw      $v0,52($fp)
        addiu   $v0,$v0,1 # v0 = level + 1
        move    $a1,$v0
        move    $a0,$v1
        jal     even_level_max
        sw      $v0,24($fp) # fp[24] = left = even_level_max(root -> left, level +1)

        lw      $v0,48($fp)
        lw      $v1,8($v0) # v1 = root -> right
        lw      $v0,52($fp)
        addiu   $v0,$v0,1 # v0 = level + 1
        move    $a1,$v0
        move    $a0,$v1
        jal     even_level_max
        sw      $v0,28($fp) # fp[28] = right = even_level_max(root -> right, level + 1)

        lw      $v1,24($fp) # v1 = right
        lw      $v0,28($fp) # v0 = left
        slt     $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
        beq     $a0,$zero,L11
        move    $v0,$v1
L11:
        sw      $v0,32($fp) # fp[32] = greater

        lw      $v0,52($fp) # v0 = level
        andi    $v0,$v0,0x1 # v0 & 1
        bne     $v0,$zero,L12

        lw      $v0,48($fp) # v0 = root
        lw      $v1,0($v0) # v1 = data
        lw      $v0,32($fp)  # v0 = greater
        slt     $a0,$v0,$v1 # a0 = v1 > v0 ? 0 : 1
        beq     $a0,$zero,L10 # return greater

        move    $v0,$v1 # v0 = data
        b       L10 # return data

L12:
        lw      $v0,32($fp) # return greater
L10:
        # epilogue
        move    $sp,$fp
        lw      $ra,44($sp)
        lw      $fp,40($sp)
        addiu   $sp,$sp,48
        jr      $ra

相关问题