При передаче longint(dword) из паскаля в asm значение обнуляется.. не пойму в чём дело

Тема в разделе "WASM.ASSEMBLER", создана пользователем gr_, 26 дек 2004.

  1. gr_

    gr_ New Member

    Публикаций:
    0
    Регистрация:
    26 дек 2004
    Сообщения:
    7
    Такая ситуция.. нужно передать в модуль на ассемблере (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`а, но всё таки хотелось сделать по-человечески :)
     
  2. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    В Delphi при "родных" соглашениях передачи параметров для передачи первых двух параметров (или одного int64) вроде бы используются регистры eax и edx (точно не помню - давно уже использую для внешних DLL соглашение stdcall, чего и всем другим советую). Если речь про Turbo/Borland Pascal, то скорее всего логика работы там такая же, только регистры в 2 раза короче. В общем, посмотри отладчиком, что у тебя кладется в регистры перед исполнением вызова.
     
  3. gr_

    gr_ New Member

    Публикаций:
    0
    Регистрация:
    26 дек 2004
    Сообщения:
    7
    Ничего не кладётся...
     
  4. Arvensis

    Arvensis New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2004
    Сообщения:
    72
    Адрес:
    Russia
    CyberManiac

    Это возврат двойного слова из функции производится через dx:ax, а параметры передаются через стэк, в прямом порядке.

    gr_

    Я удивляюсь, как ты это собрать сумел... у меня ничего не получается :) Это легально - линковать 16-битный паскалевский код с 32-битным ассемблерным? Приаттачь exe, если не сложно...
     
  5. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    Основная программа получает значение в регистрах EDX:EAX.

    То есть исправь прогу на ASM следующим образом:

    .code

    asmp proc near num:dword

    public asmp

    mov eax, num

    shld edx,eax,16 //к примеру(копировать старшие 16 разрядов из EAX в DX)

    ret

    Посему основная прогамма и получает 0.

    Это должно сработать.

    В Bodland С++ это происходит так, и в Паскале должно быть тоже так...

    Ну не силен я в Паскале....))
     
  6. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    Arvensis

    Это возврат двойного слова из функции производится через dx:ax, а параметры передаются через стэк, в прямом порядке.



    Чуток попутал названия, но по умолчанию передача параметров в Delphi действительно выполняется сначала через eax, edx, ecx и только потом, если не хватает регистров, через стек.
     
  7. gr_

    gr_ New Member

    Публикаций:
    0
    Регистрация:
    26 дек 2004
    Сообщения:
    7
    Arvensis

    В сборке магии не использовалось :) Код на ассемблере тоже 16и битный, компилировал tpc + tasm/tlink.



    vito

    Спасибо, но нет, это не сработает. Ни один регистр (ну кроме ip и sp) при переходе в модуль не изменяется... До mov eax, num в eax какой-то мусор оставшийся от begin`а, после - 0. Я на всякий случай конечно попробовал :)) но чуда не произошло...



    [​IMG] _1209824747__TEXT2.EXE



    ps. Всё-таки меня интригует что же он такое 4х байтное кладёт в стек... По виду - просто взятое с потолка число, т.е. это и не младшие/старшие байты dword`а, а просто нечто, вроде 25976d. Как указатель тоже вроде не работает...



    <sub>ой что-то форум сглючил... тут совсем удалять сообщения нельзя?</sub>
     
  8. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    gr_



    Так eax - 32х битный регистр.
     
  9. gr_

    gr_ New Member

    Публикаций:
    0
    Регистрация:
    26 дек 2004
    Сообщения:
    7
    "Код 16 битный" в смысле ДОСовский. Обычный Tasm под дос позволяет нормально использовать и 32 битные регистры.

    Tasm32 используется только для приложений win32, т.е. в моём случае его просто нельзя использовать. (хотя.. может и можно, но в любом случае не в этом дело :) если написать в конце модуля mov eax,462 в гл. программа получит именно 462. т.е. проблема только в получении dword из паскаля)
     
  10. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    Извини, не внимательно прочитал...

    Тебе нужно в ASM передать параметр а не наооборот.

    Тут все посложнее...

    Я механизм немного опишу,поэксперементируй, если не получится раскопаю старые разработки.

    Данные передаются через стек:
    Код (Text):
    1. {
    2. long num;// злесь С, но наверное можно адаптировать к Паскалю
    3. char *buffer;// указатель!
    4. asmp(buffer,num);//вызов прцедуры;
    5. }
    6.  
    7. //
    8. public asmp
    9. model large,pascal //????
    10. stack 100h
    11. .code
    12. asmp proc near С//!!!!
    13. ARG bufferPtr:word,num:dword \\установить параметры на стеке\\
    14. enter 0,0 \\установить кадр стека, второй параметр 0 для С
    15. (уровень вложенности процедур) для Паскаля???//
    16.  
    17. mov eax, num
    18. ret
    19. //


    Размещение в стеке.

    1. num

    2. Смещение буфера

    3. Адрес возврата

    4. SP,BP

    Написал, что смог вспомнить. Надеюсь поможет.
     
  11. vito

    vito New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2004
    Сообщения:
    177
    Да, чуть не забыл инициализируй стек в ASM.

    В общем довольно замутно, но у меня в 5 С все работает и именно под DOC.



    То есть твоя ошибка не- отработал стек в ACM.
     
  12. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Совсем человека запутали :-(

    Задача простая: 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)

    Эффект второй команды, впрочем, можно не заметить.
     
  13. gr_

    gr_ New Member

    Публикаций:
    0
    Регистрация:
    26 дек 2004
    Сообщения:
    7
    diamond

    Дааа.. Сколько я ни бился - так до этого и не додумался :) На самом деле всё работает, даже не верится :)))

    (Актуальность проблема конечно уже потеряла, т.к программа была просто переделана на С, но всё равно ОГРОМНОЕ СПАСИБО.)