Я решаю проблему в книге под названием «Компьютерные системы». Вот проблема, с которой я борюсь.
Вопрос: Следующий код вычисляет 128-битное произведение двух 64-битных значений со знаком x и y и сохраняет результат в памяти:
1 typedef __int128 int128_t;
2
3 void store_prod(int128_t *dest, int64_t x, int64_t y){
4 *dest = x * (int128_t) y;
5 }
Gcc генерирует следующий ассемблерный код, реализующий вычисления:
1 store_prod:
2 movq %rdx, %rax
3 cqto
4 movq %rsi, %rcx
5 sarq $63, %rcx
6 imulq %rax, %rcx
7 imulq %rsi, %rdx
8 addq %rdx, %rcx
9 mulq %rsi
10 addq %rcx, %rdx
11 movq %rax, (%rdi)
12 movq %rdx, 8(%rdi)
13 ret
Этот код использует три умножения для арифметики с множественной точностью, необходимой для реализации 128-битной арифметики на 64-битной машине. Опишите алгоритм, используемый для вычисления продукта, и аннотируйте код сборки, чтобы показать, как он реализует ваш алгоритм.
Я пытался аннотировать каждый код сборки. Но я полностью потерян из 4-й инструкции. Я понял, как работает каждый ассемблерный код, но в процессе их объединения я потерян.
1 store_prod:
2 movq %rdx, %rax // copy y to rax
3 cqto // sign-extend to upper 8 bytes of rax
4 movq %rsi, %rcx // copy x to rcx
5 sarq $63, %rcx // right arithmetic shift 63 times (why..?)
6 imulq %rax, %rcx // multiply rcx by rax (why..?)
7 imulq %rsi, %rdx // multiply rdx by x (why..?)
8 addq %rdx, %rcx // add rdx to rcx (why..?)
9 mulq %rsi // multiply by x [rax = x*y]
10 addq %rcx, %rdx // add rcx to xy (why..?)
11 movq %rax, (%rdi) // store rax at dest
12 movq %rdx, 8(%rdi) // store rdx at dest+8
13 ret //
Извините за мой ломаный английский, надеюсь, вы поняли, что я говорю.