Зачем использовать ‘divl’ при делении int / unsigned int

Я тестировал этот код в X86.

void func()
{
int a, b;
unsigned int c, d;
int ret;

ret = a / b;  // This line use idivl, expected
ret = c / d;  // this line use idivl, expected
ret = a / c;  // this line use divl..., surprised
ret = c / a;  // this line use divl..., supriised
ret = a * c;  // this line use imull, expected
}

Я вставляю код сборки здесь:

func:
pushl   %ebp
movl    %esp, %ebp
subl    $36, %esp
movl    -4(%ebp), %eax
movl    %eax, %edx
sarl    $31, %edx
idivl   -8(%ebp)
movl    %eax, -20(%ebp)
movl    -12(%ebp), %eax
movl    $0, %edx
divl    -16(%ebp)
movl    %eax, -20(%ebp)
movl    -4(%ebp), %eax
movl    $0, %edx
divl    -12(%ebp)
movl    %eax, -20(%ebp)
movl    -4(%ebp), %eax
movl    %eax, -36(%ebp)
movl    -12(%ebp), %eax
movl    $0, %edx
divl    -36(%ebp)
movl    %eax, -20(%ebp)
movl    -4(%ebp), %eax
imull   -12(%ebp), %eax
movl    %eax, -20(%ebp)
leave
ret

Скажите, пожалуйста, почему для разделения между int и unsigned int используется divl, а не idivl?

2

Решение

Так как типы a а также c имеют одинаковый рейтинг конверсии, но a подписан и c без знака, a преобразуется в unsigned int до разделения, в обоих a / c а также c / a,

Таким образом, компилятор выдает беззнаковую инструкцию деления div для этих случаев (а также c / dгде оба операнда не подписаны).

Умножение a * c также является беззнаковым умножением. В этом случае компилятор может использовать подписанную инструкцию умножения imullпотому что усеченный результат одинаков независимо от того, mull или же imull используется — отличаются только флаги, и сгенерированный код их не проверяет.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]