Discussion:
TMT паскаль задаёт всё новые загадки.
(слишком старое сообщение для ответа)
Ivan Kuvshinov
2006-05-19 19:27:01 UTC
Permalink
wormball
тмт паскаль задаёт всё новые загадки.

загадка n. когда я передавал объекты в функции по именам, вроде func(arg:
object_type), моя программа глючила и не работала, однако после того, как я
стал передавать их с помощью указателей, вроде func(arg: ^object_type), она
замечательно заработала.

загадка n+1. когда я вместо func(arg: object_type) поставил func(arg:
^object_type) и соответственно в теле функции написал arg^.run вместо arg.run,
моя программа заработала в 2 (!!) раза быстрее.

загадка n+2. когда у меня в строке uses значилось слово debug, та же программа
после нескольких минут нормальной работы выдавала general protection fault или
invalid floating point operation, однако после исключения данного слова
количество ошибок по крайней мере снизилось, в большинстве случаев они даже не
появляются, хотя иногда всё же имеют место быть, ума не приложу почему, ведь
вопервых она может работать безошибочно, а вовторых перед появлением ошибки
она несколько минут работает совершенно нормально. причём перераспределение
памяти происходит только в начале, а в процессе работы она обращается к уже
распределённой памяти. можно назвать ето загадкой n+3.

одним словом полтергейст ;D ;D

ещёфокус. я пишу

Procedure PutPixel(x, y: Longint; c: byte); code;
asm
mov eax, y
cmp eax, 0
js @end
cmp eax, 200
jns @end
imul eax, 320
mov edx, x
cmp edx, 0
js @end
cmp edx, 320
jns @end
add eax, edx
mov dl, c
mov byte ptr [bm+eax], dl
@end:
End;

, и она не работает, однако когда я пишу

Procedure PutPixel(x, y: Longint; c: byte); assembler;
, такая же процедура работает.

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

Почитывая письмо от Ivan Kuvshinov к All, написанное
wormball
IK> тмт паскаль задаёт всё новые загадки.

Загадки-то все с очевидными ответами. Думал за неделю кто-нибудь ответит, но
вот у самого время появилось.

IK> загадка n. когда я передавал объекты в функции по именам, вроде
IK> func(arg: object_type), моя программа глючила и не работала, однако
IK> после того, как я стал передавать их с помощью указателей, вроде
IK> func(arg: ^object_type), она замечательно заработала.

Ессно. В первом случае объект передается по значению, то есть создается
локальная копия объекта, в которой производятся изменения, а потом они теряются
и не передаются обратно. Когда ты стал передавать указатель, изменения стали
сохраняться в основной копии и все стало работать как надо. Обычно в таких
случаях просто делают var параметр.

IK> загадка n+1. когда я вместо func(arg: object_type) поставил func(arg:
IK> ^object_type) и соответственно в теле функции написал arg^.run вместо
IK> arg.run, моя программа заработала в 2 (!!) раза быстрее.

См. выше. Hе надо создавать копию объекта и терять на это время.

IK> загадка n+2. когда у меня в строке uses значилось слово debug, та же
IK> программа после нескольких минут нормальной работы выдавала general
IK> protection fault или invalid floating point operation, однако после
IK> исключения данного слова количество ошибок по крайней мере снизилось,
IK> в большинстве случаев они даже не появляются, хотя иногда всё же имеют
IK> место быть, ума не приложу почему, ведь вопервых она может работать
IK> безошибочно, а вовторых перед появлением ошибки она несколько минут
IK> работает совершенно нормально. причём перераспределение памяти
IK> происходит только в начале, а в процессе работы она обращается к уже
IK> распределённой памяти. можно назвать ето загадкой n+3.

Тут фиг знает. Где-то неаккуратно написано, и debug при своей работе на это
влияет. Hадо детально шерстить код.

IK> одним словом полтергейст ;D ;D

IK> ещёфокус. я пишу

IK> Procedure PutPixel(x, y: Longint; c: byte); code;
IK> asm
IK> mov eax, y
IK> cmp eax, 0
IK> js @end
IK> cmp eax, 200
IK> jns @end
IK> imul eax, 320
IK> mov edx, x
IK> cmp edx, 0
IK> js @end
IK> cmp edx, 320
IK> jns @end
IK> add eax, edx
IK> mov dl, c
IK> mov byte ptr [bm+eax], dl
IK> @end:
IK> End;

IK> , и она не работает, однако когда я пишу

IK> Procedure PutPixel(x, y: Longint; c: byte); assembler;
IK> , такая же процедура работает.

Тут тоже очевидно. code - прямо вставляется в код без обвязки. А ты руками не
устанавливаешь стек, да еще и регистры портишь. А assembler все это за тебя
делает - все начинает работать нормально. В таких вот случаях стоит смотреть
дизассемблятину - очень просветляет мозги.

┌ Интерфакс сообщает: В тайге найдены люди исполняющие указы президента.
└─ С ув. тов. Serg Klimenko aka LiON. [Team Digital Photo]
Ivan Kuvshinov
2006-05-23 18:59:31 UTC
Permalink
IK>> загадка n. когда я передавал объекты в функции по именам, вроде
IK>> func(arg: object_type), моя программа глючила и не работала, однако
IK>> после того, как я стал передавать их с помощью указателей, вроде
IK>> func(arg: ^object_type), она замечательно заработала.
Вообще-то письмо было с форума, написанное пару лет назад, просто я не
слишком разбираюсь в объектных типах и тоже не обнаружил причины (ответа на
форуме тоже не было).
Hо мне и сейчас не совсем понятно, ведь объекты - это фактически и есть
ссылки на таблицу вируальных методов (может быть здесь статические и в этом
всё дело?), то есть такая запись равносильна func(arg:Pointer); а вторая точно
такая же, только добавляется лишнее звено, и точно так же будет создаваться
копия этого указателя и потом затираться, мне не понятна причина ускорения в
два раза, разьве что из-за статической типизации.

SK> Ессно. В первом случае объект передается по значению, то есть создается
SK> локальная копия объекта, в которой производятся изменения, а потом они
SK> теряются и не передаются обратно.
Hе знаю как с объектами, а если бы там был тип ^Byte или TByte=^Byte, то это
не имело бы значения и было бы равносильно типу Pointer, то есть компилятор
реагировал бы только на самую "верхушку" - её бы передавал указанным с помощью
var, const и т.п. способом.

SK> Тут тоже очевидно. code - прямо вставляется в код без обвязки. А ты
SK> руками не устанавливаешь стек, да еще и регистры портишь. А assembler все
А я думал, что регистры некоторые портить можно, например eax,ebx,ecx,
разьве нет и тоже надо их восстанавливать и, соответственно со стеком
париться?

КИА
Serg Klimenko
2006-05-24 04:04:00 UTC
Permalink
Огромный привет тебе, Ivan!

Почитывая письмо от Ivan Kuvshinov к Serg Klimenko, написанное
23 Май 06 где-то в 23:59, решил я и сам что-нибудь добавить к этому разговору:

IK>>> загадка n. когда я передавал объекты в функции по именам, вроде
IK>>> func(arg: object_type), моя программа глючила и не работала,
IK>>> однако после того, как я стал передавать их с помощью
IK>>> указателей, вроде func(arg: ^object_type), она замечательно
IK>>> заработала.
IK> Вообще-то письмо было с форума, написанное пару лет назад, просто я
IK> не слишком разбираюсь в объектных типах и тоже не обнаружил причины
IK> (ответа на форуме тоже не было). Hо мне и сейчас не совсем понятно,
IK> ведь объекты - это фактически и есть ссылки на таблицу вируальных
IK> методов (может быть здесь статические и в этом всё дело?), то есть
IK> такая запись равносильна func(arg:Pointer); а вторая точно такая же,
IK> только добавляется лишнее звено, и точно так же будет
IK> создаваться копия этого указателя и потом затираться, мне не понятна
IK> причина ускорения в два раза, разьве что из-за статической типизации.

В самом объекте хранятся ссылки на его методы. То есть 20 методов - 20 ссылок.
Hо дело даже не в этом. В самом объекте хранятся его данные, то есть значения
всех внутренних переменных. И когда ты передаешь просто object_type, то вся эта
конструкция копируется. Если же ты передашь по var или по ^object_type, то
передается указатель на существующую копию.

SK>> Ессно. В первом случае объект передается по значению, то есть
SK>> создается локальная копия объекта, в которой производятся
SK>> изменения, а потом они теряются и не передаются обратно.
IK> Hе знаю как с объектами, а если бы там был тип ^Byte или
IK> TByte=^Byte, то это не имело бы значения и было бы равносильно типу
IK> Pointer, то есть компилятор реагировал бы только на самую "верхушку" -
IK> её бы передавал указанным с помощью var, const и т.п. способом.

Там типы существенно более простые и легкие. А вот со строками или со
структурами можешь такое проверить.

SK>> Тут тоже очевидно. code - прямо вставляется в код без обвязки. А
SK>> ты руками не устанавливаешь стек, да еще и регистры портишь. А
SK>> assembler все
IK> А я думал, что регистры некоторые портить можно, например
IK> eax,ebx,ecx, разьве нет и тоже надо их восстанавливать и,
IK> соответственно со стеком париться?

Hет, париться не надо. Hадо использовать директиву assembler. А директиву code
использовать только тогда, когда ты точно знаешь _зачем_ тебе надо руками
следить за регистрами и за стеком. У меня такое было только один раз, когда я
писал переключение контекстов процедур (aka кооперативную многозадачность), но
там без такого ничего не вышло бы.

А по поводу регистров, вот код из той программы. А перед этим он был выдран
дизассемблером из того, что генерит сам TMT.

=== Так, все дружно начали есть Windows Clipboard ===
push ebp
mov ebp,esp
push ebx
push ecx
push edx
=== Так, все дружно кончили есть Windows Clipboard ===

Соответственно, вот эти регистры портить нельзя.

┌ Hе зная броду, не суй.
└─ С ув. тов. Serg Klimenko aka LiON. [Team Digital Photo]
Loading...