2016-09-13 13 views
0

Задача из старого экзамена (я могу предоставить источник, если вы не верите мне):Измените этот короткий код на ассемблере, так что работает только без регистра индексированные

Изменить следующий код на ассемблере без использования регистров индексной адресации , Не используйте более 4 инструкций.

mov eax, [ebx+8] 
add eax, 1 
add ebx, 8 
mov [ebx], eax 

Я изменил, что:

mov eax, [ebx] 
add eax, 9 
add ebx, 8 
mov [ebx], eax 

Я не могу себе представить, что это сделано так легко, поэтому я не уверен: D

, если это так, что я сделал такой альтернативой be:

mov eax, [ebx] 
add eax, 1 
add ebx, 16 
mov [ebx], eax 

Или это теперь совершенно неправильно? Большое вам спасибо!

Edit: Исправленная версия:

mov eax, [ebx] 
add [ebx], 9 
add ebx, 8 
mov [ebx], eax 

сейчас?

+0

Это совершенно неправильно. Вы читаете неправильное местоположение в своем первом решении, а также читаете и записываете неправильные местоположения во втором месте. –

+0

О, это больно, хорошо спасибо за быстрый комментарий! Позвольте мне попытаться исправить это. –

+0

, если ebx = 1000, тогда 'mov eax, [ebx + 8]' загружает eax с 32b значением из адреса 1008. Ваш 'mov eax, [ebx]' будет загружать eax с 32b значением из адреса 1000. Если я понимаю, что правильность формулировки задачи, то это в каком-то смысле меньше, чем в первой попытке. – Ped7g

ответ

2

Прежде всего, ни один из режимов адресации в оригинале не использует индексный регистр. [ebx+8] может (и будет) использовать EBX в качестве базового регистра, а не индексный регистр, поскольку он может сделать это без байта SIB в кодировке машинного кода. Таким образом, режим адресации база + disp8, так что кодирование ModRM байт будет (в двоичной системе)

  • Mod = 01 (основание + disp8)
  • R/M = 011 (EBX)
  • REG = 000 (EAX в качестве места назначения регистра)

Таким образом, байт ModRM будет 0x43, согласно Таблица 2-2. 32-битные формы адресации с байтом ModR/M, в справочном руководстве по набору инструкций Intel (том 2). (См. Wiki для ссылок на файлы PDF).

Если на EBX был коэффициент масштабирования (например, [ebx*2 + 8]), ему пришлось бы использовать режим адресной адресации disp32 +. (См. Также x86 addressing modes).


Предположительно, вы фактически имеете в виду, что вы не можете использовать перемещение в режиме адресации.

В этом случае первой инструкцией не может быть нагрузка, поскольку вам необходимо сначала вычислить адрес в регистре. Вопрос облегчает вам, позже вычисляя то же самое значение ebx+8, которое вам нужно в качестве адреса, используя инструкцию ADD. Таким образом, вы можете просто изменить порядок, вместо того, чтобы дважды изменять EBX.

add ebx, 8 
mov eax, [ebx] 
add eax, 1 
mov [ebx], eax 

или медленнее, но меньше инструкции:

add ebx, 8 
add dword [ebx], 1  ; read-modify-write 
mov eax, [ebx]   ; and then reload 

x86 имеет много странных и прекрасных инструкций, в том числе XADD. Можно даже сделать это:

      ; LEA ebx, [ebx+8] might count as breaking the rules, even though it's not a load. 
sub ebx, -8    ; use a different instruction just for variety. 
mov eax, 1 
xadd dword [ebx], eax  ; read-modify-write, leaving the old value in eax 
inc eax     ; do the same add again, so the register matches what xadd put into memory. 

Но не делайте этого. XADD медленнее, чем обычные простые инструкции. Основной целью является многопоточная синхронизация. C++ 11's std::atomic::fetch_add - это та же самая операция, которую реализует XADD, поэтому fetch_add() может эффективно скомпилировать x86 до lock xadd.