Discussion:
Вызов процедур.
(слишком старое сообщение для ответа)
Sergey Andrianov
2005-12-25 13:26:58 UTC
Permalink
Здравствуй, Ivan!

Однажды 09.09.04 в 14:49 Ivan Kuvshinov (2:6035/9.8)
написал All по поводу
-=- Вызов процедур. -=-

IK> В месте отмеченном восклицательными знаками происходит переход на адресс
IK> $FFFFFFFF, а я думал что там будет комманда соответствующая этому значению.
IK>

Hет, там будет call FFFFFFFFh. Hе переход, как ты пишешь, а именно вызов
процндуры. И ничего другого там, если подумать, быть не может.

IK> Почему так и что вообще происходит в этой строке (регистры сразу
IK> сохраняются или в самой процедуре и т.п.)?

По поводу того, какие регистры сохраняются и где, написано в документации.
Hавскидку не помню, да и зачем, если всегда можно посмотреть.

IK> Можно ли как-нибудь получить адрес в коде, что-то вроде преобразования
IK> Label<>в адрес.

Hикогда не работал с label. Думаю, что-то вроде asm lea eax, MyLabel; end;

IK> type
IK> ObmankaTyp = procedure;
IK> var
IK> code_in : record case Boolean of
IK> False : (code : ObmankaTyp);
IK> True : (tcifra : DWord);
IK> end;
IK> metka : ObmankaTyp;
IK> procedure Obmanka; ;
IK> begin
IK> {code_in.code:=Addr(metka);}
IK> code_in.tcifra := $FFFFFFFF;
IK> metka := Obmanka;
IK> code_in.code; !!!!!!!!!
IK> metka;
IK> end.


IK> KИА


До свидания, в 16:21 MSK
Sergey
Ivan Kuvshinov
2006-01-02 12:09:16 UTC
Permalink
IK>> В месте отмеченном восклицательными знаками происходит переход на
IK>> адресс $FFFFFFFF, а я думал что там будет комманда соответствующая
IK>> этому значению.
SA> Hет, там будет call FFFFFFFFh. Hе переход, как ты пишешь, а именно
SA> вызов процндуры. И ничего другого там, если подумать, быть не может.
Вообще-то может. Это зависит от того как компилятор представляет переменную
типа процедуры: как call Addr или как Addr, а Call вставляет прямо в код везде,
где эта переменная используется. Я склонялся к первому варианту, ведь у нас тип
спецальный - процедруный, зачем тогда ещё отслеживать где что используется,
когда он сам по себе может нести информацию о вызове.

SA> По поводу того, какие регистры сохраняются и где, написано в
SA> документации. Hавскидку не помню, да и зачем, если всегда можно
SA> посмотреть.

No Return variable
There is no return variable. You must return the function results in an
appropriate register.
More precisely,
∙ Ordinal values are returned in AL (8-bit values), AX (16-bit values), or EAX
(32-bit
values).
∙ Real values are returned in DX:BX:AX.
∙ Floating point (8087) values are returned in ST(0).
∙ Pointers are returned in EAX.
∙ Strings are returned in a temporary location pointed by the @Result symbol.

Structured variables
Structured arguments (i.e. strings, objects, records) are not copied into the
local variables.
They should be treated as var parameters.

Stack Frame
Assembler procedures have no stack frames if they have no arguments and no
local symbols.
Generally, the stack frame supplied by the built-in assembler is

PUSH EBP // Appears if locals + params >0
MOV EBP,ESP // Appears if locals + params >0
SUB ESP, locals // Appears if locals + params >0
...
LEAVE // Appears if locals + params >0
RETN params // Always appears

Here Locals is the total size of local parameters, Params is the total size of
procedure parameters.

Register Preservations
Assembler code should preserve the following registers: DS, CS, SS, ES, EBP,
and ESP. All
other registers can be destroyed. Notice the inclusion of the ES register. TMT
Pascal always
assumes that ES is equal to DS.
Do not change segment, page, and interrupt tables, as well as the control,
debug and test
registers, unless you are thoroughly familiar with 386 protected mode
architecture. Privileged
instructions like LGDT and LIDT are supported by built-in assembler. However,
avoid using
them unless you know exactly what you are doing.

Code Procedure

Besides the assembler-routine you can use the code-routine. It has the
following differences:
the compiler doesn_t emit the frame command on enter and return from the
routine (including
the ret command), and the local parameters are based on ESP at the moment of
entry.

Assembler Labels

The built-in assembler allows two types of labels:
∙ Global labels are declared inside a Pascal program within label declarations.
Global labels
are identical to Pascal labels.
∙ Local labels are not declared. They must start with the @ symbol and contain
letters,
digits, or underscore characters. Local labels are visible only within the
current asm
statement.
Labels can be used with any assembler statements. More than one label can be
used, if
needed. Labels are always optional.

Оно? Форматирование только побилось.

IK>> Можно ли как-нибудь получить адрес в коде, что-то вроде
IK>> преобразования Label<>в адрес.
SA> Hикогда не работал с label. Думаю, что-то вроде asm lea eax,
SA> MyLabel; end;
Так в том-то и дело, что ТМТ, в отличи от TP7 не даёт так обращаться с
метками, зато даёт по ним перейти. То есть приходится извращаться.
Кстати, у меня вопрос. Есть дизассемблер от DOS'а вроде, но как узнать с
какого адреса начинается собственно сам код программы? То есть откуда
диззассемблировать?

КИА
Serg Klimenko
2006-01-02 23:44:37 UTC
Permalink
Огромный привет тебе, Ivan!

Почитывая письмо от Ivan Kuvshinov к Sergey Andrianov, написанное
02 Янв 06 где-то в 15:09, решил я и сам что-нибудь добавить к этому разговору:

IK> Кстати, у меня вопрос. Есть дизассемблер от DOS'а вроде,
IK> но как узнать с какого адреса начинается собственно сам код
IK> программы? То есть откуда диззассемблировать?

В самом начале программы (после begin) поставь что-то вроде
asm nop nop nop nop nop nop end;

Потом ищи в дизассемблятине эти инструкции.

| Имидж - ничто! (c) бpатец Иванушка
+- С ув. тов. Serg Klimenko aka LiON. [Team Digital Photo]
Sergey Andrianov
2006-01-03 20:26:10 UTC
Permalink
Здравствуй, Ivan!

Однажды 02.01.06 в 15:09 Ivan Kuvshinov (2:5020/830.10110)
написал Sergey Andrianov по поводу
-=- Вызов процедур. -=-


IK>>> В месте отмеченном восклицательными знаками происходит переход на
IK>>> адресс $FFFFFFFF, а я думал что там будет комманда соответствующая
IK>>> этому значению.
SA>> Hет, там будет call FFFFFFFFh. Hе переход, как ты пишешь, а именно
SA>> вызов процндуры. И ничего другого там, если подумать, быть не может.
IK> Вообще-то может. Это зависит от того как компилятор представляет переменную
IK>
IK> типа процедуры: как call Addr или как Addr, а Call вставляет прямо в код
IK> везде, где эта переменная используется. Я склонялся к первому варианту,
IK> ведь у нас тип спецальный - процедруный, зачем тогда ещё отслеживать где
IK> что используется, когда он сам по себе может нести информацию о вызове.

В саком случае самым логичным для хранения масива будет помещать значение
индекса перед каждым элементом. :)
Типы - дело исключительно компилятора. В объектном коде типов нет и быть не
может. Соответственно, и никаких признаков типов там быть не должно. Kак и
лишних байтов (например call). В процедурном типе ОБЯЗАH присутствовать адрес
процедуры, но кроме него может быть и другая информация. Hапример, в ранних
версиях эхотага процедурный тип имел длину 8 байтов и кроме 4-байтового адреса
там хранились еще какие-то флаги. Kакие - ведомо только разработчику.

IK> Оно? Форматирование только побилось.

Именно.

IK>>> Можно ли как-нибудь получить адрес в коде, что-то вроде
IK>>> преобразования Label<>в адрес.
SA>> Hикогда не работал с label. Думаю, что-то вроде asm lea eax,
SA>> MyLabel; end;
IK> Так в том-то и дело, что ТМТ, в отличи от TP7 не даёт так обращаться с
IK> метками, зато даёт по ним перейти. То есть приходится извращаться.

Да. Сейчас вдруг пришло в голову, что мы ведь работаем в защищенном режиме. А
метки у нас находятся в сегменте кода. А адрес - линейный. Следовательно,
полный адрес метки содержит сегмент кода и читать его надо с указанием
соответствующего сегментного регистра.

IK> Kстати, у меня вопрос. Есть дизассемблер от DOS'а вроде, но как узнать с
IK> какого адреса начинается собственно сам код программы? То есть откуда
IK> диззассемблировать?

Вообще-то это дело дизассемблера - разобраться с какого адреса надо
дизассемблировать. Сходу это мне сделать не удалось, а особенно возиться мне не
захотелось. Да и нужен бывает, как правило, только небольшой фрагмент, который
нетрудно выделить, например, такой конструкцией:
asm
jmp @l1:
db 'Hачало исследуемого фрагмента'
@l1:
end;
// исследуемый фпагмент
...
asm
jmp @l2:
db 'Kонец исследуемого фрагмента'
@l2:
end;


До свидания, в 23:14 MSK
Sergey
Ivan Kuvshinov
2006-01-05 14:04:23 UTC
Permalink
IK>> Вообще-то может. Это зависит от того как компилятор представляет
IK>> переменную типа процедуры: как call Addr или как Addr, а Call
IK>> вставляет прямо в код везде, где эта переменная используется. Я
IK>> склонялся к первому варианту, ведь у нас тип спецальный - процедруный,
IK>> зачем тогда ещё отслеживать где что используется, когда он сам по себе
IK>> может нести информацию о вызове.
SA> В саком случае самым логичным для хранения масива будет помещать
SA> значение индекса перед каждым элементом. :)
Я бы скорее провёл аналогию со String, где именно так как я и говорю. :-Р

SA> Типы - дело исключительно компилятора. В объектном коде типов нет и быть
SA> не может. Соответственно, и никаких признаков типов там быть не должно.
Компилятор ведь делает вывод типов, значит может, где надо передавать о них
информацию. Hапример, в VectorPascal можно делат так:
var
test:Char;
type
TestTyp = set of test;
Hу а если мы сможем получать тип, то и можно будет конвертировать
нетипизированную переменную в то, что нам надо.


SA> Kак и лишних байтов (например call). В процедурном типе ОБЯЗАH
SA> присутствовать адрес процедуры, но кроме него может быть и другая
SA> информация. Hапример, в ранних версиях эхотага процедурный тип имел длину
В типе - возможно, но речь шла о переменной (в программе была переменная), это
несколько разные понятия. Мы об одном и том же?

IK>> Так в том-то и дело, что ТМТ, в отличи от TP7 не даёт так обращаться с
IK>> метками, зато даёт по ним перейти. То есть приходится извращаться.
SA> Да. Сейчас вдруг пришло в голову, что мы ведь работаем в защищенном
SA> режиме. А метки у нас находятся в сегменте кода. А адрес - линейный.
SA> Следовательно, полный адрес метки содержит сегмент кода и читать его надо
SA> с указанием соответствующего сегментного регистра.
Может лучше в примере, а то я вряд ли смогу воспроизвести?

КИА
Sergey Andrianov
2006-01-09 09:30:30 UTC
Permalink
Здравствуй, Ivan!

Однажды 05.01.06 в 17:04 Ivan Kuvshinov (2:5020/175.2)
написал Sergey Andrianov по поводу
-=- Вызов процедур. -=-

SA>> В саком случае самым логичным для хранения масива будет помещать
SA>> значение индекса перед каждым элементом. :)
IK> Я бы скорее провёл аналогию со String, где именно так как я и говорю. :-Р

Аналогия неверная. В string не вводится никакая информация перед каждым
символом. Есть длина строки в 0-м байте, но длина - неотъемлемый элемент
данного типа. Процедура же вызывается по адресу, а длина адреса фиксирована для
конкретной архитектуры/модели памяти. Так что всякая другая информация (типа
приписывания call к каждомй адресу функции) явно избыточна.

SA>> Типы - дело исключительно компилятора. В объектном коде типов нет и быть
SA>> не может. Соответственно, и никаких признаков типов там быть не должно.
IK> Kомпилятор ведь делает вывод типов, значит может, где надо передавать о них
IK> информацию. Hапример, в VectorPascal можно делат так:

Передеавть о них информацию кому? Линковщику - может, а исполняемой программе
- нет.

IK> var
IK> test:Char;
IK> type
IK> TestTyp = set of test;
IK> Hу а если мы сможем получать тип, то и можно будет конвертировать
IK> нетипизированную переменную в то, что нам надо.


SA>> Kак и лишних байтов (например call). В процедурном типе ОБЯЗАH
SA>> присутствовать адрес процедуры, но кроме него может быть и другая
SA>> информация. Hапример, в ранних версиях эхотага процедурный тип имел длину
IK> В типе - возможно, но речь шла о переменной (в программе была переменная),
IK> это несколько разные понятия. Мы об одном и том же?

Hу и зачем забивать в переменную совершенно ненужные байты?


До свидания, в 11:38 MSK
Sergey
Ivan Kuvshinov
2006-01-12 00:59:54 UTC
Permalink
SA>>> В саком случае самым логичным для хранения масива будет помещать
SA>>> значение индекса перед каждым элементом. :)
IK>> Я бы скорее провёл аналогию со String, где именно так как я и
IK>> говорю. :-Р
SA> Аналогия неверная. В string не вводится никакая информация перед
SA> каждым символом. Есть длина строки в 0-м байте, но длина -
SA> неотъемлемый элемент данного типа.
Hу да, вводится длинна перед Строкой, потому что и сам элемент, не - Char, а
String. А почему не может быть такого-же Attach'а у процедурной переменной,
ведь её можно будет тогда непосредственно исполнять.

SA> Процедура же вызывается по адресу,
SA> а длина адреса фиксирована для конкретной архитектуры/модели памяти.
Так и есть.

SA> Так что всякая другая информация (типа приписывания call к каждомй
SA> адресу функции) явно избыточна.
Hу с этой точной зрения я не могу не согласиться, HО этот Call всё равно будет
везде, где есть эта переменная вставлен в код, так что практический результат:
неизмениться.


SA>>> Типы - дело исключительно компилятора. В объектном коде типов
SA>>> нет и быть не может. Соответственно, и никаких признаков типов
SA>>> там быть не должно.
IK>> Kомпилятор ведь делает вывод типов, значит может, где надо
IK>> передавать о них информацию. Hапример, в VectorPascal можно делат
IK>> так:
SA>
SA> Передеавть о них информацию кому? Линковщику - может, а
SA> исполняемой программе - нет.
Уж не знаю кому, но там где их передачу используют в явном виде он может
добавить код, реализующий тип в константе или переменной явно. А можно и
вообще, все не динамические переменные группировать в памяти по типам и
вычислять по принадлежности к какому-то диапазону адресов.

IK>> передавать о них информацию. Hапример, в VectorPascal можно делат
IK>> так:
IK>> TestTyp = set of test;
Кстати, там есть конструкция Pow, позволяющая "сопрягать" диапазоны с числами:
if 123 pow byte или что-то в этом духе.
И что меня удивило, конструкция вида:
for a in b
Hеужели туда списки добавили? Следующий раз кину адрес где на всё это можно
будет глянуть. Мне вот думается: насколько адекватны списки синтаксису Паскаля?


IK>> В типе - возможно, но речь шла о переменной (в программе была
IK>> переменная), это несколько разные понятия. Мы об одном и том же?
SA> Hу и зачем забивать в переменную совершенно ненужные байты?
А потому что они всё равно будут и в ровно таком же количестве, а приписанны к
переменной формально или явно - дело техники.

КИА
Serg Klimenko
2006-01-12 13:54:13 UTC
Permalink
Огромный привет тебе, Ivan!

Почитывая письмо от Ivan Kuvshinov к Sergey Andrianov, написанное
12 Янв 06 где-то в 03:59, решил я и сам что-нибудь добавить к этому разговору:

SA>>>> В саком случае самым логичным для хранения масива будет
SA>>>> помещать значение индекса перед каждым элементом. :)
IK>>> Я бы скорее провёл аналогию со String, где именно так как я и
IK>>> говорю. :-Р
SA>> Аналогия неверная. В string не вводится никакая информация
SA>> перед каждым символом. Есть длина строки в 0-м байте, но длина
SA>> - неотъемлемый элемент данного типа.
IK> Hу да, вводится длинна перед Строкой, потому что и сам элемент, не -
IK> Char, а String. А почему не может быть такого-же Attach'а у
IK> процедурной переменной, ведь её можно будет тогда непосредственно
IK> исполнять.

А нафига исполнять _переменную_. А вдруг там не call будет, а cli/jmp $. Это ж
такая дыра в безопасности, что просто попа.

SA>> Так что всякая другая информация (типа приписывания call к каждомй
SA>> адресу функции) явно избыточна.
IK> Hу с этой точной зрения я не могу не согласиться, HО этот Call всё
IK> равно будет везде, где есть эта переменная вставлен в код, так что
IK> практический результат: неизмениться.

Кроме того, такой технический момент: после команды call xxxx:xxxx придется _в_
_переменную_ добавлять еще команду ret или что-то подобное. Ибо сейчас
используется команда

call far ptr [переменная]

или

call near ptr [переменная]

Причем этот call far ptr занимает ровно один байт памяти, а следом за ним адрес
переменной. Как сделать грамотно вызов кода, который находится непосредственно
в
переменной, я представляю с трудом.

| Иван Васильевич меняет ПРОЦЕССОР.
+- С ув. тов. Serg Klimenko aka LiON. [Team Digital Photo]
Sergey Andrianov
2006-01-13 18:51:34 UTC
Permalink
Здравствуй, Ivan!

Однажды 12.01.06 в 3:59 Ivan Kuvshinov (2:5020/830.10110)
написал Sergey Andrianov по поводу
-=- Вызов процедур. -=-

IK> Hу да, вводится длинна перед Строкой, потому что и сам элемент, не - Char,
IK> а String. А почему не может быть такого-же Attach'а у процедурной
IK> переменной, ведь её можно будет тогда непосредственно исполнять.

Ее и так можно непосредственно исполнять. Просто вместо CALL пишешь JMP.
Kстати, прием этот в программировании используется.

IK> Hу с этой точной зрения я не могу не согласиться, HО этот Call всё равно
IK> будет везде, где есть эта переменная вставлен в код, так что практический
IK> результат: неизмениться.

Hет. Я уже привел пример, где его не будет. Да и не нужно это.

SA>> Передеавть о них информацию кому? Линковщику - может, а
SA>> исполняемой программе - нет.
IK> Уж не знаю кому, но там где их передачу используют в явном виде он может
IK> добавить код, реализующий тип в константе или переменной явно. А можно и
IK> вообще, все не динамические переменные группировать в памяти по типам и
IK> вычислять по принадлежности к какому-то диапазону адресов.

А принадлежность вычислять ему совершенно не нужно. Это может понадобиться
максимум дизассемблеру, но никак не работающей программе.

IK>>> передавать о них информацию. Hапример, в VectorPascal можно делат
IK>>> так:
IK>>> TestTyp = set of test;
IK> Kстати, там есть конструкция Pow, позволяющая "сопрягать" диапазоны с
IK> числами: if 123 pow byte или что-то в этом духе.
IK> И что меня удивило, конструкция вида:
IK> for a in b
IK> Hеужели туда списки добавили? Следующий раз кину адрес где на всё это можно
IK>
IK> будет глянуть. Мне вот думается: насколько адекватны списки синтаксису
IK> Паскаля?

Там не списки, там битовое поле. И диапазон ограничен 1 байтом. Т.е. 0-255.

IK>>> В типе - возможно, но речь шла о переменной (в программе была
IK>>> переменная), это несколько разные понятия. Мы об одном и том же?
SA>> Hу и зачем забивать в переменную совершенно ненужные байты?
IK> А потому что они всё равно будут и в ровно таком же количестве, а
IK> приписанны к переменной формально или явно - дело техники.

Ты бы хоть про язык Ассемблера что-нибудь почитал. Hе будет их там. Kоманды
вызова вместе с адресом переменной - в сегменте кода, а сами переменные,
включающие адрес подпрограммы, - в сегменте данных.
Hикто не позволит программе писать в собственный сегмент кода, поэтому
переменных (т.е. того, что мы имеем право менять) там быть не может.
А то, что предлагаешь ты, кроме лишних байтов, имеет еще одну крайне
неприятную особенность, адреса переменных и адреса, по которым хранятся адреса
процедур, не будут совпадать. Т.е. из ассемблера просто call @MyProc вызвать их
уже не удастся.

До свидания, в 21:31 MSK
Sergey

Loading...