【发布时间】:2019-12-26 12:32:57
【问题描述】:
得到以下函数来进行乘法、除法和求余数:
#define IS_EQUAL(var_, const_) ((INT32)(var_) == (INT32)(const_))
// all these functions must use hexadecimals as constants according to syllabus
static inline INT32
math_qmultiply (INT32 num1, INT32 num2)
{
INT32 retval = 0x0,
count = 0x0;
while (num2)
{
if (IS_EQUAL ((num2 & 0x1), 0x1))
{
retval += num1 << count;
}
count++;
num2 = num2 >> 1;
}
return retval;
}
static inline INT32
math_qdivide (INT32 num1, INT32 num2)
{
if (!num1)
{
return 0x0;
}
if (!num2)
{
return INT_MAX;
}
INT32 neg_result = FALSE;
if (num1 < 0x0)
{
num1 = -num1;
if (num2 < 0x0)
{
num2 = -num2;
}
else
{
neg_result = TRUE;
}
}
else if (num2 < 0x0)
{
num2 = -num2;
neg_result = TRUE;
}
INT32 quotient = 0x0;
while (num1 >= num2)
{
num1 -= num2;
quotient++;
}
if (neg_result)
{
quotient = -quotient;
}
return quotient;
}
static inline INT32
math_qmod (INT32 n1, INT32 n2)
{
INT32 q = math_qdivide (n1, n2);
INT32 p = math_qmultiply (q, n2);
return n1 - p;
}
这三个函数用在下面的函数中:
static inline INT32
find_actual_x_for_char_idx (const INT32 char_idx)
{
INT32 t1 = math_qdivide (char_idx, FRAME_COLS_COUNT);
register INT32 divisor = math_qmultiply (FRAME_COLS_COUNT, t1);
INT32 t2 = math_qmod(char_idx, FRAME_COLS_COUNT);
register INT32 x = !t2 ? 0x0 : char_idx - divisor;
return FRAME_TOP_LEFT_X + x;
}
这个函数产生正确的输出并且工作正常。
当我将先前函数的代码更改为这样时,问题就开始了:
INLINE_ATTRIB INT32
math_qmultiply (INT32 n1, INT32 n2)
{
INT32 res = 0x0;
asm volatile(
"mov eax, %1;"
"mov ebx, %2;"
"mul ebx;"
"mov %0, eax;"
: "=r" (res)
: "g" (n1),
"g" (n2)
);
return res;
}
INLINE_ATTRIB INT32
math_qdivide (INT32 n1, INT32 n2)
{
INT32 res = 0;
asm volatile(
"mov eax, %1;"
"mov ebx, %2;"
"xor edx, edx;"
"div ebx;"
"mov %0, eax;"
: "=r" (res)
: "g" (n1),
"g" (n2)
);
return res;
}
INLINE_ATTRIB INT32
math_qmod (INT32 n1, INT32 n2)
{
INT32 res = 0;
asm volatile
("mov eax, %1;"
"mov ebx, %2;"
"xor edx, edx;"
"div ebx;"
"mov %0, edx;"
: "=r" (res)
: "g" (n1), "g" (n2)
);
return res;
}
现在我总是 SEGMENTATION FAULT,但当我分别检查这些函数时,它们会正确地进行除法、乘法和求余数。您能告诉我导致 SEGMENTATION FAULT 的原因吗?
【问题讨论】:
-
您不应该在编译器背后更改寄存器。将它们列为已破坏或使用适当的约束(推荐)。也不需要为此使用内联汇编。
-
可能是 ebx 的垃圾处理导致了这种情况。
-
@Jester 任务是使用 asm 来完成
-
@ronni_lao 当然可以,但正如 Jester 所说,您需要告诉 gcc 您修改了哪些寄存器。
标签: c gcc assembly x86 inline-assembly