На этом шаге мы рассмотрим использование ассемблера и Delphi.
Транслятор Delphi также вносит незначительные нюансы в данную проблему. Для сегмента кода нам придется взять название CODE. Из-за того, что строки Паскаль понимает несколько иначе, чем, скажем, Си, в качестве строк пришлось взять символьный массив. Впрочем, оператор writeln оказался довольно интеллектуальным и понял все с полуслова. Обратите внимание, что директива stdcall используется и в данном случае.
Создадим консольное приложение в Delphi. Для этого выполним File | New | Other... и на вкладке New выберем Console Application:
Рис.1. Создание консольного приложения
Затем в файле Project1.dpr наберем следующий текст:
program Project1; {$APPTYPE CONSOLE} uses SysUtils; {$l 'pr88_2.obj'} procedure COPYSTR(s1, s2:PChar); stdcall; EXTERNAL; var s1,s2:array [1..30] of char; begin { TODO -oUser -cConsole Main : Insert code here } s2[1]:= 'P'; s2[2]:= 'r'; s2[3]:= 'i'; s2[4]:= 'v'; s2[5]:= 'e'; s2[6]:= 't'; s2[7]:=char(0); COPYSTR(addr(s1[1]),addr(s2[1])); writeln(s1); readln; end.
Ассемблерный файл:
.386P ;Эта процедура будет вызываться из внешнего модуля. PUBLIC COPYSTR ;Плоская модель. .MODEL FLAT, stdcall CODE SEGMENT DWORD PUBLIC USE32 'CODE' ;Процедура копирования одной строки в другую. ;Строка, куда копировать - [ЕВР+08Н]. ;Строка, что копировать - [ЕВР+0CН]. ;Не учитывает длину строки, куда производится копирование. COPYSTR PROC PUSH EBP MOV EBP,ESP MOV ESI,DWORD PTR [EBP+0CH] MOV EDI,DWORD PTR [EBP+08H] L1: MOV AL,BYTE PTR [ESI] MOV BYTE PTR [EDI],AL CMP AL,0 JE L2 INC ESI INC EDI JMP L1 L2: MOV EAX,DWORD PTR [EBP+08H] POP EBP RET 8 COPYSTR ENDP CODE ENDS END
Перед выполнением приложения вам достаточно только подготовить объектный модуль (с помощью транслятора TASM32) и указать его в директиве {$L pr88_2.obj} после чего транслятор сделает все сам.
Результат работы приложения изображен на рисунке 2:
Рис.2. Результат работы приложения
На следующем шаге мы рассмотрим передачу параметров через регистры.