Форум » Clipper » Битовый сдвиг чисел в клиппере. Это возможно или нет ? » Ответить

Битовый сдвиг чисел в клиппере. Это возможно или нет ?

p519446: Hi all. Кто-нибудь знает, есть ли в штатных средствах клиппера возможность выполнить над числом битовый сдвиг на N разрядов вправо/влево ? (т.е. не делить/умножать на степень числа 2, а именно СДВИНУТЬ биты исходного числа и получить результат, как в АСМе SHR/SHL)

Ответов - 24, стр: 1 2 All

Петр: В штатных средствах клиппера возможности работы с битами нет, есть в xHarbour. Но есть возможность или использовать библиотеки сt, nanfor или написать самомому на что-то С/ASM и подключить к Clipper с помощью extend.api/extasm.inc.

Григорьев Владимир: Есть внутренние функции 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 Вот и вся программа!

ort: Есть в Clipper Tools функция: NUMROL() - Выполняет циклический сдвиг 16-битового слова. Описание Функция позволяет осуществить циклический сдвиг влево битов 16-битового слова с числовым значением в диапазоне от 0 до 65535. При сдвиге бит, выходящий за разрядную сетку слева, переносится в самый правый разряд. Параметр <lLowByte> позволяет задать сдвиг только младшего байта слова.


Григорьев Владимир: ort пишет: Есть в Clipper Tools функция: NUMROL() - Выполняет циклический сдвиг 16-битового слова. Строго говоря, получается, что это не операция сдвига над числом Clipper-а, а операция сдвига над "получислом" Clipper-а.

p519446: Всем ответившим большое спасибо. Правда, странно как-то получилось: 1) ф-ция циклич сдвига ВЛЕВО в clipper tools есть, а ВПРАВО - почему-то нет. А мне как раз нужна последняя (означающая деление на 2 в степени N) 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ?

Pasha: Понравилось p519446 пишет: Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. Настоящие програмисты пишут только в машинном коде :) А компилятор сам должан оптимизировать такие операции #include "extend.h" CLIPPER BitShiftR() { _retnl(_parnl(1) >> _parni(2)); } CLIPPER BitShiftL() { _retnl(_parnl(1) << _parni(2)); } Не проверял, но должно работать :)

Pasha: Если есть проблемы со сборкой - давай адрес, отправлю готовый obj

Петр: 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 соответственно, и т.д.

Григорьев Владимир: Вот внутрення 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.

Sergy: 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ? Странно требовать от языка высокого уровня высокой скорости обработки 16-битовых чисел. В Клиппер ведь вообще нет понятия "16-битовое целое" - только NUMERIC. Соотв. главное здесь - не высокая скорость обработки двоичных данных (для этого есть Си и ассемблер) - а удобство написания больших и очень больших программных проектов, быстрая работа с табличными данными и т.п. А что касается твоей идеи "сдвигать" или "умножать/делить" - при обработке переменных клиппер сначала выясняет тип переменной, допустимость проведения той или иной операции с этим типом, а уж потом... что и подтверждают твои опыты с замером скорости.

Григорьев Владимир: Как я уже сказал, моя функция FullShr( [<nNumber>], [<nCount>] ) - самя быстрая! Всю проверку на допустимость типов выполняет функция __lparam(). Более сложной проверки нет необходимости делать.

p519446: 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-файл с функцией, которой я могу задать два параметра: исходное число и количество битов, на которое надо сдвигать право.

Pasha: Куда отправить ?

Sergy: 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.

p519446: 2Pasha: мыль, плз, сюда: p519446 {сабацька} yandex.ru 2Sergy: возражений нет, ты прав. Но попробовать всё же очень хотца... Кстати, вопрос: а что там будет в Vista ? DOS-машина умрёт окончательно или будет на что-то заменена ?

Pasha: Отправил Я скомпилировал эту функцию старым добрым 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-функцию Надо жить в этом веке, а не в прошлом

Григорьев Владимир: Странно, а чем моя функция не понравилась?! Даже обидно! Что касается сдвига, то интересный результат получается. Если делить 1 на 2 путем сдвига, то получаем 0. А если делить -1 на 2, то получаем снова -1! Так как знаковый бит из старшего бита постоянно сдвигается вправо, заполняя собой все число.

p519446: Володя, не обижайся, плз! : -)) Мне стыдно признаться, но я... не знаю, как твою ф-цию прислюнявить к своему коду (в АСМе я ничего не смыслю). Кинь obj, если не затруднит, чтобы я его мог прилинковать к своей проге (blinker 6.0 extended mode).

Григорьев Владимир: p519446 пишет: Кинь obj, если не затруднит Не затруднит, но только смогу это сделать завтра, так как для этого нужно зайти домой.

suv: p519446 пишет: 2) простой тест показал, что ф-ция NUMROL() работает МЕДЛЕННЕЕ, чем обычное умножение на 2 (200000 итераций выполнялось соотв-но 1.67" и 1.34"). Хотя я неоднократно слышал/читал, что бравые Си`шники и АСМ`еры никогда не умножают и не делят на число, равное степени 2 -- юзают вместо этого именно SHL/SHR. А в клиппере всё оказалось наоборот: надо забыть про эту идею и просто умножать/делить "как в школе учили", без извращений. Кто-нить может объяснить этот эффект ? я тебе уже как-то объяснял, что есть 2 типа операций в пи-коде - внутренние и внешние. Внутренние (например умножение на 2) - выполнены эффективно и выполняются в специальной пробирке, в которой уже все готово. Внешние (например, вызов твоей функции) влекут за собой кучу действий - то есть сначала открывается новая лаборатория, выливается все старое содержимое пробирок, все пробирки тщательно моются а затем начинается то, что ты хотел

suv: Sergy пишет: Странно требовать от языка высокого уровня высокой скорости обработки 16-битовых чисел. собственно сдвиг в numrol или как там - выполняется микросекунды. основное время уходит на подготовку к вызову функции... а когда она отработала - пробирки опять тщательно моются)))

suv: p519446 пишет: Кстати, вопрос: а что там будет в Vista ? DOS-машина умрёт окончательно или будет на что-то заменена ? сегодня пытались провести брифинг по висте. но не смогли - все зависло нах )))))) грят доса не будет)))) переживать первое время не стоит - не только дос, но и сама виста тоже работать первое время не будет

suv: p519446 пишет: Кто-нибудь знает, есть ли в штатных средствах клиппера возможность выполнить над числом битовый сдвиг на N разрядов вправо/влево ? (т.е. не делить/умножать на степень числа 2, а именно СДВИНУТЬ биты исходного числа и получить результат, как в АСМе SHR/SHL) чем тебе не нравится умножение и деление чисел? )))) зы. у мине есть битовые сдвиги )) чо не просишь? более того - даже не над числами (небольшое кол-во битов), а над СТРОКОЙ (большое кол-во битов)

p519446: suv пишет: сегодня пытались провести брифинг по висте. но не смогли - все зависло нах )))))) сегодня пытались провести брифинг по висте. но не смогли - все зависло нах )))))) Сцылочку в студию кинул бы, что-ли... Чтобы хоть поржать немного над очередным шедевром. suv пишет: у мине есть битовые сдвиги )) чо не просишь? Дык чего же ты молчишь-то ?!? Давай, плз!!



полная версия страницы