Автор | Сообщение |
|
| |
Пост N: 26
Зарегистрирован: 07.08.06
|
|
Отправлено: 12.10.06 02:59. Заголовок: Битовый сдвиг чисел в клиппере. Это возможно или нет ?
Hi all. Кто-нибудь знает, есть ли в штатных средствах клиппера возможность выполнить над числом битовый сдвиг на N разрядов вправо/влево ? (т.е. не делить/умножать на степень числа 2, а именно СДВИНУТЬ биты исходного числа и получить результат, как в АСМе SHR/SHL)
|
|
|
Новых ответов нет
, стр:
1
2
All
[см. все]
|
|
|
| постоянный участник
|
Пост N: 4
Зарегистрирован: 09.10.06
|
|
Отправлено: 12.10.06 09:04. Заголовок: Re:
В штатных средствах клиппера возможности работы с битами нет, есть в xHarbour. Но есть возможность или использовать библиотеки сt, nanfor или написать самомому на что-то С/ASM и подключить к Clipper с помощью extend.api/extasm.inc.
|
|
|
|
| постоянный участник
|
Пост N: 217
Зарегистрирован: 17.05.05
|
|
Отправлено: 12.10.06 13:12. Заголовок: Re:
Есть внутренние функции Clipper, точнее скорей всего это функции Microsoft C, на котором написан Clipper, которые выполняют сдвиг вправо и влево (какой-то из них по-моему арифметический сдвиг, то есть с учетом знака числа). То есть надо всего лишь написать функцию, которая принимает один параметр в ренистры AX:DX (в Clipper целые числа хранятся в виде двух слов) и передать их на вход этой внутренней функции, а затем вернуть результат. Параметр можно принять (если писать на ассемблере) с помощью функции __lparam. Например mov ax,1 call __lparam,ax ; DX:AX - target value Затем вызвать внутреннюю функцию Clipper (Microsoft С), передав ей значения в регистрах DX:AX. А затем вернуть значение с помощью функции __retnl call __retnl,ax,dx ret Вот и вся программа!
|
|
|
|
| |
Пост N: 38
Зарегистрирован: 06.06.06
|
|
Отправлено: 12.10.06 16:31. Заголовок: Re:
Есть в Clipper Tools функция: NUMROL() - Выполняет циклический сдвиг 16-битового слова. Описание Функция позволяет осуществить циклический сдвиг влево битов 16-битового слова с числовым значением в диапазоне от 0 до 65535. При сдвиге бит, выходящий за разрядную сетку слева, переносится в самый правый разряд. Параметр <lLowByte> позволяет задать сдвиг только младшего байта слова.
|
|
|
|
| постоянный участник
|
Пост N: 219
Зарегистрирован: 17.05.05
|
|
Отправлено: 12.10.06 16:56. Заголовок: Re:
ort пишет: цитата: | Есть в Clipper Tools функция: NUMROL() - Выполняет циклический сдвиг 16-битового слова. |
| Строго говоря, получается, что это не операция сдвига над числом Clipper-а, а операция сдвига над "получислом" Clipper-а.
|
|
|
|
| |
Пост N: 27
Зарегистрирован: 07.08.06
|
|
Отправлено: 12.10.06 23:23. Заголовок: Re:
Всем ответившим большое спасибо. Правда, странно как-то получилось: 1) ф-ция циклич сдвига ВЛЕВО в clipper tools есть, а ВПРАВО - почему-то нет. А мне как раз нужна последняя (означающая деление на 2 в степени N) 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ?
|
|
|
|
| Администратор
|
Пост N: 326
Зарегистрирован: 23.05.05
|
|
Отправлено: 13.10.06 08:46. Заголовок: Re:
Понравилось p519446 пишет: цитата: | Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. |
| Настоящие програмисты пишут только в машинном коде :) А компилятор сам должан оптимизировать такие операции #include "extend.h" CLIPPER BitShiftR() { _retnl(_parnl(1) >> _parni(2)); } CLIPPER BitShiftL() { _retnl(_parnl(1) << _parni(2)); } Не проверял, но должно работать :)
|
|
|
|
| Администратор
|
Пост N: 327
Зарегистрирован: 23.05.05
|
|
Отправлено: 13.10.06 08:53. Заголовок: Re:
Если есть проблемы со сборкой - давай адрес, отправлю готовый obj
|
|
|
|
| постоянный участник
|
Пост N: 9
Зарегистрирован: 09.10.06
|
|
Отправлено: 13.10.06 10:41. Заголовок: Re:
p519446 пишет: цитата: | ф-ция циклич сдвига ВЛЕВО в clipper tools есть, а ВПРАВО - почему-то нет |
| Описание NUMROL() в сt2rus.ng Выполняет циклический сдвиг 16-битового слова. ------------------------------------------------------------------------------ Синтаксис NUMROL(<nWORD1|cHexWORD1>, <nWORD2|cHexWORD2>, [<lLowByte>]) --> nWORD Параметры <nWORD1|cHexWORD1> - сдвигаемое значение в диапазоне от 0 до 65535, задаваемое в виде десятичного числа или символьной строки шестнадцатеричных цифр. <nWORD2|cHexWORD2> - количество производимых сдвигов влево, задаваемое в виде десятичного числа или символьной строки шестнадцатеричных цифр. <lLowByte> - необязательный логический параметр, задающий при значении .T. сдвиг младшего байта (диапазон количества сдвигов от 1 до 7), а при значении .F. или по умолчанию сдвиг всех 16 битов слова (диапазон количества сдвигов от 1 до 15). Возвращаемое значение nWORD - числовое значение слова с циклически сдвинутыми битами. Описание Функция позволяет осуществить циклический сдвиг влево битов 16-битового слова с числовым значением в диапазоне от 0 до 65535. При сдвиге бит, выходящий за разрядную сетку слева, переносится в самый правый разряд. Параметр <lLowByte> позволяет задать сдвиг только младшего байта слова. Примечания Количество сдвигов вычисляется как остаток от деления значения, заданного параметром <nWORD2|cHexWORD2>, на число 16 при значении .F., или на число 8 при значении .T. параметра <lLowByte> (длина слова и байта соответственно). Для выполнения циклического сдвига вправо на 1 бит следует выполнить циклический сдвиг (влево) на 15 для слова или на 7 для байта, а для сдвига вправо на 2 бита - на 14 и 6 соответственно, и т.д.
|
|
|
|
| постоянный участник
|
Пост N: 220
Зарегистрирован: 17.05.05
|
|
Отправлено: 13.10.06 11:35. Заголовок: Re:
Вот внутрення Clipper (Microsoft C) функция арифметического сдвига вправо. ;This function performs arithmetic right shifting of a DWORD ;in register pair DX:AX PROC __aFlshr xor ch,ch jcxz @@20 @@10: sar dx,1 rcr ax,1 loop @@10 @@20: ret ENDP __aFlshr То есть в дополнение к тем функциям, о которых я писал, надо просто включить вызов данной функции, поместив в регистр CL число битов, на которые хотите осуществить сдвиг, а в DX:AX сдвигаемое число. Приблизительно код (TASM 4.0) будет выглядеть следующим образом (это непроверенный код) TITLE Арифметический сдвиг вправо. Автор: Григорьев Владимир. IDEAL MODEL LARGE FULLSHR_TEXT, CPP GLOBAL __lparam: PROC GLOBAL __aFlshr: PROC GLOBAL __retnl: PROC GLOBAL FullShr: PROC CODESEG FULLSHR_TEXT PROC FullShr LOCAL @@nValue:DWORD mov ax,1 call __lparam,ax mov [word @@nValue],ax mov [word @@nValue+WORD],dx mov ax,2 call __lparam,2 mov cx,ax mov ax,[word @@nValue] mov dx,[word @@nValue+WORD] call __aFlshr call __retnl,ax,dx ret ENDP FullShr END Я думаю, данная фнкция должна работать быстро. Быстрее просто нет! Причем она делает арифметический сдвиг вправо "полного" целого числа Clipper.
|
|
|
|
| |
Пост N: 43
Зарегистрирован: 08.07.06
|
|
Отправлено: 13.10.06 15:18. Заголовок: Re:
цитата: | 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ? |
| Странно требовать от языка высокого уровня высокой скорости обработки 16-битовых чисел. В Клиппер ведь вообще нет понятия "16-битовое целое" - только NUMERIC. Соотв. главное здесь - не высокая скорость обработки двоичных данных (для этого есть Си и ассемблер) - а удобство написания больших и очень больших программных проектов, быстрая работа с табличными данными и т.п. А что касается твоей идеи "сдвигать" или "умножать/делить" - при обработке переменных клиппер сначала выясняет тип переменной, допустимость проведения той или иной операции с этим типом, а уж потом... что и подтверждают твои опыты с замером скорости.
|
|
|
|
| постоянный участник
|
Пост N: 222
Зарегистрирован: 17.05.05
|
|
Отправлено: 13.10.06 16:05. Заголовок: Re:
Как я уже сказал, моя функция FullShr( [<nNumber>], [<nCount>] ) - самя быстрая! Всю проверку на допустимость типов выполняет функция __lparam(). Более сложной проверки нет необходимости делать.
|
|
|
|
|
| |
Пост N: 28
Зарегистрирован: 07.08.06
|
|
Отправлено: 14.10.06 11:31. Заголовок: Re:
2Sergy: клиппер выясняет тип переменной и допустимость проведения операции в ОБОИХ вариантах теста, как при тупом умножении переменной на число 2, так и при вызове ф-ции NUMROL(). Получается, что либо время на проверки при использовании NUMROL(N,1) больше, чем при выполнении N*2, либо сама NUMROL выполняется медленнее. Я не собираюсь вычислять на клиппере что-то "страшное"; просто в моём коде часто выполняются операции деления на целые числа (в т.ч. на 2, 4, 8) -- вот и решил проверить, есть ли способы увеличения скорости. BTW, замена кода A = B / C на код A = IIF(C=1,B,B/C) уменьшает время примерно на 9% (проверял 5 раз на 1 млн итераций, машина 2.4MHz: 6.10" против 5.55"). Что-то мне подсказывает, что применение сдвига вправо вместо деления на 2,4 и 8 также может дать некий плюсовой эффект. 2Pasha: если не сложно, кинь, плз, obj-файл с функцией, которой я могу задать два параметра: исходное число и количество битов, на которое надо сдвигать право.
|
|
|
|
| Администратор
|
Пост N: 334
Зарегистрирован: 23.05.05
|
|
Отправлено: 14.10.06 11:46. Заголовок: Re:
Куда отправить ?
|
|
|
|
| |
Пост N: 44
Зарегистрирован: 08.07.06
|
|
Отправлено: 14.10.06 12:09. Заголовок: Re:
цитата: | 2Sergy: клиппер выясняет тип переменной и допустимость проведения операции в ОБОИХ вариантах теста, как при тупом умножении переменной на число 2, так и при вызове ф-ции NUMROL(). Получается, что либо время на проверки при использовании NUMROL(N,1) больше, чем при выполнении N*2, либо сама NUMROL выполняется медленнее. |
| вся скорость, выигрываемая битовым сдвигом в NUMROL(), теряется на сохранении регистров в стеке перед вызовом внешней функции и восстановлением оных при ее завершении. цитата: | Я не собираюсь вычислять на клиппере что-то "страшное"; просто в моём коде часто выполняются операции деления на целые числа (в т.ч. на 2, 4, 8) -- вот и решил проверить, есть ли способы увеличения скорости. BTW, замена кода A = B / C на код A = IIF(C=1,B,B/C) уменьшает время примерно на 9% (проверял 5 раз на 1 млн итераций, машина 2.4MHz: 6.10" против 5.55"). |
| Время в данном тесте будет очень сильно зависеть от входного набора данных, не так-ли? Чем меньше раз вместо сложного деления будет выполнено простое присвоение, тем больше экономия. цитата: | Что-то мне подсказывает, что применение сдвига вправо вместо деления на 2,4 и 8 также может дать некий плюсовой эффект. |
| Ты занимаешься достаточно тонкой оптимизацией кода, раз пишешь ТАКИЕ вещи. Похавльно, но имей ввиду, что все твои старания могут банально сыграть в "ноль" или даже в "минус" при простой замене ЛЮБОГО компонента выполнения: как ядра (например, конвейеры в процессорах AMD работают совершенно иначе, чем в Intel), так и 16-битной машины в ОС (к выходу Vista - будь готов! ). Кроме этого, видя "застой" в средствах ДОС-разработки, авторы Blinker всё больше увлекаются всякими улучшениями - не замечаешь? Будут ли твои оптимизации работать, к примеру, на 7 версии Блинкера, под Vista, на процессоре Core Duo ? Вот и я об этом: забей. Чем стандартнее, тем проще потом будет разбираться. IMHO.
|
|
|
|
| |
Пост N: 29
Зарегистрирован: 07.08.06
|
|
Отправлено: 14.10.06 14:54. Заголовок: Re:
2Pasha: мыль, плз, сюда: p519446 {сабацька} yandex.ru 2Sergy: возражений нет, ты прав. Но попробовать всё же очень хотца... Кстати, вопрос: а что там будет в Vista ? DOS-машина умрёт окончательно или будет на что-то заменена ?
|
|
|
|
| Администратор
|
Пост N: 335
Зарегистрирован: 23.05.05
|
|
Отправлено: 14.10.06 20:45. Заголовок: Re:
Отправил Я скомпилировал эту функцию старым добрым Turbo C 2.0, выпущенныи еще в 1988г, то еще в доисторическое время Поскольку он вставляет вызовы своих функций: они необходимы, так как сдвиг 32битного числа одной командой 16-разрядного процессора сделать нельзя, линковать программу надо с библитекой cl.lib (для large модели памяти) Я решил заодно тебе отправить и компилятор и все что надо для сборки - получилось немногим больше 200к Как видишь писать маленькие функции на C очень просто, собирать тоже Надо запустить tcc.exe <prgname>.c И в файле turboc.cfg заменить в строке -Iinc;d:\clip52\include мои каталоги на свои Если критична скорость вычислений, то все что можно лучше оформить в виде функций на C, передавать параметры ординарных типов (с массивами сложнее) легко, возвращать результат тоже Но все это понятия из давно ушедшей эпохи Что касается vista - как я понимаю это ОС для 32-разрядных машин Будет ли там 16-битный эмулятор я не знаю, но это не так уж и важно Сккажем winxp64 вышла давно, и эмулятора 16-бит там нет. Но его сделали сторонние разработчики. Так может будет и для vista Но все это опять таки не то Зачем ходить на костылях если можно твердо стоять на своих двоих Для этого есть харбор. В принципе его можно адаптировать для любой ОС, где есть компилятор С и реализован Yacc, то есть практически везде И для winxp64 харбор уже собран. И интеграция с С в харборе больше, чем у клиппера, можно фрагменты кода на C вставлять прямо в prg-функцию Надо жить в этом веке, а не в прошлом
|
|
|
|
| постоянный участник
|
Пост N: 224
Зарегистрирован: 17.05.05
|
|
Отправлено: 16.10.06 11:21. Заголовок: Re:
Странно, а чем моя функция не понравилась?! Даже обидно! Что касается сдвига, то интересный результат получается. Если делить 1 на 2 путем сдвига, то получаем 0. А если делить -1 на 2, то получаем снова -1! Так как знаковый бит из старшего бита постоянно сдвигается вправо, заполняя собой все число.
|
|
|
|
| |
Пост N: 31
Зарегистрирован: 07.08.06
|
|
Отправлено: 16.10.06 13:28. Заголовок: Re:
Володя, не обижайся, плз! : -)) Мне стыдно признаться, но я... не знаю, как твою ф-цию прислюнявить к своему коду (в АСМе я ничего не смыслю). Кинь obj, если не затруднит, чтобы я его мог прилинковать к своей проге (blinker 6.0 extended mode).
|
|
|
|
| постоянный участник
|
Пост N: 225
Зарегистрирован: 17.05.05
|
|
Отправлено: 16.10.06 14:23. Заголовок: Re:
p519446 пишет: цитата: | Кинь obj, если не затруднит |
| Не затруднит, но только смогу это сделать завтра, так как для этого нужно зайти домой.
|
|
|
|
| |
Пост N: 3
Зарегистрирован: 23.10.06
|
|
Отправлено: 23.10.06 16:09. Заголовок: Re:
p519446 пишет: цитата: | 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ? |
| я тебе уже как-то объяснял, что есть 2 типа операций в пи-коде - внутренние и внешние. Внутренние (например умножение на 2) - выполнены эффективно и выполняются в специальной пробирке, в которой уже все готово. Внешние (например, вызов твоей функции) влекут за собой кучу действий - то есть сначала открывается новая лаборатория, выливается все старое содержимое пробирок, все пробирки тщательно моются а затем начинается то, что ты хотел
|
|
|
Новых ответов нет
, стр:
1
2
All
[см. все]
|
|