汇编 - 编译器不会看到我的内联更改?

时间:2015-02-20 19:30:23

标签: linux assembly x86-64 cpu-registers att

背景:

Linux 64。

GCC 4.8.2(-O3 -march = native)

左手下方的x86_64 abi,​​在第21页打开。

C代码:

int main (int argc, char ** argv) {

    int16_t h = atoi(argv[1]) ;
    int16_t p;

  __asm__ ("mov %2, %0\n\t"
    "rol $8,%1\n\t"          
     : "=r" (p)    /* output operands */
     : "0"(p),"g"(h)/* input operands */
     :"cc");        /* clobbered operands */

  printf("%d %d\n", h, p);
  return 0;

}

汇编代码(问题所依据的行):

    ...
    movl    $10, %edx
    movq    8(%rsi), %rdi
    xorl    %esi, %esi
    call    strtol
    xorl    %edx, %edx
    movl    $.LC0, %edi
#APP
# 1627 "test2ptr.c" 1
    movl %ax, %dx          <- set in %dx
    rol $8,%dx

# 0 "" 2
#NO_APP
    movswl  %ax, %esi
    movswl  %dx, %edx <- Then this line should not appear
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    ...

如果我评论它,结果很好。

但是我不能依赖于修改源代码(不可维护:每次在源代码中改变某些内容时,必须返回该位置以确保它仍在工作...不要去。)

问题:

为什么行movswl %dx, %edx会被保留?

它应该长篇大论。但它已经由我完成并且花了我一个多余的时钟。

有没有解决方法?

这只是我没有设定的选项吗?

由于

2 个答案:

答案 0 :(得分:1)

由于您指定了16位类型,但printf需要32位整数,因此需要对结果进行符号扩展,这就是该代码的作用。然而,如果您使用printf的正确格式,则两个版本都应生成相同的输出。

像往常一样,你不需要内联asm来进行旋转,如果你在内联中使用mov,你可能会做错了。

答案 1 :(得分:0)

确定,

所以解决方法是设置int32_t而不是int16_t。

现在代码是...... 2个cpu周期更快。

这太荒谬了。

但我现在非常喜欢装配:)