Помогите понять инструкцию DIV в сборке x86 - PullRequest
5 голосов
/ 27 декабря 2010

Читая некоторый исходный код в проекте GNU, я наткнулся на этот фрагмент встроенной сборки:

__asm__ (
  "divq %4"
  : "=a" (q), "=d" (r)
  : "0" (n0), "1" (n1), "rm" (d)
);

Здесь переменные q, r, n0, n1 и d являются 64-разрядными целыми числами. Я знаю достаточно сборки, чтобы понять суть того, что это делает, но есть некоторые детали, в которых я не уверен.

Что я понимаю:

Мы делим содержимое регистра RAX на d, помещая частное в q, а оставшуюся часть в r.

Чего я не понимаю

  1. Почему есть три входа Вот? Нам нужно только ввести дивиденд и делитель, так что использовать может быть для 3 входов?
  2. Я не могу сказать, какой из входов является дивидендом. В общем, я ничего не вижу на самом деле загружается в регистр RAX, так откуда он знает, на что делить?

Ответы [ 2 ]

4 голосов
/ 27 декабря 2010

В спецификации входных операндов:

: "0" (n0), "1" (n1), "rm" (d)

регистры "0" и "1" принудительно устанавливаются на rax и rdx из-за спецификации вывода:

: "=a" (q), "=d" (r)

И семейство инструкций div хочет иметь числитель в RDX:RAX. Делитель может быть в регистре общего назначения (не используется иначе - т. Е. Не RAX или RDX) или в памяти, которая определяется ограничением "rm". Регистры RDX, RAX и операнд делителя составляют 3 входа.

Таким образом, в результате будет выполнено деление: n1:n0 / d, где n1:n0 - это количество, загруженное в rdx:rax.

0 голосов
/ 27 декабря 2010

Как вы правильно наблюдаете, семейство div работает с фиксированными регистрами a и d, rax и rdx для divq. Регистр a получает свои входные данные от n0, который связан с 0-м регистром, а именно a. n1 - это фиктивный вход с псевдонимом d, возможно, просто для того, чтобы этот регистр не использовался для других целей.

...