日期:2014-05-16  浏览次数:20646 次

怎么没人进呢?请高手进来看一下吧,你应该不会后悔进的,虽然标题写的不吸引人。所以把原标题去了
就是这段代码在linux下可编译通过,但执行时收到段错误信号。SIGSEGV
但在win下用相同的逻辑重写这段代码是ok的。
这段代码是用来测试ljmp 功能的,为什么不行呢? 望高手不吝赐教,万分感谢!
int main()
{
  unsigned long a[2] = {0,0};
  __asm__("push 1f;"
  "popl %0;"
  "push %%cs;"
  "popl %1;"
  "andl $0x000000ff,%1;" /*改成 "andl $0x0000ffff,%1;" 仍然不行*/
  "ljmp *%2;"
  "1:"
  :"=m" (a[0]), "=m" (a[1])
  :"m" (*(char*)&a[0]));

  return 0; 
}

------解决方案--------------------
因为你在"push 1f"压入的不是1:这个地址,而是1:这个地址上所存放的内容,也就是return 0;代码翻译成的指令mov $0x0, %eax,也就是b8 00 00 00 00。
所以在a[0]中存放的就是0x000000b8,所以最后ljmp时总是试图跳转到0x000000b8这个地址去,所以一定会SIGSEGV错误。
这完全是gcc内嵌汇编的问题,你在windows下写的时候不出错也很正常。

要改正的话,只需要把"push 1f;"改为"push $1f;"即可。

另外,gcc内嵌汇编一般分隔指令会用"push $1f\n"的形式,这样在看汇编出来的代码时会规整很多。