【问题标题】:Comparing numbers in inline c assembly比较内联 c 汇编中的数字
【发布时间】:2013-11-15 23:52:04
【问题描述】:

我正在尝试在 c 中感受内联汇编,而我之前从未做过任何汇编编程,所以我试图将我必须的随机代码片段转换为汇编。 我对下面的代码有问题,我想要它做的是返回 0x20 (32) 如果 a 低于 0x20 (32) 或以上 0x7e (126)。 (那是不可打印的字符)但是它也会变成字符 在这些数字之间进入 0x20 (32)

#include <stdio.h>
int foo(int a) {
  asm (
    "mov $0x20, %%ebx;"
    "cmp %%eax, %%ebx;"
    "jl l1;"
    "mov $0x7e, %%ebx;"
    "cmp %%eax, %%ebx;"
    "jg l1;"
    "jmp l2;"
    "l1: movl $0x20, %%eax;"
    "l2:;"

    : "=a" (a)
    : "a" (a)
    : "%ebx"
  );
  return a;
}
int main(void) {
  int i;
  for (i = 0; i <= 255; i++) {
    printf("%i: %i\n", i, foo(i));
  }
}

这个输出
0:32
1:32
2:32
...
31:32
32:32
33:32
34:32
35:32
...
125:32
126:32
127:32
128:32
...

【问题讨论】:

  • 函数开始时 %%eax 的内容是什么
  • 当然应该是 42 而不是 32 :-)
  • @amdixon 是a,如: "a" (a)中所说。

标签: c gcc assembly x86 inline-assembly


【解决方案1】:

代码将返回 32,因为您没有指定 else

  ...
  asm (
    "mov $0x20, %%ebx;"
    "cmp %%eax, %%ebx;" // the order should be ebx, eax
    "jl l1;"
    "mov $0x7e, %%ebx;"
    "cmp %%eax, %%ebx;" // the order should be ebx, eax
    "jg l1;"
                        // missing step here
    "jmp l2;"
    "l1: movl $0x20, %%eax;"
    "l2:;"
  ...

你无法告诉编译器变量a 将被存储在哪里,你只是将a 传递给asm。您可以将其修复为:

#include <stdio.h>
int foo(int a) {
  asm (
    "cmp $0x20, %%eax;"
    "jl l1;"
    "cmp $0x7e, %%eax;"
    "jg l1;"
    "movl $0, %%eax;"   // what should a be otherwise? 0?
    "jmp l2;"
    "l1: movl $0x20, %%eax;"
    "l2:;"

    : "=a" (a)
    : "a" (a)
    : "%ebx"
  );
  return a;
}
int main(void) {
  int i;
  for (i = 0; i <= 255; i++) {
    printf("%i: %i\n", i, foo(i));
  }
  return 0;
}

或:

#include <stdio.h>
int foo(int a) {
  asm (
    "cmp  $0x20, %0;"  // %0 => a
    "jl   l1;"
    "cmp  $0x7e, %0;"  // %0 => a
    "jg   l1;"
    "movl $0, %1;"     // what should a be otherwise? 0?
    "jmp  l2;"
    "l1:"
    "movl $0x20, %0;"  // %0 = a = 0x20
    "l2:;"
    : "=r" (a) // use r(egister)
    : "r" (a)
    :
  );
  return a;
}
int main(void) {
  int i;
  for (i = 0; i <= 255; i++) {
    printf("%i: %i\n", i, foo(i));
  }
  return 0;
}

【讨论】:

  • 输入和输出定义"a" resp。 "=a" 参考%eax。所以没关系(但不是很整洁)。
  • 并且:不需要else。 %eax 中的值已经存在。
  • @glglgl 这取决于他希望a 是什么,如果它不小于 30 或大于 127。
【解决方案2】:

我认为你很接近。或许this HOWTO可以帮到你。

本质上,你的逻辑是错误的:

#include <stdio.h>
int foo(int a) {
  asm(
    "mov $0x20, %%edx\n\t" // I use %edx because it optimizes better.
    "cmp %1, %%edx\n\t"    // I use %1 because that's more flexible.
    "jg l1\n\t"            // jg here, not jl!
    "mov $0x7e, %%edx\n\t"
    "cmp %1, %%edx\n\t"
    "jl l1\n\t"            // jl here, not jg!
    "jmp l2\n\t"
    "l1: movl $0x20, %0\n\t" // move the result to 0
    "l2:\n\t"

    : "=a" (a) // output
    : "0" (a) // input is the same
    : "%edx" // what is clobbered
  );
  return a;
}
int main(void) {
  int i;
  for (i = 0; i <= 255; i++) {
    printf("%i: %i\n", i, foo(i));
  }
}

【讨论】:

  • 嗯,我好像把jl和jg弄乱了,我的版本如果切换了就可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多