【问题标题】:Printf in inline Assembly内联汇编中的 Printf
【发布时间】:2014-07-19 13:07:03
【问题描述】:

我正在尝试编写一个内联汇编函数来交换两个值。(我正在使用扩展的 ASM 格式)

此代码有效:

#include <stdio.h>
void Exchange(int *x, int *y)
{
printf("In Exchange function: Before exchange x is: %d\n",*x);
printf("In Exchange function: Before exchange y is: %d\n",*y);

asm("xchg %%eax,%%edx\n\t" \
:"+a"(*x),"+d"(*y));

printf("In Exchange function: After exchange x is: %d\n",*x);
printf("In Exchange function: After exchange y is: %d\n",*y);


}


int main()
{
int x=20;
int y=30;
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);


return 0;
}

但是当我尝试像下面这样以完整的程序集编写它时,我得到了分段错误(核心转储)错误。

void Exchange(int *x, int *y)
{
asm("subl $8,%%esp\n\t" \
    "movl %%eax,4(%%esp)\n\t" \
    "movl %%edx,(%%esp)\n\t" \
    "call printf\n\t" \
    "addl $8,%%esp\n\t" \   
    "xchg %%eax,%%edx\n\t" \
    "subl $8,%%esp\n\t" \
    "movl %%eax,4(%%esp)\n\t" \
    "movl %%edx,(%%esp)\n\t" \
    "call printf\n\t" \
    "addl $8,%%esp\n\t" \
:"+a"(*x),"+d"(*y));

}
 int main() 
{   
int x=20;
int y=30; 
printf("In main: Before exchange x is: %d\n",x);
printf("In main: Before exchange y is: %d\n",y);
Exchange(&x,&y);
printf("In main: After exchange x is: %d\n",x);
printf("In main: After exchange y is: %d\n",y);


return 0;
}

我们不能在汇编部分使用 printf 函数吗?

【问题讨论】:

  • 查看您的第一个代码示例,是否有某些原因需要强制使用特定的 eax 和 edx 寄存器?为什么不使用 asm("xchg %0,%1" :"+r"(*x),"+r"(*y)) 让编译器选择最有效的?或者如果你真的想看人的脑袋爆炸,试试 asm("" : "=r"(*x),"=r"(*y) : "1" (*x), "0" (*y) )。看,没有代码!但它仍然有效。

标签: c assembly inline-assembly


【解决方案1】:

您的 asm 代码使用两个整数参数调用 printf —— 没有格式字符串。所以它试图取消引用第一个整数作为指向格式字符串的指针并崩溃。

此外,调用 printf 将破坏 %eax 和 %edx 中的值,因为它们不会在标准 x86 调用约定中的调用中保留。

【讨论】:

猜你喜欢
  • 2012-10-20
  • 2020-06-06
  • 2013-11-26
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多