Вопрос

No comments
  • > Давай у любого отвлечённого человека (не знающего про наш спор), но понимающего, что такое двоичная, десятичная, шестнадцатеричная системы исчисления, попросим
    > перевести число $FFFFFFFF или 11111111111111111111111111111111 ?
    > Кто нибудь его переведёт как (-1) "минус один"?

    Если он программирует на ассемблере, то скажет, что это либо -1, либо 0xFFFFFFFF.
    Если вернуться к тому, с чего все началось, я не вижу особой необходимости записывать число -1 как 0xFFFFFFFF, потому что "так правильно, и в регистре якобы только так и хранится", особенно если ассемблер поддерживает запись -1.
    Например, если в документации к функции написано, что в случае ошибки она возвращает -1, и фактически у нее перед ret написано mov eax, -1 (ну или xor eax, eax и dec eax), то я буду проверять возвращенное значение на равенство -1, а не на равенство с 0xFFFFFFFF, тем более что если есть версии этой функции под 16 бит, под 32 бита, под 64 бита, то проще сравнивать возвращенное значение именно с -1, а не с разными числами для каждой версии функции. То же и с входными параметрами.
  • Ага, лучше сравнивать с -1.
    Например -1 в 32: 0xFFFFFFFF
    А -1 в 16 соответственно: 0xFFFF
    а если -12, ты же не будешь в уме делать преобразования
    mov eax,12
    not eax
    inc eax
  • [quote="pavelyakov"]Ага, лучше сравнивать с -1.
    Например -1 в 32: 0xFFFFFFFF
    А -1 в 16 соответственно: 0xFFFF
    а если -12, ты же не будешь в уме делать преобразования
    mov eax,12
    not eax
    inc eax[/quote]
    pavelyakov, а тебе не кажется глупым, что когда я вызываю сис.функции (любые), кроме выхода, то их номер не зависит от 32 и 16 битности и любой другой битности ячейки, а вот функция выхода, в 32, она = $FFFFFFFF (4294967295) в 16, она равно $FFFF (65535), а в 8 ? а в 48 ? а в 64 ? 128 ? - это всё по сути разные значения!
    Ребята, В ДАННОМ МОМЕНТЕ это попросту глупость!
  • Ладно, :-) вопрос в следующем:
    Когда я вызываю эту функцию, что происходит для программы ? - она делает не медленный выход не вызывает никаких финализаций самой программы, так ? Т.е. для самой программы,это "тупо" её "обнуление" и "выбрасывание в сторону", так ?
  • ДОП. т.е аналогичнно команде дельфи Halt ?

    procedure Halt [ ( Exitcode: Integer) ];



    Halt performs an abnormal termination of a program and returns to the operating system.

    To perform a normal termination of a Delphi application, call the Terminate method on the global Application object. If the application does not use a unit that provides an Application object, call the Exit procedure from the main Program block.

    Exitcode is an optional expression that specifies an exit code for the program.


    Останов выполняет аварийное завершение программы и возвращается операционной системе.

    Для того, чтобы выполнять нормальное завершение приложения Delphi, назовите метод Terminate на глобальном Прикладном объекте. Если приложение не использует устройство, которое обеспечивает Прикладной объект, назовите Выходную процедуру из основного Программного блока.

    Exitcode - дополнительное выражение, которое определяет выходной код для программы.
  • В том то и особенность -1, что эта цифра не зависит от битности. Всегда 2 - 3 = -1, а -1 + 3 = 2, то есть FFFFFFFF = FFFF = FF

    Действительно, то что ты собираешься сделать — не говнокод. Это индусский код. Я бы даже сказал, песни и пляски под народные ударные инструменты. Я вообще не могу понять, какие могут быть проблемы с вызовом подпрограмм, чтоб такое городить. Давай всё таки попытаемся разобраться. Со стеком вроде всё правильно, но вот обрати внимание на изменения регистра ebx.
  • [quote="Pathoswithin"] Действительно, то что ты собираешься сделать — не говнокод. Это индусский код. Я бы даже сказал, песни и пляски под народные ударные инструменты.[/quote]
    Да хоть китайский код! :-) Такой дельфи создает и считается приемлимым! Чем он не отпимальный ? Чем он недостоен для сущетсвования и работы его ? Он что систему подглючивать будет ? Неоправданно много памяти "жрёт" ? или еще чего-то ?

    [quote="Pathoswithin"] Я вообще не могу понять, какие могут быть проблемы с вызовом подпрограмм, чтоб такое городить. Давай всё таки попытаемся разобраться. [/quote]
    Поначалу это "тупо перестраховка" по моей неопытности. Далее видно будет!
    Вот уже мысля появилась, что почему бы всю программу не написать на делфи и перекинуть её целиком и полностью, а не попроцедурно, вот тогда там "танцев с бубном" точно не будет, ну между процедурами это уж точно, дак как всё будет сделано дельфи и вызов из процедуры процедуру тоже! А уж вызов int 40, можно будет скорректировать, ну или оставить "танці с бубном", :-) фиг с ним, пойдёт работать ведь будет, вреда наносить никому и ничему не будет! :-)
    [quote="Pathoswithin"] Со стеком вроде всё правильно, но вот обрати внимание на изменения регистра ebx.[/quote]
    И что я должен бы понять с регистром ebx ? В каком моменте ? Чего там не так ?
  • mov ebx,[ebp+$0c]
    dec ebx
    test ebx,ebx
    jb @STR37
    inc ebx
    xor edi,edi
    @STR23:
    ...
    call setEBX_
    ...
    dec ebx
    jnz @STR23
    @STR37:
  • call INT0x40D сохраняет ebx?
  • Ещё я не понял, зачем вообще нужны подпрограммы вроде "setEBX_", укладывающие значение в переменную. Но вот это явно неправильный подход, с которым нужно разбираться:
    mov [@esp_],esp
    Call Draw
    mov esp,[@esp_]
    Причём то, что программа вообще доходит до последней строки, говорит нам что команда ret получает из стека правильный адрес возврата.
    Кстати, на счёт передачи трёх параметров в регистрах, скажи спасибо delphi. В других языках все параметры передаются через стек.
  • Pathoswithin, ты конечно хороший парень, :-) и мне бывает подсказываешь и очень даже по делу, мне это нравится, но...
    скрывать не стану, иногда ты меня злишь и утомляешь! :-( :-)
    Скачай пожалуйста последний архив урока (урок05) и рассмотри все файлы архива очень внимательно! Дельфи файлы, фасм файлы, вообщем всё рассмотри. (Если не получается скачать с майлру, напиши куда тебе закачать его чтобы ты мог скачать.)

    Представь ситуацию: Я пишу на дельфи, вырезаю асмовский код , вставляю его в асм-вставки дельфи, "прямой" КОСовской int40 в дельфи нет, она сделана в виде процедуры, процедура написана на дельфи, которая используется вызывает процедуру из KOS.dll, передавать параметры надо через переменные (кортеж переменных Var eax_,ebx_,ecx_,edx_,esi_,edi_:Cardinal;), в переменные надо передавать значения регистров, для этого созданы процедуры procedure setEAX_(c:cardinal); procedure setEBX_(c:cardinal);
    procedure setECX_(c:cardinal); procedure setEDX_(c:cardinal); procedure setESI_(c:cardinal);
    procedure setEDI_(c:cardinal);... так же чтобы было видно и понятно в результирующем дельфи коде
    далее для чтобы чтобы, испытав в амовских вставках дельфи, меньше морочится при "переброске" в Фасм, созданы аналогичные кортеж-переменные и процедуры установки их значений.... и т.д.
    Т.е. при написание и испытании программы процедуры написанные на дельфи, чтобы вызвать аналог int40, нужна процедура INT0x40D;, а из асм-вставок-дельфи, чтобы вызывать нужна INT0x40;.... идёт "смесь" вызовов из процедур написанных на дельфи и асм-вставок.... и т.д.

    И тут является Pathoswithin, который не хочет в этом всём разобраться (потому что даже исходников не смотрел), (хотя пишет что хочет разобраться). и начинает мне рассказывать про то что те процедуры setEDX_ лишние, а нафига они мол нужны и т.д.
    Дорогой Pathoswithin, я всё таки не на "прямую" в фасме пишу, а видишь как делаю, и надо чтобы это всё происходило максимально корректно, быстро, эфективно и работало к тому же.А "палировкой" можно заняться позже и то если оно нужно будет. Скачай пожалуйста урок5, прежде чем критиковать setEDX_ и прочее, расмотри, представть как оно всё происходит, а лучше сам попробуй сделать как я делал.
  • Я понял, твой "кортеж переменных" находится внутри KOS.dll. Но это будет проблемой, если ты захочешь реализовать многопоточность. Логичней передавать INT0x40/INT0x40D указатель на структуру регистров, которая находится в самой программе или выделяется динамически, тогда и специальные процедуры типа setEAX_ не понадобятся.

    Хотя, меня больше интересует, из-за чего у тебя на ровном месте стек не сходится, что ты ещё и "кортеж параметров" собираешься городить.
  • [quote="Pathoswithin"]Я понял, твой "кортеж переменных" находится внутри KOS.dll. Но это будет проблемой, если ты захочешь реализовать многопоточность. Логичней передавать INT0x40/INT0x40D указатель на структуру регистров, которая находится в самой программе или выделяется динамически, тогда и специальные процедуры типа setEAX_ не понадобятся.

    Хотя, меня больше интересует, из-за чего у тебя на ровном месте стек не сходится, что ты ещё и "кортеж параметров" собираешься городить.[/quote]


    Pathoswithin, то что ты мне сейчас пишешь, ( "Логичней передавать INT0x40/INT0x40D указатель на структуру регистров..." ) для меня это сложновато! :-( :-) Я всё таки новичок! Даже если я и пойму (вникну) в написанное, то его еще надо реализовывать и "обкатывать".

    Думаю однажды всё сойдется (это я о стеке), ну а кортеж всё равно нужен, гадом буду... :-) если каждая процедура будет "завязана" на кортеж, то каждая процедура будет понятней (по крайней мере мне), да и компилироваться она будет каждый раз одинаково и в этом можно быть уверенным, т.е. понимаешь, если ты применишь процедуру в дельфи где передаётся несколько параметров фиксированных (констант) и переменных, то она скомпилируется в одном виде, потом решишь, еще раз применить процедуру, - она скомпилированна будет по другому, уже с учётом двух вызовов этой процедуры с разным кол-вом констант и переменных в разных местах, что добавляет лишнюю мороку при рассмотрении кода (мне во всяком случае). А вот если будет "завязана" на кортеж, где будут все (всегда) переменные, то она будет каждый раз компилирована одинаково, да и мне понятней будет КОД1 чем КОД2 (см.ниже).
    О стеке."чего у тебя на ровном месте стек не сходится" - а он точно не сходится ? То я вообще-то (как уже писал) для перестраховки, что-бы уж точно сходился! Понимаешь, процедура компилированная дельфи ведь не расчитана на "врезки" в неё КОСовских вызовов int40. Ну это хорошо, если какая нить функция КОС из int40 не изменят никакого регистра или или со стеком всё так как надо компилированой дельфи процедуре из которой вызывается int40, а если всё таки нет, не так как надо, если всё таки возвраты значений на которые не расчитано. Ведь не обязательно же будет вызов int40 одним из последних в компилированной процедуре.
    Короче говоря, вот представь себе, что тебе внутрь твоей написанной процедуры нужно сделать врезку Call primer, причём врезка должна быть универсальной и может быть вставлена в любое (абсолютно любое) место твоей любой процедуры, как ты построишь процедуру "primer" ? - правильно заПУШИШЬ значения, и сохранишь позицию стека, а после выполнения, вернёшь всё обратно! Так ведь !? Ну это чтобы без лишних хлопот. Ну вот и у меня так:

    primer:
    Pusha
    mov [ESP_], esp
    ; А ЗДЕСЬ ВНУТРИ ЭТОЙ ПРОЦЕДУРЫ ХОТЬ "НА УШАХ СТОЙ"!
    ; ДА ХОТЬ НЕКОРРЕКТНО ПУШУЙ и прочие некоректности делай!
    ; И ТАКУЮ ПРОЦЕДУРУ МОЖНО ВРЕЗАТЬ В ЛЮБОЕ МЕСТО ЛЮБОЙ ПРОЦЕДУРЫ ИЛИ ПРОГРАММЫ
    ; НЕ БОЯСЬ НИ ЗА КАКИЕ ПОСЛЕДСТВИЯ ДЛЯ ВЫЗЫВАЕМОЙ ПРОЦЕДУРЫ!
    ; ИЛИ Я НЕ ПРАВ ?!
    mov esp,[ESP_]
    popa

    ================================================

    КОД1:
    mov eax,Param1
    push eax
    mov eax,Param2
    push eax
    ....
    call ....

    КОД2:
    mov eax,[ebp+$18]
    push eax
    mov eax,[ebp+$14]
    push eax
    ..............
    call ......
  • Pathoswithin, попробовал через кортеж для передачи данных в процедуру (будет и второй кортеж, для приёма данных из процедуры) увидел множество плюсов в этом. Настолько много, что облегчение почувствувал и уверенность....

    1. Кол-во регистров используется больше, видимо быстродействие и эфективность будет тоже больше и лучше.
    2. Симпатично и понятно выглядит часть кода где передаются параметры.
    3. Единой процедурой, т.е. без вызова процедуры в процедуре как при передачи через стек (см.пример ниже).
    4. Поскольку кортеж отдельный для приёма и передачи данных, то вызывая сразу же (повторно) эту же процедуру, можно менять только те параметры, которые отличаются от предыдущего вызова (см. пример ниже, там показано, где отличается только лишь параметр ParamCO6 )
    5. Размер процедуры: со стеком 62 строки чистыми строками , через кортеж 66 строк чистыми строками. (Прим. Чётко в одной строке асм-одна команда, без строк коментов и лишних отступов).
    6. Размер блока передачи данный в процедуру:
    При первом вызове процедуры:
    со стеком 7 строк, через кортеж 7 строк
    При повторном вызове той же процедуры сразу, изменив всего лишь один параметр:
    со стеком 7 строк, через кортеж 2
    7 Поочерёдность передачи данных в процедуры:
    со стеком: в определенной проследовательности некототорые параметры (которые через push). Обязательная передача параметров (которые через push)
    с кортежом: в любой последовательности, необязательная передача параметров

    Примеры для сравнения.
    Предыдущий способ передачи параметров (через стек) и вызов процедуры
    DrawXLineP:
    push $00ffffff //ColorLine -цвет
    push $03 //Thickness - Толщина
    push $00 // drawTypedraw - тип рисования.....
    mov ecx,$0000000a //lengthLine - длина линии
    mov edx,$0000000a // PosY- Левый верхний угол линии
    mov eax,$0000000a // PosX- Левый верхний угол линии
    call @DrawXLine
    ret
    @DrawXLine: //DrawXLine
    ........................
    ret $000c



    Способ передачи через кортеж и вызов процедуры.

    mov [ParamCO1],50
    mov [ParamCO2],50
    mov [ParamCO3],30
    mov [ParamCO4],$FFFFFF
    mov [ParamCO5],5
    mov [ParamCO6],1
    call DrawXLineA2;

    DrawXLineA2:
    push ebx
    push esi
    push edi
    push ebp
    add esp,-$0c

    mov ebp,[ParamCO1] ; x- Левый верхний угол линии
    mov ebx,[ParamCO2] ; y- Левый верхний угол линии
    mov edx,[ParamCO3] ; - длина линии
    mov eax,[ParamCO4] ; --цвет
    mov [esp],eax
    mov eax,[ParamCO5] ; - - Толщина
    mov ecx,[ParamCO6] ; -тип рисования
    ......................
    ret


    Способ передачи параметров и двойного вызова подряд одной и той же процедуры с изменённым одним параметром.

    Предыдущий способ (через стек).

    push $ffffff ;//ColorLine -цвет
    push 5 ;//Thickness - Толщина
    push 0 ;// drawTypedraw - тип рисования

    mov ecx,30 ;//lengthLine - длина линии
    mov edx,50 ;// PosY- Левый верхний угол линии
    mov eax,50 ;// PosX- Левый верхний угол линии
    call DrawXLineA;

    push $ffffff ;//ColorLine -цвет
    push 5 ;//Thickness - Толщина
    push 1 ;// drawTypedraw - тип рисования
    mov ecx,30 ;//lengthLine - длина линии
    mov edx,50 ;// PosY- Левый верхний угол линии
    mov eax,50 ;// PosX- Левый верхний угол линии
    call DrawXLineA;



    Через кортеж.

    mov [ParamCO1],50
    mov [ParamCO2],50
    mov [ParamCO3],30
    mov [ParamCO4],$FFFFFF
    mov [ParamCO5],5
    mov [ParamCO6],1
    call DrawXLineA2;

    mov [ParamCO6],0
    call DrawXLineA2;
  • Who is online

    Users browsing this forum: Bing [Bot] and 31 guests