В настоящее время я изучаю язык ассемблера x86 и задаюсь вопросом, что является лучшим способом для реализации циклов. Один из способов состоял бы в том, чтобы переместить значение в регистр ecx и использовать инструкцию цикла, а другой способ - использовать инструкцию jmp, а затем - тело цикла, а затем условное переключение в конечном итоге в начало тела цикла. Я предполагаю, что первый из них будет иметь лучшую читаемость, но в других случаях я не знаю, зачем его использовать.
X86 с помощью команды ecx и loop по сравнению с jmp + j <условие>
Ответ 1
Когда вы упоминаете тест jmp + body +, я считаю, что вы говорите о переводе цикла while
на языках высокого уровня. Существует причина для второго подхода. Давайте посмотрим.
Рассмотрим
x = N
while (x != 0) {
BODY
x--
}
Наивный способ
mov ecx, N ; store var x in ecx register
top:
cmp ecx, 0 ; test at top of loop
je bottom ; loop exit when while condition false
BODY
dec ecx
jmp top
bottom:
У этого есть N условных прыжков и N безусловных переходов.
Второй способ:
mov ecx, N
jmp bottom
top:
BODY
dec ecx
bottom:
cmp ecx, 0
jne top
Теперь мы все еще выполняем N условных переходов, но делаем только ОДИН безусловный переход. Небольшая экономия, но это может иметь значение, особенно потому, что она находится в цикле.
Теперь вы упоминали инструкцию loop
, которая по существу
dec ecx
cmp ecx, 0
je somewhere
Как бы вы это работали? Наверное, вот так:
mov ecx, N
cmp ecx, 0 ; Must guard against N==0
je bottom
top:
BODY
loop top ; built-in dec, test, and jump if not zero
bottom:
Это довольно малое решение, типичное для процессоров CISC. Это быстрее, чем второй способ выше? Это многое зависит от архитектуры. Я предлагаю вам провести некоторое исследование производительности команды loop
в архитектурах IA-32 и Intel 64, если вы действительно хотите узнать больше.