在内联c程序集中比较数字

时间:2021-02-17 03:13:30

I'm trying to get a feel for inline assembly in c, and I have never done any assembly programming before, so I'm trying to convert random pieces of code I have to assembly. I got a problem with the code below, what I wanted it to do was returning 0x20 (32) if a is below 0x20 (32) or above 0x7e (126). (thats unprintable characters) However it also turns the characters between those numbers into 0x20 (32)

我试着感受一下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));
  }
}

This outputs
0: 32
1: 32
2: 32
...
31: 32
32: 32
33: 32
34: 32
35: 32
...
125: 32
126: 32
127: 32
128: 32
...

输出0:32 1:32 2:32…31: 32: 32: 32: 32: 32: 32: 32: 32: 32…125: 32 126: 32 127: 32: 128: 32…

2 个解决方案

#1


0  

I think you are quite close. Maybe this HOWTO can help you.

我想你已经很接近了。也许这个方法可以帮助你。

Essentially, you have the logic wrong:

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

#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));
  }
}

#2


1  

The code will returns 32 since you didn't specify else:

代码将返回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:;"
  ...

you can't tell the compiler where the variable a is going to be stored, you just passed a to asm. You can fix it as:

你不能告诉编译器变量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;
}

or:

或者:

#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;
}

#1


0  

I think you are quite close. Maybe this HOWTO can help you.

我想你已经很接近了。也许这个方法可以帮助你。

Essentially, you have the logic wrong:

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

#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));
  }
}

#2


1  

The code will returns 32 since you didn't specify else:

代码将返回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:;"
  ...

you can't tell the compiler where the variable a is going to be stored, you just passed a to asm. You can fix it as:

你不能告诉编译器变量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;
}

or:

或者:

#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;
}