Такая ситуция.. нужно передать в модуль на ассемблере (tasm) longint (т.е. dword) из осн. программы на паскале. Например так: pascal: var num:longint; function asmP (pnum:longint):integer;external; {$L D:\asmp.obj} begin num:=904; write(asmp(num)); end. asm: masm .386 model large,pascal stack 100h .code asmp proc near num:dword public asmp mov eax, num ret asmp endp end asmp В результате паскаль всегда выводит 0. (???) Пробовал через стэк вручную, без масмовского large,pascal. В стеке похоже оказывается 4х байтовое число. (?????) Вобщем вообще никаких идей что происходит... ps word`ы передаются нормально, и вообще-то можно dword разделить на два word`а, но всё таки хотелось сделать по-человечески
В Delphi при "родных" соглашениях передачи параметров для передачи первых двух параметров (или одного int64) вроде бы используются регистры eax и edx (точно не помню - давно уже использую для внешних DLL соглашение stdcall, чего и всем другим советую). Если речь про Turbo/Borland Pascal, то скорее всего логика работы там такая же, только регистры в 2 раза короче. В общем, посмотри отладчиком, что у тебя кладется в регистры перед исполнением вызова.
CyberManiac Это возврат двойного слова из функции производится через dx:ax, а параметры передаются через стэк, в прямом порядке. gr_ Я удивляюсь, как ты это собрать сумел... у меня ничего не получается Это легально - линковать 16-битный паскалевский код с 32-битным ассемблерным? Приаттачь exe, если не сложно...
Основная программа получает значение в регистрах EDX:EAX. То есть исправь прогу на ASM следующим образом: .code asmp proc near num:dword public asmp mov eax, num shld edx,eax,16 //к примеру(копировать старшие 16 разрядов из EAX в DX) ret Посему основная прогамма и получает 0. Это должно сработать. В Bodland С++ это происходит так, и в Паскале должно быть тоже так... Ну не силен я в Паскале....))
Arvensis Это возврат двойного слова из функции производится через dx:ax, а параметры передаются через стэк, в прямом порядке. Чуток попутал названия, но по умолчанию передача параметров в Delphi действительно выполняется сначала через eax, edx, ecx и только потом, если не хватает регистров, через стек.
Arvensis В сборке магии не использовалось Код на ассемблере тоже 16и битный, компилировал tpc + tasm/tlink. vito Спасибо, но нет, это не сработает. Ни один регистр (ну кроме ip и sp) при переходе в модуль не изменяется... До mov eax, num в eax какой-то мусор оставшийся от begin`а, после - 0. Я на всякий случай конечно попробовал ) но чуда не произошло... _1209824747__TEXT2.EXE ps. Всё-таки меня интригует что же он такое 4х байтное кладёт в стек... По виду - просто взятое с потолка число, т.е. это и не младшие/старшие байты dword`а, а просто нечто, вроде 25976d. Как указатель тоже вроде не работает... <sub>ой что-то форум сглючил... тут совсем удалять сообщения нельзя?</sub>
"Код 16 битный" в смысле ДОСовский. Обычный Tasm под дос позволяет нормально использовать и 32 битные регистры. Tasm32 используется только для приложений win32, т.е. в моём случае его просто нельзя использовать. (хотя.. может и можно, но в любом случае не в этом дело если написать в конце модуля mov eax,462 в гл. программа получит именно 462. т.е. проблема только в получении dword из паскаля)
Извини, не внимательно прочитал... Тебе нужно в ASM передать параметр а не наооборот. Тут все посложнее... Я механизм немного опишу,поэксперементируй, если не получится раскопаю старые разработки. Данные передаются через стек: Код (Text): { long num;// злесь С, но наверное можно адаптировать к Паскалю char *buffer;// указатель! asmp(buffer,num);//вызов прцедуры; } // public asmp model large,pascal //???? stack 100h .code asmp proc near С//!!!! ARG bufferPtr:word,num:dword \\установить параметры на стеке\\ enter 0,0 \\установить кадр стека, второй параметр 0 для С (уровень вложенности процедур) для Паскаля???// mov eax, num ret // Размещение в стеке. 1. num 2. Смещение буфера 3. Адрес возврата 4. SP,BP Написал, что смог вспомнить. Надеюсь поможет.
Да, чуть не забыл инициализируй стек в ASM. В общем довольно замутно, но у меня в 5 С все работает и именно под DOC. То есть твоя ошибка не- отработал стек в ACM.
Совсем человека запутали :-( Задача простая: DOS Turbo/Borland Pascal, который сроду ничего не оптимизировал, и TASM под DOS. Turbo Pascal, Delphi, Borland C[++] - три совершенно разные вещи! Первоначальный код будет работать, если исправить хитрую ошибку. Исправить ее можно двумя способами. Первый: переставить 1 и 2 строки (нумерация, естественно, с 0). Можно, впрочем, запихнуть .386 и дальше. Второй: сказать model use16 large,pascal. Ошибка заключается в следующем. Если сделать tdump asmp.obj, то можно заметить строку 000067 SEGDEF 1 : ASMP_TEXT DWORD PUBLIC USE32 Class 'Code' length 000b Это описание сегмента кода. TASM компилирует код, как если бы он был 32-битным! Происходит это потому, что сначала TASM видит .386, а потом model; в режиме 386+ ассемблер считает все происходящее 32-битным. Первый из способов выше сначала указывает TASM генерировать 16-битный код, а потом делает доступными 32-битные регистры. Второй способ явно специфицирует разрядность. В результате для исходного варианта TASM генерирует код mov eax,[ebp+8] без 32-битных префиксов. Поскольку код 16-разрядный, то процессор исполняет команду как mov ax,[di+8] со всеми вытекающими последствиями. (Кстати, в di оказывается адрес структуры TTextRec файла Output). Если вставить команду mov eax,904, ее "побайтный" эквивалент в 16-битном коде состоит из двух команд: mov ax,904 и add [bx+si],al (коды B8 88 03 00 00 и B8 88 03; 00 00) Эффект второй команды, впрочем, можно не заметить.
diamond Дааа.. Сколько я ни бился - так до этого и не додумался На самом деле всё работает, даже не верится )) (Актуальность проблема конечно уже потеряла, т.к программа была просто переделана на С, но всё равно ОГРОМНОЕ СПАСИБО.)