【问题标题】:MIPS - Call C function in Assembly codeMIPS - 在汇编代码中调用 C 函数
【发布时间】:2016-08-27 03:09:20
【问题描述】:

我试图从汇编文件中调用在 C 文件中声明的函数,但我收到“非法指令”错误。

我的 C 代码:

#include <stdio.h>

int BubbleSort(int *v){
    return 13;
}

int Run(int *, int *);


int main(){
    int vetor[] = {1, 3, 5, 4, 10}, numTrocas = 0, res = 0;
    numTrocas = Run(vetor, &res);   
    printf("numTrocas= %d\nf= %d\n", numTrocas, res);
    return 0;
}

我的汇编代码:

.data 
.text 
.globl Run

Run:
    addi $sp,$sp,-8
    sw $ra,0($sp)
    sw $a0,4($sp)
    move $t4, $a1 #$t4 = $a1; address of variable res in C file
    move $t6, $a0 #$t6 = address of the first vector element

    lw $a0, ($t6)
    add $t6, $t6, 4
    lw $a1, ($t6)
    add $t6, $t6, 4
    lw $a2, ($t6)
    add $t6, $t6, 4
    lw $a3, ($t6)
    add $t6, $t6, 4
    lw $t3, ($t6)
    jal PolyCalc

    lw $a0,4($sp)
    jal BubbleSort #-> Illegal Instruction

    lw $ra, 0($sp)
    addi $sp, $sp, 8 
    jr $ra

PolyCalc: #This function calculates the result of the expression 5(V[0] + V[1])(V[2] − 3xV[3]xV[4])
    li $s0,5             #$s0 = 5
    li $s1,3             #$s1 = 3
    add $t1,$a0,$a1      #t1=(x1+x2)
    mul $t1,$t1,$s0      #t1=5*(x1+x2)
    mul $t2,$a3,$t3      #$t2 = x4*x5
    mul $t2,$t2,$s1      #$t2 = 3*x4*x5
    sub $t2,$a2,$t2      #$t2 = (x3-3x4*x5)
    mul $t1,$t1,$t2      
    sw $t1, ($t4) #Save the result on the address of $t4
    jr $ra

当我注释 jal BubbleSort 行并将随机值添加到 $v0 作为 BubbleSort 函数的返回时,我停止收到该错误并且程序运行正常。

有人能在我的代码中找到错误吗? 谢谢

【问题讨论】:

  • 你如何编译和链接这个?您是否在调试器中单步执行了该程序?
  • 通常会发生非法指令错误,因为程序会有错误,这将使其跳转到带有纯数据或代码的随机地址,但不在操作码的开头。如果它是手动编写的代码汇编代码,那么我希望您检查堆栈返回以确保它没有指向正确的值。
  • 糟糕,我混淆了调用者保存和被调用者保存的抱歉。我的意思是 callee-saved,这意味着你必须为你的调用者保留 $s0$s1,而 PolyCalc 不会这样做,这反过来意味着 Run 也不会这样做,而 C调用代码稍后可能会对此不满意。但这不是非法指令的原因。 (删除旧的 cmets)

标签: c assembly mips


【解决方案1】:

为了更好地衡量,在您的 asm 文件中,您可能应该添加:

.extern BubbleSort

然后,jal BubbleSort 应该被正确重定位。

但是,对于jal 的[有限] 范围,链接器可能会将其放置得太远,因此您可能需要将其替换为:

la $t0,BubbleSort
jalr $t0

【讨论】:

    【解决方案2】:

    您遇到的错误是因为汇编代码找不到名为 BubbleSort 的标签进行跳转。我认为你应该使用不同的方法。您可以使用 asm 函数在 C 中嵌入汇编代码。

    类似:

    #include <stdio.h>
    
    int BubbleSort(int *v){
        asm("lw $a0, ($t6)"
        "lw $a1, ($t6)");
    }
    
    int Run(int *, int *);
    
    
    int main(){
        int vetor[] = {1, 3, 5, 4, 10}, numTrocas = 0, res = 0;
        numTrocas = Run(vetor, &res);   
        printf("numTrocas= %d\nf= %d\n", numTrocas, res);
        return 0;
    }
    

    您可以在 GCC 文档中找到有关此函数的更多信息:https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

    【讨论】:

    • 如果是这种情况,链接不会失败吗?
    • GNU C 内联 asm 使事情变得更简单或更容易。您必须了解更多内容才能编写在所有条件下都安全的正确约束。编写看起来可以工作的内联汇编很容易(尤其是如果您只测试而不进行优化),但是在您更改 C 或编译选项后会中断。有关更多信息,请参阅stackoverflow.com/questions/34520013/…。您的 asm 完全是伪造的,只有在您将 __attribute__((noinline)) 用于您放入的函数时才可能有效
    猜你喜欢
    • 2013-03-13
    • 2014-08-16
    • 2011-09-04
    • 2014-09-01
    • 1970-01-01
    • 2016-09-07
    • 2017-02-18
    • 1970-01-01
    • 2017-12-20
    相关资源
    最近更新 更多