обращаясь к ассемблеру - PullRequest
2 голосов
/ 02 марта 2010

Есть кое-что, что я не могу переварить. Я изучаю некоторый ассемблер и сейчас я в главе с адресацией. Я понимаю концепцию скобок для разыменования, но каким-то образом, когда я вижу его использование, я просто не могу понять смысл этого. Чтобы быть немного более точным, вот где началось мое замешательство:

mov al, [L1]

Здесь я предполагаю, что L1 в качестве примера представляет собой некий макрос, который впоследствии заменяется реальным адресом в машинном коде, верно?

Так что эта инструкция делает: разыменование al регистр (потому что вы вряд ли можете изменить физический адрес) и изменение значения на значение, хранящееся в L1.

Если до сих пор все в порядке:

mov [L1], al

это аналогично означало бы, что должен быть сохранен адрес (так что в этом был какой-то смысл), и вы меняете его в другом месте в памяти, верно?

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

И последнее: NASM добавляет группу 0xAA55 в мой код (эта последовательность должна завершать программу правильно?), Почему она там так много раз?

Ответы [ 3 ]

4 голосов
/ 02 марта 2010

L1 - это обычно / вероятно метка , , связанная с одним конкретным адресом в памяти. Программист определяет различные метки для своего удобства, и такие метки используются для символического представления определенного места в памяти (L1 - паршивое имя; метки обычно указывают на основную цель местоположения: скажем, PingCounter, ErrorMessage, Login и тому подобное).

Метка для 1 байта статического хранилища - это то, как компилятор C может реализовать char L1; в глобальном масштабе.


В синтаксисе NASM mov edi, L1 будет собираться в форму mov eax, imm32 mov, т. Е. Адрес метки станет 32-битным непосредственным в машинном коде. (Ассемблер не знает окончательное числовое значение, но компоновщик знает.) Помните, что в синтаксисе MASM это будет загрузка, и вам потребуется mov edi, OFFSET L1, чтобы сразу получить адрес метки.

Но mov al, [L1] будет собираться в другую инструкцию с 32-битным адресом, встроенным в машинный код в качестве адреса, на который нужно разыменовать. Эта инструкция загружает 1 байт с адреса L1 и помещает его в AL.

На языке ассемблера этот режим косвенной адресации обозначается квадратными скобками исходного или целевого операнда данной инструкции. (Но не оба: x86 поддерживает не более одного явного операнда памяти на инструкцию.)

mov al, [L1]

использует адрес, сохраненный в L1, для определения местоположения в памяти и считывает 1 байт (= 8 бит = размер регистра AL) в этом месте и загружает его в регистр AL.

  mov [L1], al

Делает это в обратном порядке. то есть, в частности, прочитайте адрес, сохраненный в L1, используйте этот адрес, чтобы найти конкретное место в памяти и сохранить там содержимое регистра AL.


При условии, что вы понимаете, что следующая информация является неполной и несколько устаревшей в отношении новых процессоров семейства x86, этот учебник по архитектуре 8086 , вероятно, очень полезен для Начните с языка ассемблера для семейства x86.
Преимущество, начиная с этой «древности ЦП» (все еще используемой на самом деле), состоит в том, что все фундаментальные концепции существуют, не обремененные новыми наборами регистров, причудливыми режимами адресации, режимами работы и другими понятиями. Большие размеры, функции и режимы новых ЦП просто вводят комбинаторный набор опций, все (большинство?) Из них полезны по-своему, но, по сути, не имеют значения для инициации.

3 голосов
/ 02 марта 2010

Трудно ответить на ваш вопрос, но я постараюсь помочь.

В сборке символ - это просто имя для адреса. В вашем источнике ассемблера L1 - это символ, определенный в другом месте, который ассемблер разрешит как смещение в памяти.

При разыменовании (используя нотацию []) вы можете разыменовать регистр (как в «mov al, [esi]») или адрес (как в «mov al, [L1]»). Оба утверждения делают одно и то же, единственное отличие состоит в том, откуда берется адрес.

Я рекомендую загрузить Документация по процессору Intel и просмотреть справочную инструкцию. Если вы не хотите перегружаться, начните читать со старого процессора x86 (скажем, 486 или старше), эта документация не совсем удобна, но иметь ее под рукой очень полезно.

Я не знаю специфики NASM, я изучал ассемблер 15 лет назад с Turbo Assembler, и эти знания все еще полезны сегодня:)

Кроме того, могу ли я предложить вам попробовать Googling для «учебника по сборке x86», вы найдете множество соответствующей документации, которая может быть полезна для вас.

1 голос
/ 02 марта 2010

о, и еще одна вещь, NASM добавляет связка 0xAA55 под моим кодом (это последовательность должна закончить программа правильная?) почему так много раз? Спасибо большое за читая это здесь ..

Я почти уверен, что это применимо, только если вы создаете загрузчик. Это «подпись загрузки». Скажем, вы записываете этот код на дискету (ваш машинный код также точно 512 байт?), Хорошо, когда вы хотите запустить компьютер с этим кодом загрузчика, BIOS будет смотреть на дискету и определять, является ли это настоящий загрузчик. Чтобы сделать это, он будет смотреть на последние два байта первого сектора дискеты, который должен быть 0xAA55, чтобы указывать, что он загрузочный .. (также, это работает так же, если вы загружаетесь с жесткого диска). или флэш-накопитель, или что-то еще. Немного отличается для компакт-дисков, потому что они имеют сектора 4096 байт)

В вашем исходном коде это похоже на последнюю строку что-то вроде $(times.. db 0xAA55 или что-то в этом роде? Если вы не собираетесь создавать загрузчик, вы можете эффективно удалить эту строку.

...