<?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=41358&amp;view=findpost&amp;p=575986</guid>
        <pubDate>Thu, 13 Jan 2005 17:15:46 +0000</pubDate>
        <title>Внешние процедуры или функции</title>
        <link>https://forum.sources.ru/index.php?showtopic=41358&amp;view=findpost&amp;p=575986</link>
        <description><![CDATA[Romtek: <span class='tag-size' data-value='10' style='font-size:10pt;'><strong class='tag-b'><span class="tag-color tag-color-named" data-value="blue" style="color: blue">&lt; Связь Паскаля с Ассемблером &gt;</span></strong></span><br>
<br>
<div class='tag-align-right'><strong class='tag-b'>Посвящается Тиkи.</strong></div><br>
<br>
<br>
   Связь Паскаля с Ассемблером реализуется как многомодульная программа, где главный модуль написан на Паскале, а вспомогательный на языке Ассемблера. Обычно, в Ассемблерном модуле реализуется часть алгоритма программы, которую выполнить в Паскале трудно или данная часть критична к времени выполнения.<br>
   В Ассемблерном модуле пишутся процедуры которые будут соответствовать процедурам или функциям Паскаля. После чего Ассемблерные модули транслируются в .obj файлы и линкуются. Линкование выполняет сам компилятор Паскаля, следовательно, правило интерфейса определяется языком, на котором написан главный модуль (т.е. Паскалем).<br>
<br>
<br>
  <strong class='tag-b'>[ Адресация. ]</strong><br>
<br>
В TP используются far и near процедуры<br>
<br>
<span class='tag-u'>Ближняя адресация используются для:</span><br>
<ul class="tag-list"><li>вызова процедур, расположенных в главном модуле.</li><li>вызова вложенных процедур</li><li>вызова процедур, описанных в implementation и не описанных в interface.</li></ul><br>
<br>
<span class='tag-u'>Дальняя адресация используются для:</span><ul class="tag-list"><li>Процедур, описанных в секции Interface {&#036;F+}<br>
      (после этой директивы все процедуры будут оформлены как дальние до директивы {&#036;F-})</li><li>или для процедур, описанных с использованием директивы FAR.</li></ul>для любых процедур с явно указанной директивой.<br>
   В пределах одного сегмента на Ассемблере можно использовать как дальнюю так и ближнюю адресацию. При этом работа программы не изменится, однако в стеке адрес возврата будет состоять из двух слов: сегмент+смещение. Если используется несколько сегментов, то процедуры должны быть описаны как дальние.<br>
<br>
<br>
     <strong class='tag-b'>[ Передача параметров. ]</strong><br>
<br>
     Параметры погружаются в стек в порядке их описания (в отличие от Си).<br>
Выход из подпрограммы осуществляется командой ret data (т.е стек очищает<br>
Ассемблерный модуль, опять таки, в отличие от Си), где data - кол-во байт,<br>
переданных подпрограмме в качестве параметров.<br>
     Ссылки (указатели) в Паскале всегда задаются 2 словами (сегмент:смещение).<br>
По ссылке передаются все параметры переменные; массивы и записи, если их размер<br>
превышает 4 байта. Множества и строки всегда передаются по ссылке.<br>
     <span class='tag-u'>В стек погружаются:</span><ul class="tag-list"><li>Тип boolean как байт с фиксированным значением 0 или 1.</li><li>byte, char, shortint как байт.</li><li>Перечисляемый тип, как слово.</li><li>integer или word как 2 байта.</li><li>longint как 2 слова.</li><li>real как 3 слова.</li></ul><br>
     <strong class='tag-b'>[ Возврат значений функциями. ]</strong><br>
<br>
     Ассемблерные функции должны следующим образом возвращать результат<br>
своей работы:<br>
    * длиной 1 байт (Byte, Char и т.п.) - в регистре AL;<br>
    * длиной 2 байта (Integer, Word) - в регистре АХ;<br>
    * длиной 4 байта (Pointer, Longlnt) - в регистрах DX (старшее слово или<br>
сегм.) и в АХ (младшее слово или смещ.);<br>
    * типа Real - в регистрах DX, BX, АХ (старшее слово - в DX, младшее в АХ);<br>
    * вещественных типов Single, Double, Extended, Comp - в регистре ST(0) со-<br>
процессора;<br>
    * строкового типа - во временной области памяти, на которую ссылает-<br>
ся один из параметров в стеке. Подробнее о строках мы поговорим в разделе<br>
&quot;Обработка строк&quot;.<br>
     Интересное замечание: в книге В.В. Фаронова &quot;ТР 7.0&quot; написано, что<br>
строки должны возвращаться по ссылке в DX:AX. Лично мне это не понятно:<br>
куда я должен записать строку чтобы возвратить на нее ссылку? Возможно, это<br>
опечатка... Я же работал со строками как ребята из Борланда, но об<br>
этом чуть позже ;)<br>
<br>
     <strong class='tag-b'>[ Подключение asm модуля. ]</strong><br>
<br>
     Подключение asm модуля имеет ряд  особенностей:<br>
     ASM модуль может содержать сегмент данных со стандартными именами :<br>
CODE (CSEG) - сегмент с п/п, DATA(DSEG) - лок. переменными, CONST - <br>
типизированные констранты. Сегмент кода объединяется с основным сегментом<br>
кода  паскалевской программы, аналогично включается сегмент данных. Сегмент<br>
стека объявлять не требуется т.к. будет использоваться сегмент Паскаля.<br>
     Переменные сегмента данных являются локальными для asm  модуля,  то<br>
есть паскалевской программе они не известны.  Даже  если  определить  их<br>
конкретные значения db, dw, то в результирующей программе они не опреде-<br>
лены.<br>
     В  паскалевской  программе  asm  процедуры  описываются  директивой<br>
external. Транслируя asm модуль, результат - .obj - файл. В начале паска-<br>
левской программы записывается директива подключения .obj - модуля:<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">Program lab5;</div><div class="code_line">Uses crt;</div><div class="code_line">Type</div><div class="code_line">&nbsp;&nbsp; &nbsp;tmas = array[1..10] of integer;</div><div class="code_line">Var</div><div class="code_line">&nbsp;&nbsp; &nbsp;a,b: tmas;</div><div class="code_line">&nbsp;&nbsp; &nbsp;i,j: byte;</div><div class="code_line">&nbsp;&nbsp; &nbsp;na,n: word;</div><div class="code_line">&nbsp;</div><div class="code_line">{$L obrab.obj}</div><div class="code_line">&nbsp;</div><div class="code_line">{$F+} {все процедуры после этой директивы будут иметь дальнюю адресацию}</div><div class="code_line">Procedure M_ch_zr (Var x:tmas; n:word); external;</div><div class="code_line">Function max_cl (Var x:tmas; n:word):integer; external;</div><div class="code_line">{$F-}</div><div class="code_line">&nbsp;</div><div class="code_line">{Процедуры ввода-вывода массивов}</div><div class="code_line">Begin { main }</div><div class="code_line">&nbsp;&nbsp;in_massiv (a,na,&#39;A&#39;)</div><div class="code_line">&nbsp;&nbsp;in_massiv (b,nb,&#39;B&#39;);</div><div class="code_line">&nbsp;&nbsp;clrscr;</div><div class="code_line">&nbsp;&nbsp;out_massiv (a,na,&#39;Исходный массив A&#39;);</div><div class="code_line">&nbsp;&nbsp;Writeln (&#39;Максимальный элемент -&#39;,max_el(A,nA));</div><div class="code_line">&nbsp;&nbsp;M_ch_zr (A,na);</div><div class="code_line">&nbsp;&nbsp;Out_mas (A,na,&#39;Преобразованный массив A&#39;)</div><div class="code_line">End. { /main }</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
<br>
<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">CODE &nbsp; &nbsp; &nbsp;SEGMENT</div><div class="code_line">PUBLIC &nbsp; &nbsp;M_ch_Zr</div><div class="code_line">ASSUME &nbsp; &nbsp;CS:CODE</div><div class="code_line">M_ch_zr &nbsp; PROC &nbsp; &nbsp; &nbsp;FAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;замена &#60;0 на 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUSH &nbsp; &nbsp; &nbsp;CX DI BP ES</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; BP,SP</div><div class="code_line">; &nbsp; &nbsp;В данный момент в стек выглядит следующим образом:</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; &nbsp; &nbsp; &nbsp; &nbsp;&#9474;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; ES &nbsp; &nbsp; &#9474;bp+0</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; BP &nbsp; &nbsp; &#9474; +2</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; DI &nbsp; &nbsp; &#9474; +4</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; CX &nbsp; &nbsp; &#9474; +6</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp;адрес &nbsp; &#9484;&#9508;смещение&#9474; +8</div><div class="code_line">; &nbsp;возврата&#9474;&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#9492;&#9508;сегмент &#9474; +10</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9474; &nbsp;n &nbsp; &nbsp; &#9474; +12</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp;адрес &nbsp; &#9484;&#9508;смещение&#9474; +14</div><div class="code_line">; &nbsp;x &nbsp; &nbsp; &nbsp; &#9474;&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#9492;&#9508;сегмент &#9474; +16</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;</div><div class="code_line">;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; CX,[BP+12] &nbsp; &nbsp; ; n</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;les &nbsp; &nbsp; &nbsp; DI,[BP+14] &nbsp; &nbsp; ; адрес X</div><div class="code_line">c: &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; AX,es:[DI]</div><div class="code_line">; при трансляции перед этой командой ставится префикс изменения сег-</div><div class="code_line">; мента адресации. При отсутствии ES: &nbsp;адресация &nbsp;автоматически &nbsp;де-</div><div class="code_line">; лается DS:[DI]. Префикс действует только на одну команду.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; &nbsp; AX,0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jge &nbsp; &nbsp; &nbsp; M</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; word PTR ES:[DI],0</div><div class="code_line">M: &nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; &nbsp; DI,2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;loop &nbsp; &nbsp; &nbsp;C</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop &nbsp; &nbsp; &nbsp; ES BP DI CX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; 6</div><div class="code_line">M_ch_zr &nbsp; ENDP</div><div class="code_line">CODE &nbsp; &nbsp; &nbsp;ENDS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;END</div><div class="code_line">; Как видите, этот модуль практически ничем не отличается от обычной программы</div><div class="code_line">; на Ассемблере, но отличия все же есть: это, во-первых, строго заданные имена</div><div class="code_line">; сегментов и, во-вторых, вконце подуля стоит END без параметров. Это нужно</div><div class="code_line">; помнить!</div></ol></div></div></div></div><br>
     Ранее отмечено, что процедуры asm модуля попадают  в  сегмент  кода<br>
паскалевской программы, поэтому использование команды les является  избы-<br>
точным, т.к. в этом случае ES=DS.<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">Max_el &nbsp; &nbsp;PROC &nbsp; &nbsp; &nbsp;FAR</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp; &nbsp;CX DI BP ES</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; BP,SP</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; CX,[BP+12]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; DI,[BP+14]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; AX,DI</div><div class="code_line">C1: &nbsp; &nbsp; &nbsp; cmp &nbsp; &nbsp; &nbsp; AX,[DI]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jge &nbsp; &nbsp; &nbsp; M1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; &nbsp; AX,[DI]</div><div class="code_line">M1: &nbsp; &nbsp; &nbsp; add &nbsp; &nbsp; &nbsp; [DI],2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;loop &nbsp; &nbsp; &nbsp;C1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop &nbsp; &nbsp; &nbsp; ES BP DI CX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; 6</div><div class="code_line">Max_el &nbsp; &nbsp;ENDP</div></ol></div></div></div></div><br>
<br>
<br>
<br>
     По завершению процедуры в AX - max_el, который и возвращается в ка-<br>
честве результата функции в паскалевскую программу.<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">&nbsp;&nbsp; &nbsp; start &nbsp; &nbsp; stop &nbsp; &nbsp; &nbsp;length &nbsp; &nbsp;name &nbsp; &nbsp; &nbsp;class</div><div class="code_line">&nbsp;&nbsp; &nbsp; 00000h &nbsp; &nbsp;00343h &nbsp; &nbsp;00344h &nbsp; &nbsp;lab5 &nbsp; &nbsp; &nbsp;code</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; от &nbsp; &nbsp; &nbsp; &nbsp;до &nbsp; &nbsp; &nbsp;всего</div><div class="code_line">&nbsp;&nbsp; &nbsp; 00350h &nbsp; &nbsp;00962h &nbsp; &nbsp;00613h &nbsp; &nbsp;crt &nbsp; &nbsp; &nbsp; code</div><div class="code_line">&nbsp;&nbsp; &nbsp; -------------------------- &nbsp; &nbsp;system &nbsp; &nbsp;code</div><div class="code_line">&nbsp;&nbsp; &nbsp; 01390h &nbsp; &nbsp;---------------- &nbsp; &nbsp;data &nbsp; &nbsp; &nbsp;data</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; глобальный сегмент данных pas программы</div><div class="code_line">&nbsp;&nbsp; &nbsp; 01660h &nbsp; &nbsp;0505fh &nbsp; &nbsp;04000h &nbsp; &nbsp;stack &nbsp; &nbsp; stack</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;16 Kb</div><div class="code_line">&nbsp;&nbsp; &nbsp; 05660h &nbsp; &nbsp;05660h &nbsp; &nbsp;00000h &nbsp; &nbsp;heap &nbsp; &nbsp; &nbsp;heap</div></ol></div></div></div></div><br>
     Динамические переменные, т.к. куча не используется.<br>
<br>
<br>
     [ Особенность обработки матриц. ]<br>
<br>
     Обработка матриц в asm модуле имеет свои &quot;тонкости&quot;. Рассмотрим это<br>
подробнее:<br>
     Пусть, в Паскалевской программе матрица объявлена след. образом:<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">Program Matrix_asm;</div><div class="code_line">Uses CRT;</div><div class="code_line">Const</div><div class="code_line">&nbsp;&nbsp;max_n = 10;</div><div class="code_line">&nbsp;&nbsp;max_m = 5; </div><div class="code_line">Type</div><div class="code_line">&nbsp;&nbsp;TMatrix = array[1..max_n, 1..max_m] &nbsp;of integer;</div><div class="code_line">Var</div><div class="code_line">&nbsp;&nbsp;Matrix : TMatrix;</div><div class="code_line">&nbsp;&nbsp;m,n &nbsp; &nbsp;: word;</div><div class="code_line">Begin</div><div class="code_line">&nbsp;&nbsp;n:=0;</div><div class="code_line">&nbsp;&nbsp;m:=0;</div><div class="code_line">&nbsp;&nbsp;repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;ClrScr;</div><div class="code_line">&nbsp;&nbsp; &nbsp;write(&#39;Введите размеры матрицы n, m&#39;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;readln(n,m);</div><div class="code_line">&nbsp;&nbsp;until (n&#62;0 and n &#60;= max_n) and (m&#62;0 and m &#60;= max_m);</div><div class="code_line">&nbsp;&nbsp;{ Здесь осуществляется ввод матрицы }</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;. . .</div><div class="code_line">&nbsp;&nbsp;{ Здесь осуществляется обработка матрицы }</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;. . .</div><div class="code_line">&nbsp;&nbsp;{ Здесь осуществляется вывод матрицы }</div><div class="code_line">End.</div></ol></div></div></div></div>	<br>
<br>
<br>
<br>
     При таком объявлении матрицы наша переменная (Matrix) в памяти<br>
будет занимать такой участок:<br>
<br>
<pre>	    1        n     max_n
	     &#9556;&#9552;&#9552;&#9572;&#9552; . &#9552;&#9559; . &#9472;&#9516;&#9472;&#9472;&#9488;
	     &#9567;&#9472;&#9472;&#9532;&#9472; . &#9472;&#9570; . &#9472;&#9532;&#9472;&#9472;&#9508;
	       . . . . . . . .
	   m &#9562;&#9552;&#9552;&#9575;&#9552; . &#9552;&#9565; . &#9472;&#9532;&#9472;&#9472;&#9508;
	       . . . . . . . .
	     &#9500;&#9472;&#9472;&#9532;&#9472; . &#9472;&#9532; . &#9472;&#9532;&#9472;&#9472;&#9508;
	max_m&#9492;&#9472;&#9472;&#9524;&#9472; . &#9472;&#9524; . &#9472;&#9524;&#9472;&#9472;&#9496;</pre><br>
<br>
     На	данном рисунке двойной линией обозначено реально используемое<br>
пространство матрицы, а одинарной - полный объем памяти, занимаемый <br>
матрицей.<br>
     Таким образом, чтобы обратиться ко второму эл-ту третей строки<br>
нужно использовать смещение: &quot;((3-1) * max_n + (2-1)) * 2&quot;, а не <br>
&quot;3 * n + 2&quot;, как может показаться на первый взгляд. В конце нужно<br>
умножить на размер элемента в байтах (в нашем случае это 2 байта - раз-<br>
мер типа integer). Это следует учитывать при обработ ке матриц. Для того<br>
чтобы корректно обработать матрицу в процедуру обработки нужно передавать<br>
не только адрес матрицы, n и m но и длину строки (в нашем случае это max_n).<br>
<br>
{ Т.е. процедура должна быть описана так: }<br>
  Procedure Do_Something(Var Matr: TMatrix; n,m,max_n: word); external;<br>
<br>
{ А вызов, соответственно, делать так: }<br>
  Do_Something(Matrix, n,m,max_n);<br>
<br>
<br>
<br>
    <strong class='tag-b'> [ Обработка строк. ]</strong><br>
<br>
     Обычно функция возвращает одно скалярное значение. Но в TP есть исключе-<br>
ние. Это тип string, который является структурированным (массивом символов),<br>
однако с другой стороны имеются средства обработки как скаляра (операция<br>
присвоения, операции сравнения и др.).<br>
<br>
     Рассмотрим следующий пример из состава TASM:<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">; Turbo Assembler example. Copyright (c) 1993 By Borland International, Inc.</div><div class="code_line">;</div><div class="code_line">; HEX.ASM</div><div class="code_line">;</div><div class="code_line">; Usage: Run tasm on this file and link with hex.pas</div><div class="code_line">&nbsp;</div><div class="code_line">CODE &nbsp; &nbsp; &nbsp;SEGMENT</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ASSUME cs:CODE,ds:NOTHING</div><div class="code_line">&nbsp;</div><div class="code_line">; Parameters (+2 because of push bp)</div><div class="code_line">&nbsp;</div><div class="code_line">byteCount EQU BYTE PTR &nbsp;ss:[bp+6] &nbsp; ; а это параметры</div><div class="code_line">num &nbsp; &nbsp; &nbsp; EQU DWORD PTR ss:[bp+8] &nbsp; &nbsp; &nbsp; ; функции HexStr.</div><div class="code_line">&nbsp;</div><div class="code_line">; Function result address (+2 because of push bp)</div><div class="code_line">&nbsp;</div><div class="code_line">resultPtr EQU DWORD PTR ss:[bp+12] &nbsp; &nbsp; &nbsp;; это результат функции</div><div class="code_line">&nbsp;</div><div class="code_line">HexStr &nbsp; &nbsp;PROC FAR</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUBLIC HexStr</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;push bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov bp,sp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;get pointer into stack</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;les di,resultPtr &nbsp; ;get address of function result</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov dx,ds &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;save Turbo&#39;s DS in DX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lds si,num &nbsp; &nbsp; &nbsp; &nbsp; ;get number address</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov al,byteCount &nbsp; ;how many bytes?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xor ah,ah &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;make a word</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov cx,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;keep track of bytes in CX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;add si,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;start from MS byte of number</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dec si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;shl ax,1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;how many digits? (2/byte)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cld &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;store # digits (going forward)</div><div class="code_line">&nbsp;</div><div class="code_line">; Важно!!! Не забывайте записывать длину строки в нулевой байт!</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stosb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;in destination string&#39;s length byte</div><div class="code_line">&nbsp;</div><div class="code_line">HexLoop:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;std &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;scan number from MSB to LSB</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lodsb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;get next byte</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ah,al &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;save it</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;shr al,1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;extract high nibble</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;shr al,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;shr al,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;shr al,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;add al,90h &nbsp; &nbsp; &nbsp; &nbsp; ;special hex conversion sequence</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;daa &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;using ADDs and DAA&#39;s</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;adc al,40h</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;daa &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;nibble now converted to ASCII</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cld &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;store ASCII going up</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stosb</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov al,ah &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;repeat conversion for low nibble</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;and al,0Fh</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;add al,90h</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;daa</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;adc al,40h</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;daa</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stosb</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;loop HexLoop &nbsp; &nbsp; &nbsp; ;keep going until done</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov ds,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;restore Turbo&#39;s DS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;parameters take 6 bytes</div><div class="code_line">HexStr &nbsp; &nbsp;ENDP</div><div class="code_line">CODE &nbsp; &nbsp; &nbsp;ENDS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;END</div></ol></div></div></div></div><br>
<br>
<hr><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">{ Turbo Assembler example. Copyright (c) 1993 By Borland International, Inc. }</div><div class="code_line">&nbsp;</div><div class="code_line">{ Use with hex.asm }</div><div class="code_line">&nbsp;</div><div class="code_line">Program HexTest;</div><div class="code_line">Var</div><div class="code_line">&nbsp;&nbsp;num : Word;</div><div class="code_line">&nbsp;</div><div class="code_line">Function HexStr (Var num; byteCount : Byte) : string; far; external;</div><div class="code_line">&nbsp;</div><div class="code_line">{$L HEX.OBJ}</div><div class="code_line">&nbsp;</div><div class="code_line">Begin</div><div class="code_line">&nbsp;&nbsp;num := $face;</div><div class="code_line">&nbsp;&nbsp;Writeln(&#39;The Converted Hex String is&quot;&#39;,HexStr(num,sizeof(num)),&#39;&quot;&#39;);</div><div class="code_line">End.</div></ol></div></div></div></div><br>
<br>
<br>
     Не вникаясь в алгоритм функции рассмотрим как выглядит стек при<br>
вызове HexStr(num,sizeof(num)).<br>
<br>
<pre>              ВР+0              &#9474; старый ВР    &#9474;
                                &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
              ВР+2,4            &#9500; адр. возвр.  &#9508;  (4 байта)
                                &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
              ВР+6              &#9474; sizeof(num)  &#9474; &#9472;&#9488;
                                &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;  &#9474;  Все параметры
              ВР+8        адрес&#9484;&#9508;  смещение    &#9474;  &#9500;  данной функции
                           num &#9474;&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;  &#9474;  занимают 6 байт
              ВР+10            &#9492;&#9508;  сегмент     &#9474; &#9472;&#9496;
                                &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
              ВР+12       адрес&#9484;&#9508;  смещение    &#9474;  Это поле в стек
                          врем.&#9474;&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;  поместил сам компилятор.
              ВР+14       поля &#9492;&#9508;  сегмент     &#9474;  При расчете параметра ret
                                &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;  это поле не учитывать&#33;
                                                  Именно поэтому в примере
                                                  стоит ret 6, а не ret 8.</pre><br>
<br>
     Итак, что же это все значит? Ну, по порядку:<br>
     В стеке лежит адрес возврата и адрес обрабатываемого поля num. Тут<br>
все понятно... Но вот что за адрес временного поля? На самом деле, компиля-<br>
тор помещает в стек адрес поля памяти, куда следует записать результат.<br>
После работы подпрограммы компилятор сам позаботится о копировании<br>
этого поля в результирующую строку.<br>
<br>
     <strong class='tag-b'>[ Макростредства в помощь ]</strong><br>
<br>
     Ведь не зря ребята в Борланде парились создавая макросредства в<br>
своем ассемблере ;-). Скажем им спасибо и посмотрим как же их можно использо-<br>
вать в нашем случае. Для примера опять возьмем исходник от Борланда:<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">; Turbo Assembler example. Copyright (c) 1993 By Borland International, Inc.</div><div class="code_line">;</div><div class="code_line">; ENVSTR.ASM - Example program to scan the DOS environment</div><div class="code_line">;</div><div class="code_line">; Usage: Run tasm on this file and link with envstr.pas</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.MODEL &nbsp;large,PASCAL</div><div class="code_line">; Эта директива создает сегменты по умолчанию и соответствующие им</div><div class="code_line">; выражения ASSUME и GROUP. В кач-ве параметра указана модель памяти,</div><div class="code_line">; полностью соответствующая Паскалю.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.DATA</div><div class="code_line">; А тут мы начали сегмент данных.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EXTRN prefixSeg : WORD &nbsp;;gives location of PSP</div><div class="code_line">; А тут одной строкой объявили адрес PSP.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.CODE</div><div class="code_line">; А вот и сегмент кода.</div><div class="code_line">EnvString PROC FAR &nbsp;EnvVar:DWORD &nbsp;RETURNS EnvVal:DWORD</div><div class="code_line">; Тут мы объявили дальнюю функцию с параметром EnvVar размером в 4 байта</div><div class="code_line">; (сегм. + смещ.) и указали что EnvVal тогоже размера будет</div><div class="code_line">; нашой переменной, куда мы запишем результат ;)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUBLIC &nbsp;EnvString</div><div class="code_line">; А это для того чтобы Паскаль смог &quot;увидеть&quot; нашу функцию.</div><div class="code_line">; Это что-то типа объявления функций в интерфейсе модуля ;)</div><div class="code_line">; И еще, как видите, в начале подпрограммы команды &quot;push bp&quot; и</div><div class="code_line">; &quot;mov bp,sp&quot; писать не нужно. За вас это сделает компилятор ;)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cld &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;work upward</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; es,[prefixSeg] &nbsp;;look at PSP</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; es,es:[2Ch] &nbsp; &nbsp; ;ES:DI points at environment</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; di,di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;which is paragraph-aligned</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bp,sp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;find the parameter address</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lds &nbsp; &nbsp; si,EnvVar &nbsp; &nbsp; &nbsp; ;which is right above the return address</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ASSUME &nbsp;ds:NOTHING</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lodsb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;look at length</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;al,al &nbsp; &nbsp; &nbsp;;is it zero?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jz &nbsp; &nbsp; &nbsp;RetNul &nbsp; &nbsp; ;if so, return</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ah,al &nbsp; &nbsp; &nbsp;;otherwise, save in AH</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx,si &nbsp; &nbsp; &nbsp;;DS:DX contains pointer to first parm character</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; al,al &nbsp; &nbsp; &nbsp;;make a zero</div><div class="code_line">Compare:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ch,al &nbsp; &nbsp; &nbsp;;we want ch=0 for next count, if any</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; si,dx &nbsp; &nbsp; &nbsp;;get back pointer to string sought</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl,ah &nbsp; &nbsp; &nbsp;;get length</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; si,dx &nbsp; &nbsp; &nbsp;;get pointer to string sought</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;repe &nbsp; &nbsp;cmpsb &nbsp; &nbsp; &nbsp;;compare bytes</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; Skip &nbsp; &nbsp; &nbsp; ;if compare fails, try next string</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; byte PTR es:[di],&#39;=&#39;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;compare succeeded; is next char &#39;=&#39;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; NoEqual &nbsp; &nbsp;;if not, still no match</div><div class="code_line">Found:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax,es &nbsp; &nbsp; &nbsp;;make DS:SI point to string we found</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ds,ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc &nbsp; &nbsp; si &nbsp; &nbsp; &nbsp; &nbsp; ;get past the equal (=) sign</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;les &nbsp; &nbsp; bx,EnvVal &nbsp;;get address of function result</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; di,bx &nbsp; &nbsp; &nbsp;;put it in ES:DI</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc &nbsp; &nbsp; di &nbsp; &nbsp; &nbsp; &nbsp; ;get past the length byte</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl,255 &nbsp; &nbsp; ;set up a maximum length</div><div class="code_line">CopyLoop:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lodsb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;get a byte</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;al,al &nbsp; &nbsp; &nbsp;;zero test</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jz &nbsp; &nbsp; &nbsp;Done &nbsp; &nbsp; &nbsp; ;if zero, we&#39;re done</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stosb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;put it in the result</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;loop &nbsp; &nbsp;CopyLoop &nbsp; ;move up to 255 bytes</div><div class="code_line">Done: &nbsp; &nbsp; not &nbsp; &nbsp; cl &nbsp; &nbsp; &nbsp; &nbsp; ;we&#39;ve been decrementing CL from</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; 255 during save</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; es:[bx],cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;save the length</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax,@DATA</div><div class="code_line">; А тут мы а АХ поместили сегмента данных ;)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ds,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;restore DS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ASSUME &nbsp;ds:@DATA</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret</div><div class="code_line">; Как видите, тут ret без параметров ;)</div><div class="code_line">; А знаете почему? А потому что компилятор сам сюда напишет все что</div><div class="code_line">; нужно: восстановит ВР и напишет retf с нужным параметром в зависимости</div><div class="code_line">; от входных параметров. В нашем случае выход будет таким:</div><div class="code_line">; &quot;pop bp&quot; + &quot;retf 4&quot;.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ASSUME &nbsp;ds:NOTHING</div><div class="code_line">Skip:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dec &nbsp; &nbsp; di &nbsp; &nbsp; &nbsp; &nbsp; ;check for null from this char on</div><div class="code_line">NoEqual:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cx,7FFFh &nbsp; ;search a long way if necessary</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; cx,di &nbsp; &nbsp; &nbsp;;environment never &#62;32K</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jbe &nbsp; &nbsp; RetNul &nbsp; &nbsp; ;if we&#39;re past end, leave</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;repne &nbsp; scasb &nbsp; &nbsp; &nbsp;;look for the next null</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jcxz &nbsp; &nbsp;RetNul &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;exit if not found</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; byte PTR es:[di],al &nbsp;;second null in a row?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; Compare &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;if not, try again</div><div class="code_line">RetNul:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;les &nbsp; &nbsp; di,EnvVal &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;get address of result</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stosb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;store a zero there</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax,@DATA</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ds,ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;restore DS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ASSUME &nbsp;ds:@DATA</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret</div><div class="code_line">; Как видите, тут тоже ret без параметров(см. выше) ;)</div><div class="code_line">EnvString ENDP</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;END</div><div class="code_line">; И еще, как вы заметили, ребята из Борланда не сильно беспокоятся о регистрах.</div><div class="code_line">; Точнее беспокоятся только о DS, SS и SP, а о ВР заботится сам компилятор при</div><div class="code_line">; входе и выходе из п/п(только при использовании ключевого слова PASCAL в объяв-</div><div class="code_line">; лении п/п или при указании модели памяти!). Т.е. Все остальные регистры к мо-</div><div class="code_line">; менту выхода из п/п могут иметь произвольные значения ;). Исключение состав-</div><div class="code_line">; ляют только функции, которые возвращают результат в некоторых регистрах.</div></ol></div></div></div></div><br>
<br>
<hr><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">{ Turbo Assembler example. Copyright (c) 1993 By Borland International, Inc. }</div><div class="code_line">&nbsp;</div><div class="code_line">{ Use with envstr.asm }</div><div class="code_line">&nbsp;</div><div class="code_line">Program EnvTest;</div><div class="code_line">{ program looks for environment strings }</div><div class="code_line">&nbsp;</div><div class="code_line">Var</div><div class="code_line">&nbsp;&nbsp;EnvVariable : string;</div><div class="code_line">&nbsp;&nbsp;EnvValue : string;</div><div class="code_line">&nbsp;</div><div class="code_line">Function EnvString(s:string) : string; far; external;</div><div class="code_line">{$L ENVSTR.OBJ}</div><div class="code_line">Begin</div><div class="code_line">&nbsp;&nbsp;EnvVariable := &#39;PROMPT&#39;;</div><div class="code_line">&nbsp;&nbsp;EnvValue := EnvString(EnvVariable);</div><div class="code_line">&nbsp;&nbsp;if EnvValue=&#39;&#39; then EnvValue := &#39;*** not found ***&#39;;</div><div class="code_line">&nbsp;&nbsp;Writeln(&#39;Environment Variable:&#39;,EnvVariable,&#39;Value:&#39;,EnvValue);</div><div class="code_line">End.</div></ol></div></div></div></div><br>
<br>
<br>
     <strong class='tag-b'>[ Резюме ]</strong><br>
<br>
Ну что ж, вспомним все, о чем говорилось в этой статье...<br>
     Asm модули, в основном, используются для увеличения производительности<br>
программы. <br>
     В одном модуле можно использовать как ближнюю, так и дальнюю адресацию,<br>
но если в модуле используются межсегментные вызовы, то такие п/п должны иметь<br>
дальнюю адресацию. Кстати, при дальней адресации значение CS при выходе из п/п<br>
может быть произвольным. Э то связано с тем, что при такой адресации адрес<br>
возврата состоит из 4 байт (сегм.+смещ.).<br>
     Параметры передаются в стек в порядке их описания. Адреса всегда переда-<br>
ются дальними. По ссылке передаются все параметры переменные; массивы и записи,<br>
если их размер превышает 4 байта. Множества и строки всегда передаются по ссылке.<br>
Стек чистит сама п/п использую ret data.<br>
     Функции возвращают свои значения в регистрах (см. &quot;Возврат значений функ-<br>
циями&quot;). Исключение чение составляют строки - их сохраняют во времееной облас-<br>
ти памяти.<br>
     Asm модули практически не отличаются от обычных программ на ЯА. Модули<br>
должны иметь строго определенные имена сегментов (CODE, DATA, STACK). Эти<br>
сегменты будут объеденены с Паскалевскими. В конце модуля стоит END без пара-<br>
метров. Возможны следующие варианты оформления:<br>
<br>
     Пусть дана такая процедура:<br>
<br>
     procedure proc_name(Var a: byte; b: integer; c: longint);<br>
<br>
<br>
     Тогода:<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">CODE &nbsp; &nbsp; &nbsp;SEGMENT</div><div class="code_line">PUBLIC &nbsp; &nbsp;proc_name</div><div class="code_line">ASSUME &nbsp; &nbsp;CS:CODE</div><div class="code_line">proc_name PROC &nbsp; &nbsp; &nbsp;FAR</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUBLIC &nbsp;proc_name</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;push bp ds ss sp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp;bp,sp</div><div class="code_line">a &nbsp; &nbsp; &nbsp; &nbsp; equ &nbsp;[bp+12] &nbsp; &nbsp;; &nbsp; Это</div><div class="code_line">b &nbsp; &nbsp; &nbsp; &nbsp; equ &nbsp;[bp+10] &nbsp; &nbsp;; &nbsp; &nbsp; параметры</div><div class="code_line">c &nbsp; &nbsp; &nbsp; &nbsp; equ &nbsp;[bp+6] &nbsp; &nbsp; ; &nbsp; &nbsp; &nbsp; процедуры</div><div class="code_line">&nbsp;. . .</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop &nbsp;sp ss ds bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp;10 &nbsp; &nbsp; ; 10 - кол-во переданных байт</div><div class="code_line">proc_name ENDP</div><div class="code_line">CODE &nbsp; &nbsp; &nbsp;ENDS</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;END</div><div class="code_line">&nbsp;</div><div class="code_line">; &nbsp; &nbsp; Процедуру можно было объявить и так:</div><div class="code_line">&nbsp;</div><div class="code_line">proc_name PROC FAR PASCAL, a:dword,b:word,c:dword ; Это параметры</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUBLIC &nbsp;proc_name</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;push ds ss sp</div><div class="code_line">&nbsp;. . .</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop &nbsp;sp ss ds</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret ; без параметров</div><div class="code_line">proc_name endp</div><div class="code_line">&nbsp;</div><div class="code_line">; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;или</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.MODEL &nbsp;large,PASCAL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.DATA</div><div class="code_line">&nbsp;. . . &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.CODE</div><div class="code_line">proc_name PROC FAR &nbsp;a:dword,b:word,c:dword ; Это параметры процедуры</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PUBLIC &nbsp;proc_name</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;push ds ss sp</div><div class="code_line">&nbsp;. . .</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pop &nbsp;sp ss ds</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ret ; без параметров</div><div class="code_line">proc_name ENDP</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;END</div></ol></div></div></div></div><br>
<br>
<br>
     <strong class='tag-b'>[ Приложение А. Работа с множествами. ]</strong><br>
<br>
     Многих давно итересует как же на самом деле работают множества и какова<br>
их внутренняя структура... <br>
     Итак, максимальный кол-во эл-тов в мн-ве 256 (т.е от 0 до 255) хотя,<br>
мн-во может быть пустым ([]). Каждому элементу мн-ва соответствует 1 бит<br>
(1 - элемент присутствует в мн-ве, 0 - отсутствует). Таким образом мак-<br>
симальный объем памяти, занимаемый множеством не может превышать 32 байта<br>
(256 бит, по биту на элемент). Однако, как вы знаете, минимальный объем<br>
памяти равен 1 байту т.е. даже если вы обявите мн-во как &quot;X: set of 1..1&quot; то<br>
его размер все равно будет равен 1 байту и более того, вы даже можете<br>
сделать такое:<br>
<br>
     b:=5;<br>
     Include(X,n);<br>
<br>
<br>
<br>
и это будет работать... ;)<br>
     Из всего вышеперечисленного следует что вся работа над множествами<br>
состоит из логических операций над памятью. Пример:<br>
<br>
     Пусть заданы мн-ва &quot;X,Y: set of 0..7;&quot;<br>
     Тогда операция &quot;X:=[];&quot; на самом деле обнуляет участок памяти с мно-<br>
жеством т.е. это будет &quot;0000 0000&quot;.<br>
     Операция &quot;Include(X,3);&quot; будет выглядеть так:<br>
<br>
    old X  0000 0000<br>
        or<br>
       [3] 0001 0000<br>
        =<br>
    new X  0001 0000<br>
<br>
     Y:=X+[2..4,7]<br>
<br>
<br>
<br>
        X  0001 0000<br>
        or<br>
  [2..4,7] 0011 1001<br>
        =<br>
        Y  0011 1001<br>
<br>
     X:=X*Y<br>
<br>
<br>
<br>
    old X  0001 0000<br>
       and<br>
        Y  0011 1001<br>
        =<br>
    new X  0001 0000<br>
<br>
     X:=X-[2..3];<br>
<br>
<br>
<br>
     А тут немного сложнее: для начала инвертируем [2..3], а потом<br>
умножаем:<br>
<br>
         [2..3]  0011 0000<br>
     not [2..3]  1100 1111<br>
<br>
          old X  0001 0000<br>
              *<br>
     not [2..3]  1100 1111<br>
              =<br>
          new X  0000 0000<br>
<br>
     И в заключение приведу пример работы с множествами в asm модуле:<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">; File name: &quot;Prime_m.asm&quot;</div><div class="code_line">; Работа с множествами (решето Эратосфена).</div><div class="code_line">; Данный файл является asm модулем к программе &quot;Prime_a.pas&quot;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;.MODEL &nbsp;large,PASCAL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;.DATA</div><div class="code_line">n1 &nbsp;dw &nbsp;?</div><div class="code_line">next &nbsp; &nbsp;dw &nbsp;2</div><div class="code_line">BytesInSet dw &nbsp; ?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;.CODE</div><div class="code_line">PUBLIC CalcPrime</div><div class="code_line">CalcPrime proc far</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bp,sp</div><div class="code_line">Set_Adr equ [bp+8]</div><div class="code_line">N &nbsp; equ [bp+6]</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov si,Set_Adr &nbsp; ; si - адрес исходного мн-ва</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov ax,N</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov dl,8</div><div class="code_line">&nbsp;&nbsp; &nbsp;div dl</div><div class="code_line">&nbsp;&nbsp; &nbsp;sub dl,ah</div><div class="code_line">&nbsp;&nbsp; &nbsp;add N,dl</div><div class="code_line">&nbsp;&nbsp; &nbsp;dec byte ptr N</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov dx,N &nbsp; &nbsp; &nbsp; &nbsp; ; dx=N</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cx,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp;shr cx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;inc cx</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov BytesInSet,cx &nbsp; ; BytesInSet=SizeOf(Set);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov di,si</div><div class="code_line">c: &nbsp;mov byte ptr [di],0 ; Set:=[];</div><div class="code_line">&nbsp;&nbsp; &nbsp;inc di</div><div class="code_line">&nbsp;&nbsp; &nbsp;loop &nbsp; &nbsp;c</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov byte ptr [si],2 ; Set:=[1]</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;sub sp,BytesInSet &nbsp; ; Создадим вспомогательное мн-во в стеке</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov di,sp &nbsp; &nbsp; &nbsp; ; di - адрес нового мн-ва</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;di</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cx,BytesInSet</div><div class="code_line">c1: mov byte ptr [di],0FFh ; Set:=[0..N];</div><div class="code_line">&nbsp;&nbsp; &nbsp;inc di</div><div class="code_line">&nbsp;&nbsp; &nbsp;loop &nbsp; &nbsp;c1</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop di</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov byte ptr [di],11111100b &nbsp; &nbsp;; Set:=[2..N];</div><div class="code_line">ccc: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; While Set &#60;&#62; []</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov al,0</div><div class="code_line">&nbsp;&nbsp; &nbsp;cld</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cx,BytesInSet</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;di si</div><div class="code_line">&nbsp;&nbsp; &nbsp;repe &nbsp; &nbsp;scasb</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop si di</div><div class="code_line">&nbsp;&nbsp; &nbsp;je &nbsp;m_end</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;next</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop n1</div><div class="code_line">m_wh: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; while n1 do begin&#60;=N</div><div class="code_line">&nbsp;&nbsp; &nbsp;cmp n1,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp;ja &nbsp;m_endd</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov ax,n1</div><div class="code_line">&nbsp;&nbsp; &nbsp;call &nbsp; &nbsp;Excl</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov ax,next</div><div class="code_line">&nbsp;&nbsp; &nbsp;add n1,ax</div><div class="code_line">&nbsp;&nbsp; &nbsp;jmp m_wh</div><div class="code_line">m_endd: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; end { while n1&#60;=N }</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov ax,next</div><div class="code_line">&nbsp;&nbsp; &nbsp;call &nbsp; &nbsp;Incl</div><div class="code_line">&nbsp;</div><div class="code_line">m_rep: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;inc next</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov ax,next</div><div class="code_line">&nbsp;&nbsp; &nbsp;Call &nbsp; &nbsp;In_s</div><div class="code_line">&nbsp;&nbsp; &nbsp;jnz m_end_rep</div><div class="code_line">&nbsp;&nbsp; &nbsp;cmp next,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp;ja &nbsp;m_end_rep</div><div class="code_line">&nbsp;&nbsp; &nbsp;jmp m_rep</div><div class="code_line">&nbsp;</div><div class="code_line">m_end_rep: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; until (next in Set) or (next &#62; N)</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;jmp ccc</div><div class="code_line">&nbsp;</div><div class="code_line">m_end:</div><div class="code_line">&nbsp;&nbsp; &nbsp;add sp,BytesInSet &nbsp; ; Удалим вспомогательное мн-во в стеке</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;ret 6</div><div class="code_line">CalcPrime endp</div><div class="code_line">; - - - - - - - - - -</div><div class="code_line">Incl &nbsp; &nbsp;proc &nbsp; &nbsp;near</div><div class="code_line">; Set:=set+[al]</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;si bx cx</div><div class="code_line">&nbsp;&nbsp; &nbsp;xor ah,ah</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,ax</div><div class="code_line">&nbsp;&nbsp; &nbsp;shr bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;add si,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;sub ax,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cl,al</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,cl</div><div class="code_line">&nbsp;&nbsp; &nbsp;or &nbsp;[si],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop cx bx si</div><div class="code_line">&nbsp;&nbsp; &nbsp;ret</div><div class="code_line">Incl &nbsp; &nbsp;endp</div><div class="code_line">; - - - - - - - - - -</div><div class="code_line">Excl &nbsp; &nbsp;proc &nbsp; &nbsp;near</div><div class="code_line">; Set:=set-[al]</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;di bx cx</div><div class="code_line">&nbsp;&nbsp; &nbsp;xor ah,ah</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,ax</div><div class="code_line">&nbsp;&nbsp; &nbsp;shr bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;add di,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;sub ax,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cl,al</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,cl</div><div class="code_line">&nbsp;&nbsp; &nbsp;not bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;and [di],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop cx bx di</div><div class="code_line">&nbsp;&nbsp; &nbsp;ret</div><div class="code_line">Excl &nbsp; &nbsp;endp</div><div class="code_line">; - - - - - - - - - - - - -</div><div class="code_line">In_s &nbsp; &nbsp;proc &nbsp; &nbsp;near</div><div class="code_line">; [al] in Set ?</div><div class="code_line">&nbsp;&nbsp; &nbsp;push &nbsp; &nbsp;di bx cx</div><div class="code_line">&nbsp;&nbsp; &nbsp;xor ah,ah</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,ax</div><div class="code_line">&nbsp;&nbsp; &nbsp;shr bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;add di,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,3</div><div class="code_line">&nbsp;&nbsp; &nbsp;sub ax,bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp;mov cl,al</div><div class="code_line">&nbsp;&nbsp; &nbsp;shl bx,cl</div><div class="code_line">&nbsp;&nbsp; &nbsp;and bx,[di]</div><div class="code_line">&nbsp;&nbsp; &nbsp;pop cx bx di</div><div class="code_line">&nbsp;&nbsp; &nbsp;ret</div><div class="code_line">In_s &nbsp; &nbsp;endp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end</div></ol></div></div></div></div><br>
<br>
<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">{</div><div class="code_line">&nbsp;File name: &quot;Prime_a.pas&quot;</div><div class="code_line">&nbsp;Работа с множествами (решето Эратосфена).</div><div class="code_line">&nbsp;Данный файл компилируется вместе с &quot;Prime_m.obj&quot;</div><div class="code_line">}</div><div class="code_line">Program Prime_a;</div><div class="code_line">Const</div><div class="code_line">&nbsp;&nbsp;N=255;</div><div class="code_line">Type</div><div class="code_line">&nbsp;&nbsp;SetOfNumb = set of 1..N;</div><div class="code_line">Var</div><div class="code_line">&nbsp;&nbsp;i : word;</div><div class="code_line">&nbsp;&nbsp;PrimeSet &nbsp; : SetOfNumb;</div><div class="code_line">{$L prime_m.obj}</div><div class="code_line">Procedure CalcPrime(Var SetOfNumb; n:word); far; external;</div><div class="code_line">Begin</div><div class="code_line">&nbsp;&nbsp;CalcPrime(PrimeSet,N);</div><div class="code_line">&nbsp;&nbsp;for i:=1 to N do</div><div class="code_line">&nbsp;&nbsp; &nbsp;if i in PrimeSet then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Write(i:8);</div><div class="code_line">&nbsp;&nbsp;WriteLn;</div><div class="code_line">End.</div></ol></div></div></div></div><br>
<br>
<br>
<br>
     [ THE END ]<br>
<br>
     Ну что, вроде все что я хотел сказать... Всем удачи ;) До встречи.<br>
<br>
<br>
(С) Лабинский Николай aka <a class='tag-url' href='http://forum.sources.ru/index.php?showuser=9927' target='_blank'>e-moe</a>. ДонНТУ 2004-2005.<br>
					I love Borland.<br>
 <br>
&lt;<br>
Написано по мотивам конспекта лекций по &quot;СП&quot; Теплинского С.В, а также,<br>
книги Фаронова В.В. &quot;Turbo Pascal 7.0&quot; и, естественно, книги П.Абеля &quot;ЯА&quot;<br>
&gt;<br>
<br>
При написании этой стати использовались:<br>
 * Пиратские копии bp.exe, tasm.exe и td.exe. ;)<br>
 * И зарегистрированный FAR. %)<br>
<br>
Last one modified at: GMT+2 23:31:50 9.01.2005<br>
<br>
<span class="tag-color tag-color-named" data-value="gray" style="color: gray"><span class='tag-size' data-value='7' style='font-size:7pt;'>Это сообщение было перенесено сюда или объединено из темы &quot;Linking Asm to Pascal&quot;</span></span>]]></description>
        <author>Romtek</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=41358&amp;view=findpost&amp;p=268842</guid>
        <pubDate>Tue, 23 Dec 2003 13:41:03 +0000</pubDate>
        <title>Внешние процедуры или функции</title>
        <link>https://forum.sources.ru/index.php?showtopic=41358&amp;view=findpost&amp;p=268842</link>
        <description><![CDATA[Some1: <span class="tag-color tag-color-named" data-value="blue" style="color: blue"><div class='tag-align-center'><strong class='tag-b'>Внешние процедуры (функции)</strong></div></span><br>
<br>
<br>
С помощью внешних процедур (функций) можно осуществить вызов из программы процедур или функций, написанных на языке ассемблера. Ассемблер обеспечивает компиляцию программ, написанных на машинно-ориентированном языке программирования низкого уровня. В Турбо Паскале есть собственный встроенный ассемблер см. гл.12). В этом разделе речь идет о программах, написанных и откомпилированных с помощью внешнего ассемблера, такого как, например, ассемблер фирмы MicroSoft или Turbo Assembler фирмы Borland. <br>
<br>
Машинно-ориентированный язык ассемблера предоставляет квалифицированному программисту богатейшие возможности использования всех особенностей архитектуры ПК. Ассемблерные программы выполняются значительно быстрее и занимают меньший объем памяти, чем программы, написанные на Турбо Паскале, однако низкий уровень языка ассемблера существенно снижает производительность труда программиста и резко усложняет отладку программ. Как правило, на языке ассемблера пишутся сравнительно небольшие фрагменты программ, в которых используются недоступные из Турбо Паскаля особенности архитектуры ПК.<br>
<br>
Внешняя процедура (функция) в программе, написанной на Турбо Паскале, объявляется своим заголовком, за которым следует стандартная директива EXTERNAL, например: <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">Function LoCase (ch : char):char; external;</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">Procedure Swapping (var a,b; N:word); external;</div></ol></div></div></div></div><br>
<br>
Как видно из этих примеров, тело внешней процедуры (функции) отсутствует - его заменяет директива EXTERNAL. Для подключения ассемблерной программы необходимо предварительно ее откомпилировать и получить объектный файл с расширением OBJ, содержащий перемещаемый код ассемблерной программы. Непосредственно перед описанием внешней процедуры (функции) в тело основной программы вставляется директива компилятора <span class="tag-color tag-color-named" data-value="blue" style="color: blue"><em class='tag-i'>{&#036;L&lt;имя файла&gt;}</em></span>, где &lt;имя файла&gt; - имя OBJ-файла. Диск и каталог, в котором следует искать этот файл, если он не обнаружен в текущем каталоге, указываются опцией OPTIONS/DIRECTORIES/OBJECT DIRECTORIES (см. прил. 1). <br>
<br>
Перед передачей управления внешней процедуре (функции) программа помещает параметры обращения в программный стек в том порядке, как они перечислены в заголовке процедуры (функции). Ассемблерная процедура должна сохранить регистры ВР, SP, SS и DS центрального процессора в самом начале своей работы и восстановить содержимое этих регистров перед возвратом управления в программу. Остальные регистры можно не сохранять и соответственно не восстанавливать. <br>
<br>
Параметры могут передаваться по ссылке или по значению. Если параметр передается по ссылке, в стек помещается указатель, содержащий абсолютный адрес параметра, если по значению - в стек помещается сам параметр, точнее - его значение. Все параметры-переменные, т.е. параметры, объявленные в заголовке с предшествующим словом VAR, всегда передаются по ссылке. Параметры-значения могут передаваться по ссылке или по значению в зависимости от длины внутреннего представления соответствующего параметра. В общем случае используется следующее правило: если длина внутреннего представления параметра-значения составляет 1, 2 или 4 байта, он передается своим значением, т.е. его значение помещается в стек. Точно так же через стек передаются и все вещественные данные длиной в 4, 6, 8 и 10 байт (в версии 4.0 эти данные передаются через стек сопроцессора 8087/80287, начиная с версии 5.0 -через стек центрального процессора 8086/80486). Во всех остальных случаях, если длина внутреннего представления больше 4 байт, соответствующий параметр передается по ссылке. <br>
<br>
Ассемблерные функции в зависимости от длины внутреннего представления результата должны возвращать его через регистры центрального процессора или сопроцессора по следующим правилам: <br>
<br>
длиной в 1 байт - в регистре AL; <br>
длиной в 2 байта - в регистре АХ; <br>
длиной в 4 байта - в регистрах DX:AX (старшее слово в DX); <br>
тип REAL (6 байт) - в регистрах DX:BX:AX; <br>
типы SINGLE, DOUBLE, EXTENDED и СОМР - через стек сопроцессора 8087/80486; <br>
указатели - в регистрах DX:AX (сегмент в DX); <br>
строки возвращаются по ссылке: адрес начала строки помещается в DX:AX (сегмент в DX). <br>
<br>
Все ассемблерные процедуры должны размещаться в сегменте с именем CODE или CSEG, или с именем, оканчивающимся на _ТЕХТ; инициализированные локальные Переменные помещаются в сегмент с именем CONST или с именем, оканчивающимся на _DATA. Все другие локальные переменные необходимо размещать в сегменте с именем DATA или DSEG, или с именем, оканчивающимся на _BSS. Любые другие объявления сегментов игнорируются. Все имена, объявленные в интерфейсной части модулей программы, написанной на Турбо Паскале, становятся доступны ассемблерной процедуре (функции) после их объявления директивой EXTRN. Точно так же все имена ассемблерных процедур и функций, которые должны быть доступны программе на Турбо Паскале, следует объявлять директивой PUBLIC. <br>
<br>
<div class='tag-align-right'><strong class='tag-b'>Ozzя ©</strong></div>]]></description>
        <author>Some1</author>
        <category>Pascal: Общие вопросы</category>
      </item>
	
      </channel>
      </rss>
	