<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=101328&amp;view=findpost&amp;p=769325</guid>
        <pubDate>Wed, 06 Jul 2005 11:29:16 +0000</pubDate>
        <title>Изучаем ассемблер. Часть 1</title>
        <link>https://forum.sources.ru/index.php?showtopic=101328&amp;view=findpost&amp;p=769325</link>
        <description><![CDATA[miksayer:  <br>
<div class='tag-align-center'><span class='tag-size' data-value='13' style='font-size:13pt;'><span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>Изучаем ассемблер. Часть 1</strong></span></span></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Предисловие</strong></span></span></div><br>
С этой статьи я начинаю цикл статей «Изучаем Ассемблер». Основная идея состоит в том, что я знаю ассемблер не лучше вас и я как бы изучаю ассемблер вместе с вами. Предполагается, что вы уже хотя бы немного знакомы с любым языком программирования. Итак, начнем&#33;<br>
<br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Основы</strong></span></span></div><br>
Какой компилятор выбрать? Компиляторов ассемблера существует очень много. Самые популярные из них: MASM, TASM, FASM, NASM. Большинство примеров будет на MASM’е, но большинство компиляторов мало чем отличаются по синтаксису. Скачать MASM можно на http://www.masm32.cjb.net/. Вместе с MASM поставляется редактор для него. Перед тем, как компилировать программу нужно ее сохранить(File-&gt;Save). Теперь можно откомпилировать(Project-&gt;Build All). Чтобы запустить вашу программу нажмите Project-&gt;Run Program.<br>
Теперь о структуре программы. Вот «скелет» стандартной программы:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">.386 </div><div class="code_line">&nbsp;</div><div class="code_line">.model flat, stdcall </div><div class="code_line">option casemap :none </div><div class="code_line">&nbsp;</div><div class="code_line">;подключение библиотек,необходимых нам</div><div class="code_line">include \MASM32\INCLUDE\windows.inc</div><div class="code_line">include \MASM32\INCLUDE\masm32.inc</div><div class="code_line">include \MASM32\INCLUDE\gdi32.inc</div><div class="code_line">include \MASM32\INCLUDE\user32.inc</div><div class="code_line">include \MASM32\INCLUDE\kernel32.inc</div><div class="code_line">includelib \MASM32\LIB\masm32.lib</div><div class="code_line">includelib \MASM32\LIB\gdi32.lib</div><div class="code_line">includelib \MASM32\LIB\user32.lib</div><div class="code_line">includelib \MASM32\LIB\kernel32.lib</div><div class="code_line">&nbsp;</div><div class="code_line">;раздел, где объявляются все константы</div><div class="code_line">.const</div><div class="code_line">&nbsp;</div><div class="code_line">;раздел, где объявляются переменные, уже имеющие какое-то значение</div><div class="code_line">.data</div><div class="code_line">&nbsp;</div><div class="code_line">;раздел, где объявляются переменные, еще не имеющие значения</div><div class="code_line">.data?</div><div class="code_line">&nbsp;</div><div class="code_line">.code</div><div class="code_line">start: ;с этого слова начинается код программы</div><div class="code_line">invoke ExitProcess,0</div><div class="code_line">end start ;с этого слова заканчивается код программы</div><div class="code_line">&nbsp;</div><div class="code_line">Советую сохранить этот «скелет» в отдельном файле для удобства. В большинстве наших программ мы будем использовать функции WinAPI. Давайте напишем программу, которая будет выводить всплывающее окно с каким-либо сообщением. Для вывода этого окна мы будем пользоваться функцией MessageBox:</div><div class="code_line">&nbsp;</div><div class="code_line">.386</div><div class="code_line">&nbsp;</div><div class="code_line">.model flat, stdcall </div><div class="code_line">option casemap :none </div><div class="code_line">&nbsp;</div><div class="code_line">include \MASM32\INCLUDE\windows.inc</div><div class="code_line">include \MASM32\INCLUDE\masm32.inc</div><div class="code_line">include \MASM32\INCLUDE\gdi32.inc</div><div class="code_line">include \MASM32\INCLUDE\user32.inc</div><div class="code_line">include \MASM32\INCLUDE\kernel32.inc</div><div class="code_line">includelib \MASM32\LIB\masm32.lib</div><div class="code_line">includelib \MASM32\LIB\gdi32.lib</div><div class="code_line">includelib \MASM32\LIB\user32.lib</div><div class="code_line">includelib \MASM32\LIB\kernel32.lib</div><div class="code_line">&nbsp;</div><div class="code_line">.data</div><div class="code_line">message db &quot;Sources.RU Magazine&quot;,0 ;переменная с сообщением </div><div class="code_line">mestitle db &quot; Sources.RU Magazine &quot;,0 ;переменная с заголовком</div><div class="code_line">&nbsp;</div><div class="code_line">.code</div><div class="code_line">start:</div><div class="code_line">invoke MessageBox,0,ADDR message,ADDR mestitle,MB_OK ;выводим сообщение</div><div class="code_line">invoke ExitProcess,0 ;завершаем программу</div><div class="code_line">end start</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Как можно увидеть в примере, все API-функции вызываются с помощью команды invoke. Сначала нужно написать имя функции, а потом все ее параметры, то есть:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">invoke имя_функции, [параметр1, параметр2, параметр3, … …]</div></ol></div></div></div></div><br>
<br>
У многих сразу возникнет вопрос: где взять справочник по API? Я отвечу: а искать не пробовали? Но если все-таки не нашли, то я пользуюсь API-Guide(<a class='tag-url' href='http://www.allapi.net/' target='_blank'>http://www.allapi.net/</a>). Это справочник по API для VB, но он подходит и для ассемблера. А вообще сети их полно, просто нужно хорошо поискать. <br>
<br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Математика</strong></span></span></div><br>
На любом языке программирования высокого уровня, чтобы сложить два числа нужно сделать что-то вроде этого:<br>
<br>
переменная=число1 + число2<br>
<br>
В ассемблере все по-другому. Чтобы сложить, вычесть, умножить или разделить два числа он использует не переменные, а регистры процессора. Регистр процессора – это как бы переменные, которые находятся в процессоре. Вот таблица с основными регистрами:<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">EAX</span> используется для сохранения числа и для счета<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">ECX</span> используется для счета<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">EDX</span> сохраняет остаток от деления <br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">EBX</span> может быть использован для всего<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">ESI</span> используется для управления строками<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">EDI</span> также используется для управления строками<br>
И таблица с основными операторами, которые используются для счета:<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">MOV EAX,число1</span> копирует число1 в регистр EAX<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">ADD EAX,число1</span> прибавляет к содержимому EAX число1<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">SUB EAX,число1</span> отнимает от содержимого EAX число1<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">MUL регистр1</span> используется для умножения, умножает содержимое регистр1 на число, которое всегда хранится в EAX и сохраняет результат в EAX<br>
<span class="tag-color tag-color-named" data-value="red" style="color: red">DIV регистр1</span> Делит содержимое EAX на содержимое регистр1 и сохраняет результат в EAX<br>
<br>
Вообще все арифметические операции в ассемблере производятся между регистром и аккумулятором, то есть регистром EAX. В операторах MUL и DIV только один параметр, потому что ассемблер сразу знает, что второе число хранится в EAX. Но почему же в операторах SUB и ADD два параметра, а не один? Об этом мы поговорим позже после того, как рассмотрим пример в конце статьи. <br>
Теперь немного подробнее об арифметике. В регистре EDX всегда хранится остаток от деления и вы должны запомнить, что перед делением нужно обязательно очистить этот регистр. Это можно сделать так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">MOV EDX,0</div></ol></div></div></div></div><br>
или так:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">XOR EDX,EDX</div></ol></div></div></div></div><br>
Между этими двумя способами нет никакой разницы, но второй способ быстрее. Привожу пример программы, вычисляющей число 7*30-40*2:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; в программе есть то, о чего я еще не объяснял, но я объясню вам это позже</div><div class="code_line">.386</div><div class="code_line">&nbsp;</div><div class="code_line">.model flat, stdcall </div><div class="code_line">option casemap :none </div><div class="code_line">&nbsp;</div><div class="code_line">include \MASM32\INCLUDE\windows.inc</div><div class="code_line">include \MASM32\INCLUDE\masm32.inc</div><div class="code_line">include \MASM32\INCLUDE\gdi32.inc</div><div class="code_line">include \MASM32\INCLUDE\user32.inc</div><div class="code_line">include \MASM32\INCLUDE\kernel32.inc</div><div class="code_line">includelib \MASM32\LIB\masm32.lib</div><div class="code_line">includelib \MASM32\LIB\gdi32.lib</div><div class="code_line">includelib \MASM32\LIB\user32.lib</div><div class="code_line">includelib \MASM32\LIB\kernel32.lib</div><div class="code_line">wsprintfA PROTO C :DWORD,:VARARG</div><div class="code_line">wsprintf equ &#60;wsprintfA&#62;</div><div class="code_line">&nbsp;</div><div class="code_line">.data</div><div class="code_line">bufferforstring db 10 dup(0)</div><div class="code_line">titlestring db &quot;Результат&quot;,0</div><div class="code_line">szformat db &quot;%u&quot;,0</div><div class="code_line">&nbsp;</div><div class="code_line">.code</div><div class="code_line">&nbsp;</div><div class="code_line">start:</div><div class="code_line">mov eax,7 ;заносим в EAX 5</div><div class="code_line">mov ecx,30 ;заносим в ECX 25</div><div class="code_line">mul ecx ;умножаем EAX на ECX</div><div class="code_line">mov ebx,eax ;заносим содержимое EAX в EBX</div><div class="code_line">mov eax,40 ;заносим в EAX 40</div><div class="code_line">mov ecx, 2 ;заносим в ECX 2</div><div class="code_line">mul ecx ;заносим в ECX 2</div><div class="code_line">sub ebx,eax ;отнимаем от EBX EAX</div><div class="code_line">invoke wsprintf,addr bufferforstring,addr szformat,eax</div><div class="code_line">invoke MessageBox,0,ADDR bufferforstring,ADDR titlestring,MB_OK ;выводим резульат</div><div class="code_line">invoke ExitProcess,0</div><div class="code_line">end start</div></ol></div></div></div></div><br>
Помните, как я обещал объяснить, почему в mul и div один параметр, а в sub и add их два? На самом деле ответ прост. Вспомните правила арифметики. Ведь умножение и деление должно производится раньше, чем сложение и вычитание&#33; То есть, чтобы решить наше выражение(7*30-40*2), нужно где-то хранить результат 7*30 и 40*2, EAX мы использовать не можем, так как он используется в арифметических операциях. Поэтому приходится хранить результат 7*30 в EBX. Конечно, в нашем случае в операторе sub  все равно используется EAX. Но подумайте, что было бы, если бы у нас было в выражении не одна операция вычитания или сложения, а несколько? <br>
Вот и конец статьи&#33; Надеюсь, что вы все поняли, если нет, то пишите письма miksayer@mail.ru. Удачи&#33;<br>
                                                                                <em class='tag-i'>С уважением, Miksayer&#33;</em>]]></description>
        <author>miksayer</author>
        <category>Assembler FAQ</category>
      </item>
	
      </channel>
      </rss>
	