Я очень новичок в x86 и пытаюсь написать программу, которая вычисляет целочисленный квадратный корень из числа, постепенно строя его от наиболее значимого к наименее значимому. Единственные рабочие регистры, которые у меня есть, это% rax,% rcx,% rdx,% rdi,% rsi,% r8,% r9,% r10 и% r11. Мне не разрешено использовать какие-либо другие. Я не совсем уверен, как скопировать значение из% edi в регистр r, а затем, когда все вычисления будут завершены, повторно скопировать это значение из регистра r обратно в% eax для возврата.
Переменные:% edi содержит аргумент x (32-разрядный без знака). % eax будет содержать возвращаемое значение
Это весь код, который у меня есть, я уверен, что он полон ошибок, я новичок в этом.
.globl sqrt
sqrt:
movl $0, %eax #initializing return to 0
movslq %edi, %rdi #moving edi into rdi, not sure if this works
movq $0, %rax #initializing scratch return to 0
movq $15, %rcx #initializing loop counter to 15(start at 15th bit)
movq $0x80000, %rbx #creating bit mask (1000 0000 0000 0000)
loop:
xorq %rax, %rcx #set specific bit to 1 in rcx
pushq %rax #temporarily store rax value in stack
mulq %rax #rax=rax*rac
cmpq %rax, %rdi #rax<=rdi
popq %rax #restore original rax value
jbe keep_bit #keep bit if rax<=rdi
xorq %rax, %rcx #unset bit in rax if rdi>rax
keep_bit:
shr $1, %rcx #shift to the next bit
jnz loop #continue to loop until all bits are tried
Я знаю, что мне нужна строка, чтобы загрузить значение% rax обратно в% eax, но я не уверен, как это сделать
mov $15, %rcx
), вы можете сразу переместить 32-битный регистр (mov $15, %ecx
), так как это очистит старшие 32 бита. Чтобы обнулить регистр, используйтеxorl
(тот же принцип сmov
s выше) и, наконец, я считаю, что вам не нужно обрабатывать воображаемые результаты, поэтому можно с уверенностью предположить, что ввод беззнаковый, и поэтомуmovzlq %edi, %rdi
более подходит (или эквивалентmov %edi, %edi
) - person Margaret Bloom   schedule 28.09.2017%rbx
вызывающего абонента, не сохраняя / не восстанавливая его. Но вы никогда не используете указанную вами константу0x80000
. Кроме того, вы можете использоватьimul %rcx, %rax
, поскольку вам не нужен результат с высокой половиной в%rdx
. (вашmul
квадратrax
; я думаю, вы хотитеmul %rcx
. Пошаговый код вgdb
; см. нижнюю часть stackoverflow.com/tags / x86 / info) Вы также можете использовать другой регистр вместо push / pop внутри цикла! - person Peter Cordes   schedule 28.09.2017double
и использоватьsqrtsd
, а затем преобразовать обратно в целое число. Это было бы намного быстрее, чем цикл; всего 3 инструкции: godbolt.org/g/taEYGi - person Peter Cordes   schedule 28.09.2017eax
vs.rax
иedi
vs.rdi
является дубликатом некоторых существующих вопросов о подмножествах регистров. - person Peter Cordes   schedule 28.09.2017rax*rax
, опечатка была в комментарии. Эта реализация сбивает с толку (а также является медленной), потому что она использует%rax
для двух разных вещей внутри цикла с использованием push / pop. (Я раньше не видел алгоритм и не был уверен, есть ли у него больше ошибок или нет). См. stackoverflow.com/questions/46481471/ для последующего вопроса об имени алгоритма, который представляет собой чистую версию псевдокода. Кстати, вы можете использоватьbts
/btr
вместо смещения маски. - person Peter Cordes   schedule 29.09.2017