【问题标题】:Linking assembly language with c用 c 连接汇编语言
【发布时间】:2013-01-29 03:16:17
【问题描述】:

我对汇编语言非常陌生,对 C 语言也很陌生。我看过一个示例,该示例从 c 代码中创建了一个调用函数,并且汇编代码具有一个执行计算并返回值的函数(这是一个任务) C代码:

#include <stdio.h>

int Func(int);

int main() 
{
int Arg;
Arg = 5;
printf("Value returned is %d when %d sent\n",Func(Arg), Arg);
}

汇编代码:

.global Func
Func:    save  %sp,-800, %sp
add  %i0, -45 , %l0  
mov %l0, %i0 
ret 
restore

它从 C 代码中获取值,将该值与汇编代码中的数字相加,然后输出新数字。我在很大程度上理解这个例子。我们的任务(修改代码):“编写一个调用 Func1 的 C 源文件,带有 2 个参数 A 和 B,以及包含两个方法 Func1 和 Func2 的汇编源文件。让 Func1 调用 Func2,就好像它是 Func2(Q) . Func2 应将其输入参数加倍并将该加倍的值发送回 Func1。Func1 应将值 2*A + 2*B 返回到 C 主程序。我已经尝试过了,并提出了这个解决方案(请原谅我,我是今天的新手)

#include <stdio.h>

int Func1(int, int);
void Func2(int, int);
int main() 
{
int Arg1 = 20;
int Arg2 = 4;
printf("Value returned is %d ",Func1(Arg1,Arg2));

}

组装:

.global Func1
Func1: save %sp,-800, %sp 
mov %l0, %i0
mov %l1, %i1
call Func2
nop
ret
restore

Func2: save %sp,-800, %sp
umul %i0, 2 , %l0
umul %i1, 2 , %l1
call Func1
nop

它不起作用,我一点也不惊讶。我确信这段代码有很多问题,但是对这里发生的事情或我做错的事情进行彻底的解释真的会有所帮助。

【问题讨论】:

  • @thelaws 是的,效果很好,当给定 5 时返回值 -40
  • 组装,好的,但是对于什么 CPU?可以标记一下吗?
  • 我不肯定,我只知道我们正在通过 ssh 在学校的 SPARC 机器上运行。
  • 您需要了解/查找架构的调用约定,以及一些有关为其编写汇编代码的文档。您可以在一定程度上作弊并使用 gcc 的 -S 选项将 C 代码转换为汇编代码并从中学习一些东西。
  • 我建议您使用gcc -Wall -S -fverbose-asm 进行编译(也许还有一些优化选项,例如-O2)。生成的.s 程序集文件随后包含一些有用的生成 cmets。

标签: c linux function assembly sparc


【解决方案1】:

我看对了吗:

In Func1, you call Func2
   which calls Func1 again
      which calls Func2 again
         which calls Func1 again
             which calls Func2 again
                 ...
Stack overflow, resulting in bad memory access and segmentation fault

显然,不要那样做 :)。你到底想做什么?从 Func2 返回乘法结果?然后返回它,就像你从 Func1 返回加法结果一样。

然后作业清楚地说:

像调用 Func2(Q) 一样调用 Func2。 Func2 应将其输入加倍 参数并将双倍的值发回

那么你为什么要给 Func2 两个参数呢?如果我们假设有效的分配,那么你可以处理它的小部分,就像我引用的这篇文章一样。它说 Func2 需要 1 个参数,因此请相信这一点并使用一个参数制作 Func2,并且您完成了一项分配(然后,如果事实证明分配无效或试图欺骗您,您当然需要回到它,但上面很清楚)。


但是为了帮助你,你有工作代码,对吧?

.global Func
Func:    save  %sp,-800, %sp
add  %i0, -45 , %l0  
mov %l0, %i0 
ret 
restore

对于 Func2,您需要更改该代码使其乘以 2,而不是添加 -45?您是否尝试过将添加指令更改为:

imul  %i0, 2 , %l0  

(或umul,但在你的C代码中你指定int而不是unsigned int,所以我认为它是签名的......)。


我不会为你写你的Func1,但你看看你是如何得到你的输入的,我认为这是正确的。然后你需要在返回之前在%i0 中产生结果。分小步进行:首先创建Func1,它只返回%i0 + %i1,根本不调用Func2。然后尝试2 * %i0 + %i1,调用一次Func2。然后最后编写请求版本的2 * %i0 + 2 * %i1 调用Func2 两次(或者对于更少和更简单的代码,提取公因数,因此您仍然需要调用Func2 一次)。

【讨论】:

  • 很棒的答案!谢谢!
【解决方案2】:

要将值传递回 func1,func2 不应再次调用 func1。让函数返回一个值给 func1。函数的返回值应该保存在寄存器 i0 中,这是大多数处理器的 ABI。

  1. main 调用具有值的 func1
  2. func1 读取 i0 形式的参数
  3. func1 使用 i0 中的参数调用 func2
  4. func2 将参数相乘并保存在 %l0
  5. 将值移回 i0 并返回

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    相关资源
    最近更新 更多