【发布时间】:2020-10-26 07:09:54
【问题描述】:
我想用上面的cmov函数实现的结果是,如果pred=true,返回t_val,否则返回f_val。但是在实际操作中,每次都会返回t_val。
#include<stdio.h>
#include <stdint.h>
#include <stdlib.h>
int cmov(uint8_t pred, uint32_t t_val, uint32_t f_val) {
uint32_t result;
__asm__ volatile (
"mov %2, %0;"
"test %1, %1;"
"cmovz %3, %0;"
"test %2, %2;"
: "=r" (result)
: "r" (pred), "r" (t_val), "r" (f_val)
: "cc"
);
return result;
}
int main() {
int a=1,b=4,c=5,d;
int res = (a==3); //
printf("res = %d\n",res);
d = cmov(res,b,c);
printf("d = %d\n",d);
a=3;
res = (a==3);
d = cmov(res,b,c);
printf("d = %d\n",d);
return 0;
};
【问题讨论】:
-
因为您两次都传递了非零的
b,所以z条件为假。如果不清楚,请使用调试器单步执行 asm。这似乎真的很低效;对输出使用"+r"约束,因此您不需要在asm 模板中使用mov;让编译器为您完成result=t_val。test %2,%2之后 cmoz 也无所作为;你甚至没有使用 GCC6 标志输出操作数。 -
test %2 %2 用于刷新标志位,防止部分信息泄露。第一次传入的res为0,第二次传入的res为1。这个在printf信息中可以看出。 b 非零会影响它吗?不是用 res 做选择吗?
-
哦,是的,您将
res作为第一个参数传递的令人困惑的杂乱示例实际上是谓词,而不是结果。用可能的解释修正了我的答案:缺少早期破坏声明。不过,“泄露信息”毫无意义;如果攻击者可以看到 FLAGS 值,他们就可以看到寄存器值,并且谓词仍在寄存器中。
标签: c assembly x86 inline-assembly