Перейти к содержанию

Не могу до конца освоить прямую/косвенную адресацию.


FHell

Рекомендуемые сообщения

Здравствуйте. Начну с примера

fstp dword ptr [edi]
// По адресу [edi] лежит, скажем, current_float
// Рядышком, в [edi+4] лежит maximum_float
// Задача записать maximum_float вместо current_float
// Как я вижу решение:
fstp dword ptr [edi]
mov [edi], [edi+4]
// Конечно, это не работает и моя проблема заключается в том, что я не понимаю почему данная запись не верна.
// Workaround1:
fstp dword ptr [edi]
push eax
  mov eax, [edi+4]
  mov [edi], eax
pop eax
// Workaroud2:
fstp dword ptr [edi]
fld dword ptr [edi+4]
fstp dword ptr [edi]

Собственно вопрос, какое решение является лучшим и почему запись вида "mov [edi], [edi+4]" не верна.

Изменено пользователем FHell
Опечатка в названии темы
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, FHell сказал:

моя проблема заключается в том, что я не понимаю почему данная запись не верна

Как насчет решить проблему, почитав документацию к интересующей тебя инструкции ассемблера?

 

2 часа назад, FHell сказал:

какое решение является лучшим

То, которое ты почему-то назвал Workaround 2, хотя по факту оно и есть правильное исходя из вышеупомянутой документации.

 

И да, кстати, что конкретно ты подразумеваешь под прямой и косвенной адресацией?

 

 

Ссылка на комментарий
Поделиться на другие сайты

Цитата

И да, кстати, что конкретно ты подразумеваешь под прямой и косвенной адресацией?

Если левый операнд edi - это прямая регистровая адресация, то [edi] - это косвенно-регистровая адресация.

Цитата

Как насчет решить проблему, почитав документацию к интересующей тебя инструкции ассемблера?

Rtfm это, безусловно, хороший совет. И я читал про команды ассемблера. Но я просто не понимаю некоторые описанные в ней моменты :)

Вот например вырезка с av-assembler:

Спойлер

При использовании этой команды следует учитывать, что имеются некоторые ограничения. А именно, инструкция MOV не может:

  • Записывать данные в регистры CS и IP.
  • Копировать данные из одного сегментного регистра в другой сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).
  • Копировать непосредственное значение в сегментный регистр (сначала нужно скопировать данные в регистр общего назначения).

ИСТОЧНИКОМ может быть один из следующих:

  • Область памяти (MEM)
  • Регистр общего назначения (REG)
  • Непосредственное значение (например, число) (IMM)
  • Сегментный регистр (SREG)

ПРИЁМНИКОМ может быть один из следующих:

  • Область памяти (MEM)
  • Регистр общего назначения (REG)
  • Сегментный регистр (SREG)

С учётом ограничений, которые были описаны выше, комбинации ПРИЁМНИК-ИСТОЧНИК могут быть следующими:


REG,  MEM
SREG, MEM
MEM,  REG
REG,  REG
SREG, REG
MEM,  IMM
REG,  IMM
MEM,  SREG
REG,  SREG

Пример использования инструкции MOV:


MOV AX, 0B800h    ; установить AX = B800h (память VGA).
MOV DS, AX        ; копировать значение из AX в DS.
MOV CL, 'A'       ; CL = 41h (ASCII-код).
MOV CH, 01001110b ; CH = атрибуты цвета (желтый текст на красном фоне).
MOV BX, 72eh      ; BX = позиция на экране = 2*(x + y*80).
MOV [BX], CX      ; [0B800h:015Eh] = CX.

По всей видимости, я упускаю какой-то важный момент. Если я думаю, что операция mov [edi], [edi+4] должна работать. Буду признателен, если вы меня "тыкните носом".

P.S. если и [edi], и [edi+4] это области памяти MEM, то почему я не могу сделать mov MEM, MEM.

 

Изменено пользователем FHell
дополнил
Ссылка на комментарий
Поделиться на другие сайты

8 часов назад, FHell сказал:

Собственно вопрос, какое решение является лучшим и почему запись вида "mov [edi], [edi+4]" не верна.

Из памяти в память напрямую писать нельзя.
нужно либо юзать регистр, утебя это:

Спойлер

push eax
  mov eax, [edi+4]
  mov [edi], eax
pop eax

 


либо стек у тебя это:

Спойлер

fld dword ptr [edi+4]
fstp dword ptr [edi]

 


Я лично предпочитаю юзать mov


 

Ссылка на комментарий
Поделиться на другие сайты

4 часа назад, FHell сказал:

почему я не могу сделать mov MEM, MEM

Потому, что архитектура процессора этого не позволяет. Ограничения, о которых написано в твоей выжимке - это ограничения архитектуры процессора. 

Представь, что у тебя есть два аквариума, отделенных друг от друга стенкой. И еще чуть подальше у тебя есть третий аквариум. Первый и второй аквариум соединены с третьим трубкой, но никак не соединены между собой. 

Дальше представь, что тебе надо немного воды из первого аквариума загнать во второй. Напомню - первый и второй аквариумы архитектурно между собой не связаны. И ты можешь из первого налить в третий, а потом

из третьего - во второй. Можешь из второго налить в третий, и из него - в первый. А потом стоишь и спрашиваешь, а почему ты не можешь налить сразу из первого во второй. И вот тебе ответ - нет между ними трубки, не предусмотрено. 

Это и есть архитектурное ограничение. Предвосхищая твой вопрос "почему до сих пор не сделали" - потому что, процессор при работе всегда копирует данные из оперативки в свою внутреннюю память - регистры и кеш, потому что сколь бы ни была память оперативная быстрой, все равно работа с ней будет медленее, чем с собственным кешем процессора. Ограничения системной шины и законов физики. Потому, если интересно, рекомендую прокопать глубже эту тему, благо, материалов в интернетах полным-полно. И да, сравнение я привел, разумеется, довольно грубое, но хорошо иллюстрирующее ответ на твоё "почему".

 

Если лень было читать всё, что выше, скажу кратко - твой вопрос выглядит как "у моего велосипеда есть два колеса, я могу на нем катиться вперед, могу катиться назад. А почему я не могу катиться вбок?"

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.