KeyFC欢迎致辞,点击播放
资源、介绍、历史、Q群等新人必读
KeyFC 社区总索引
如果你找到这个笔记本,请把它邮寄给我们的回忆
KeyFC 漂流瓶传递活动 Since 2011
 

[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

[ 5632 查看 / 6 回复 ]

现在的情况是,有一段代码必须要用汇编来写,其他代码还是要用c来写,
即程序运行到了到了c的某处,需要运行一段汇编,然后回到c
而且,麻烦的是,c还需要给这段汇编一些参数。
尝试使用asm{}语句去嵌入,但是编译器不吃。。。= =
现在的想法最好还是分开来写,一个文件是c,另一个是汇编,
但是不知道怎么才能在c中的某个地方运行另一边的汇编,
即这个接口到底是怎么写的。像一般的方程就可以?
还是分别编译,然后link到一起,但是要怎么link?
不太清楚compiler和linker到底是怎么工作的,
对待不同语言之间的有什么区别,能否让两种语言一起工作。
基本上就是寻求一个解决方案,
如何让这两种语言一起工作,然后还能有数据往来。
分别写都没问题,但是到了这个interface就不知道怎么写才好了。

还有一个问题,就是怎么在c里定义一个指针,指向一个绝对的物理地址。
比如 *p = 0xfff10010;我的编译器还是不吃orz
其实需要的是一个指针指向这里,然后同时传四个参数,
茅盾的是,如果用方程指针,是可以传参数了,但是方程指针只能指向一个自定义的方程,不能让他指向一个地址。
如果用一般指针,就像上面问的,也许能指向地址,但是指针不能当方程用,无法传参数。
我知道这些想法和语言的基本原理不合,
按理说,把四个参数传到一个地址这件事本身就没法解释,但是实际问题就是如此需要。。。orz

顺便,编译器现在是linux环境下的gcc...
如果c++或者别的语言下有解决方案的话,也可以参考,
把c移植到c++对实际要求没有影响。
多谢了,这个问题直接关系到我这个月的工资。。。orz
最后编辑深海蓝空 最后编辑于 2007-07-06 00:37:53
分享 转发
比大海更深沉的忧伤,比天空更青蓝的悠远。
TOP

回复:[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

好恐怖的东西= =
明显我是不会的= =
这些找程序员啊飘他们╭ (′▽`)╭(′▽`)╭(′▽`)╯
玛娜也应该会吧=3=
飘过= =..
=========================
话说特别想把蓝空殿拉入口古月的小说=3=
但是黄昏说很不礼貌突然把人拉入小说=3=
到底拉不拉好呢= =
好困扰呢= =...
顺带一提=3=那口古月小说里头..如果拉入了蓝空殿=3=
蓝空的能力就是...
因为
深海之蓝+深海之空=深海蓝空=3=
所以你的能力是必死病毒加什么的复合型-3-
如果加入的话就不透剧了=3=
当然这还是在这里问问比较好以免黄昏又骂了= =
毕竟和你不熟╭ (′▽`)╭(′▽`)╭(′▽`)╯

总比大和的角色好=3=
不断自残提高能力..再燃烧Y染色体=3=
飘过了
╭ (′▽`)╭(′▽`)╭(′▽`)╯
最后编辑qwe1025 最后编辑于 2007-07-06 00:42:27
…破風馳行。
…穿越數層浮雲而行。
前往到九霄雲外之處。
胸口的悸動是如此地急促。
身體雖然似乎快垮了…但我仍使盡全身的力氣…
前往那個地方…
………。
……。
...
TOP

回复:[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

影響工資....精神上支持藍空-_-,
深夜的發問,危急關頭。
我四年後,不知道能否答得到。
TOP

回复:[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

gcc内嵌汇编啊,呵呵,我一直在用。
个人感觉......语法非常混乱....|||||||||||||||

使用asm inline的方式是可以的,具体格式如下:

asm(<汇编指令块> : <输入参数> : <输出参数> : <更改寄存器表>);

其中汇编指令块就是指令的列表,格式如下:

指令1 输入参数, ..., 输出参数;
指令2 输入参数, ..., 输出参数;

* 注意:
1. 指令参数的顺序和intel汇编是相反的。(输入在前,输出在后)
2. 数字前面要加$
3. 寄存器名前面用%
4. 如果要使用C变量,寄存器的前缀还要改...||||

举例:

将1赋给eax
asm("mov $1,%eax");

将dx赋给cx
asm("mov %dx, %cx");

扫描C变量test中的第一个标志位,并将编号放到eax
asm("bsf %0, %%eax" : :"m"(test));
解释:
1. 传入了一个C参数,因此用%0表示"第0个参数"
2. 因为一个%被C参数使用了,因此寄存器表示变成了两个%
3. 参数是输入用的,因此放在第二个:后面
4. m的意思是,这个参数是放在内存中的 (如果是放在寄存器里面的,用r表示)

调用rdtsc指令
asm(“rdtsc" : : : "eax", "edx");
解释:
1. 这样写没有什么意义,主要是为了解释更改寄存器表用法
2. 这条指令将64位的CPU指令计数器值放入eax, edx中。
2. 更改寄存器表中给出"eax", "edx"是为了告诉编译器"eax和edx中的值发生了改变";
因为两个寄存器没有明确的在汇编块中出现,编译器可能意识不到这两个寄存器变了,这样程序可能出错。

另外,建议在asm后面加关键字volatile,这样告诉编译器"这里面的东西都要原封不动!"
不然的话,编译器可能自作聪明的将你的汇编的某些指令"优化掉",造成程序死得很难看。
我就遇到过,把我的一个pop指令吃了,结果函数一返回就segfault... >_<


最后再一个稍微复杂点的例子吧:

// 测试变量的一个位是否标记(可以用在if条件中)
static inline int BitTest(register unsigned int R32, register unsigned int Idx)
{
int Ret;
asm volatile ("btl %1, %2;"
                  "sbbl %0, %0"
                  : "=r"(Ret)
                  : "Ir"(Idx), "r"(R32));
return Ret;
}

// 从一个bitmap中取得一个已经标记的位的编号,并且将这个位重置
// 如果没有位标记了,返回-1
#define BitFetch64(M64, Index)                  \
asm volatile ("movl $-1, %0;"                  \
              "bsfq %1, %%rax;"                \
              "jz 1f;"                        \
              "btrq %%rax, %1;"                \
              "movl %%eax, %0;"                \
              "1:"                            \
              : "=Jr"(Index), "=m"(M64)        \
              : : "cc", "rax")


这里仅仅是简单介绍一下,要获得详细资料,google关键字: gcc inline assembly howto

-----------------
还有一个问题,就是怎么在c里定义一个指针,指向一个绝对的物理地址。
比如 *p = 0xfff10010;我的编译器还是不吃orz
其实需要的是一个指针指向这里,然后同时传四个参数,
茅盾的是,如果用方程指针,是可以传参数了,但是方程指针只能指向一个自定义的方程,不能让他指向一个地址。
如果用一般指针,就像上面问的,也许能指向地址,但是指针不能当方程用,无法传参数。
我知道这些想法和语言的基本原理不合,
按理说,把四个参数传到一个地址这件事本身就没法解释,但是实际问题就是如此需要。。。orz


你想说的是调用某个地址的函数吧。
函数指针应该可以赋值,但是需要cast一下,比如:
*(int*)p = 0xfff10010;

觉得麻烦的话,就自己调用吧,注意目标函数使用的calling convention
如果我没有记错,一般的调用参数是push到stack上的:
push 参数1;
push 参数2;
push 参数3;
push 参数4;
call 地址;
如果register调用的话,第一个参数放在eax,第二个edx,第三个ecx,后面的放在stack上。
最后编辑Prz 最后编辑于 2007-07-06 02:05:30
飛べない翼に、意味はあるんでしょうか?
TOP

回复:[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

多谢><

其实我刚才也找到了GCC inline assembly 的 guide
就是用google: gcc inline assembly howto。。。orz
但是我需要运行的是intel的内部汇编,基于ia64, 我不知道gcc可不可以编译
所以我才想到最好是分开来都编译成obj然后再link,
都成binary了也就没什么语言问题了
而且我的这段汇编有很长,inline可能不好办。

这个基本上是要运行的汇编

http://www.gelato.unsw.edu.au/lxr/source/arch/ia64/kernel/pal.S

里面像方程一样,有很多GLOBAL_ENTRY, 我需要根据不同需要分别access them

但是就是不知道怎么从c access asm, 怎么access这些GLOBAL_ENTRY。。。

我先试试楼上的方法,看看能不能编译><
比大海更深沉的忧伤,比天空更青蓝的悠远。
TOP

回复:[技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><

IA64 .... ||||| 没玩过这么高级的东西....
不过gcc的话,应该是支持的。(不过gcc好像仅仅做基本语法检查,然后交给as作机器码编译的)
飛べない翼に、意味はあるんでしょうか?
TOP

回复: [技术求助]如何能在c中召唤汇编并传递参数,然后汇编运行完再返回c.><


汇编……不好意思,堕落了

不过,提供一种规避的思路,偶以前某多媒体课程曾经要做的,偶用不惯Matlab,只用于计算数据,思路就是在文件上和VC就是这样交互的

实在没办法在程序中用Module的方式来做的话,也许可以
  1. VC得到参数,然后写到内存,调用汇编(打开编译出来的可执行程序)
  2.汇编中先读内存,把结果再写到内存
  3. VC在内存中读汇编的输出

要读写的话,内存中位置可以先约定。 要不可以使用文件中继


却问何日君再来...
TOP