Embedded OS

Здравствуйте, Уважаемый Leha!

Wed Mar 16 2005 10:35, Leha Bishletov wrote to Olga Nonova:

ON>> Если честно, то задача контроля типов, слава Богу!, никак не ON>> решается.

LB> Интересно, что хорошего в отсутствии контроля типов? Для меня одной из LB> существенных причин перехода ASM->C был именно контроль типов.

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

ON>> "Компилированный стек" тоже не реализуется. Ибо от лукавого.

LB> А как же экономия байтов? Или нужно отказаться от совместного LB> использования одного и того же участка памяти разными подпрограммами?

Динамическое распределение локальных переменных может решаться и без привлечения стека данных (см. например PLM-51). Стек данным нужен только в случае рекурсивного использования процедур. Вы часто используете рекурсии в своих задачах?

ON>> MoveByte MACRO Byt1,Byt2 ON>> lds R16,Byt1 ON>> sts Byt2,R16 ON>> ENDM

LB> Я плохо разбираюсь в системе команд AVR, но мне кажется, что там есть LB> косвеная адресация, корорая "экономнее" lds-sts. Компилятор может для LB> MoveByte выбрать наиболее выгодную форму, в зависимости от того, что это LB> за Byt, а твоя программа будет всегда использовать lds-sts. Вот один из LB> моментов, когда результат на ASM проигрывает результату на С. Есть и LB> другие предпосылки для получения менее эффективного кода на ASM, т.к. LB> нужно сохранить читаемость программы, а оптимизатора нет ...

Если вспомнить, что для косвенной алресации нужно предварительно назначить все указатели, то должно сразу стать понятным, что для пересылки одного байта ее использовать совершенно неэкономично. И для двух, и для трех...Затраты по инструкциям выравниваются, где-то начиная с пересылки в 8 _последовательно_ расположенных байт. Таким образом...

LB> Без контроля типов и какой-нибудь оптимизации твои макросы просто LB> замена мнемоник одного ASM на другой, привычный.

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

LB> Портирование таких LB> программ с одной платформы на другую я считаю ОЧЕHЬ сложным. У тебя есть LB> опыт портирования твоего ASM с AVR на "не AVR"?

Такого опыта у меня нет. Да и зачем менять шило на мыло? Спектра моделей AVR хватит еще лет на 10 практической деятельности.

Всего Вам Хорошего Ольга

Reply to
Olga Nonova
Loading thread data ...
Reply to
Sergey Davydov

Здравствуйте, Уважаемый Leha!

Wed Mar 16 2005 10:35, Leha Bishletov wrote to Olga Nonova:

ON>> Задача, значит, для Вас- раз плюнуть? И учесть ON>> при этом все крайние случаи исходных строк?

LB> Список "крайних" случаев?

Строки нулевой длины. Строки, у которых "забыли" /0 в конце. Строки, выходящие за диапазон отведенной под нее памяти.

ON>> И предусмотреть защиту от "забыли ноль в конце строки"?

LB> Библиотечная функция этого не делает

А в Pascal - делает! Очень грамотно проверяет выход за диапазон.

ON>> И не испортить контекст вызова функции?

LB> Запросто, при условии, что функция вызвана корректно.

А кто вызывает? Компилятор. Значит, будьте добры разобраться во всех тонкостях, как он это делает и какого уровня сохранности контекста требует. Придется лезть в ASM. Cовсем не тривиально.

ON>> И не вляпаться в инструкции ON>> контроллера из списка ERRATA?

LB> Это забота компилятора. Кстати, много ты знаешь таких инструкций?

Библиотечная функция не является "заботой" компилятора. В AVR-ах были баги с выполнением отдельных инструкций ветвления при прерываниях. Сейчас правда утверждают, что пофиксили.

Всего Вам Хорошего Ольга

Reply to
Olga Nonova

Здравствуйте, Уважаемый Dima!

Wed Mar 16 2005 09:42, Dima Orlov wrote to Olga Nonova:

DO> Зачем? Компилятор ноль не забывает, в библиотечной функции никаких защит DO> от этого нет, кстати размер буфера она тоже не контролирует.

Компилятор может и не "забывает" ноль. Зато в приходящих из канала связи пакетах можно встретить и не такие чудеса забывчивости. И последствия фатальны для скомпилированной на Си программы.

Всего Вам Хорошего Ольга

Reply to
Olga Nonova
Reply to
Andy Mozzhevilov
Reply to
Andy Mozzhevilov
15-Mar-05 21:50 Olga Nonova wrote to Leha Bishletov:

ON> Примеры самих макросов

ON> MoveByte MACRO Byt1,Byt2 ON> lds R16,Byt1 ON> sts Byt2,R16 ON> ENDM Кстати, атмелу за наличие ldi,ld,ldd,lds вместо одного mov и модификаторов для задания константы/ячейки ( var и #var или [var] и var - по вкусу) и средств макроязыка для определения метода адресации - поотрывать надо всё лишнее...

ON> LoadConst MACRO IntegerVar, LongConst ON> ;------------------------------------- ON> ; Load Integer Variable with a 32-bit constant. ON> ldi R16, Low(IntegerVar) ON> ldi R17, High(IntegerVar) ON> ldi R18, Low (LWRD LongConst) ON> ldi R19, High (LWRD LongConst) ON> ldi R20, Low (HWRD LongConst) ON> ldi R21, High (HWRD LongConst) ON> EXTERN _LoadConst ON> call _LoadConst ;--to math library ON> ENDM

Вдогонку. "как бы это было у меня, если бы когда-то я решил много писать для AVR на ассемблере". Было бы что-то в духе (ошмётки на тему):

; где-то оставить rcall (вызовы внутри данного модуля), где-то поставть ; _call - макрос, превращающийся в rcall или call в зависимости от процессора - ; это в качестве домашнего задания.

; достать адрес возврата как указатель на БАЙТЫ кода .macro popZcptr pop ZH pop ZL lsl ZL rol ZH .endm

; раз уж для AVR - то для всех, и старух, и посвежее .macro lpm_rp reg #ifdef __AVR_ENHANCED__ lpm \reg,Z+ #else lpm adiw ZL,1 .ifnc "\reg","r0" .ifnc "\reg","R0" mov \reg,r0 .endif .endif #endif .endm

; только для "завершённости" примера - где-то может быть именно макрос вывода, ; где-то -- вызов. .macro putchar_R0 rcall _putchar_R0 .endm

.macro putstr_P txt ; вывод строки через putchar_R0 rcall _putstr_P .asciz "\txt" .align 1 .endm

; "могу грузить, могу и не грузить" .macro ldi_X val .ifnc "\val","" ldi XL,lo8(\val) ldi XH,hi8(\val) .endif .endm

; Грузим строку из памяти кода в буфер в ОЗУ. .macro ldstring_P txt,buf ldi_X \buf ; ldi_X само разберётся - был ли указан buf rcall _ldstring_P .asciz "\txt" .align 1 .endm

; 16 бит ещё может и выгодно грузить через ldi, а вот 32 - ; по объёму кода уже откровенно лучше через два слова после ; вызова служебной функции .macro sti_32 const,var ldi_X \var rcall _sti_32 .long \const .endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#include "macs.inc"

.data buf: .skip 8

.text

_sti_32: popZcptr .rept 4 lpm_rp r0 st X+,r0 .endr rjmp iret

_putstr_P: popZcptr rjmp 2f

1: putchar_R0 2: lpm_rp r0 tst r0 brne 1b align_iret: ; восстановить Z как адрес возврата (с округлением вверх) и вернуться adiw ZL,1 iret: ; округление не нужно - только восстановление и возврат asr ZH ror ZL ijmp

_ldstring_P: popZcptr

1: lpm_rp r0 st X+,r0 tst r0 brne 1b rjmp align_iret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

main: putstr_P "Hello, I am here!!\r\n"

sti_32 0xDEADBEEF,buf sti_32 0x01234567 ; продолжаем грузить тот же буфер

ldstring_P "kwa!",buf tst r16 breq 1f sbiw XL,1 ; отмотка назад концевого '\0' ldstring_P " mooo!\r\n" ; дописываем в хвост

1: ; ...

.end

А в случае ориентации только на кристаллы с наличием lpm reg,Z+ и для копирования в ОЗУ между не вычисляемыми в runtime адресами становится выгодно и аргументы memcpy не в регистры грузить в каждой точке вызова, а тоже словами в код. Точнее, это быстрее окупается, чем для не-ENHANCED ядра. Ну так и тут никто не мешает пустить под условную компиляцию варианты как реализации макроса, так и функции.

.macro memcpy_ii dst,src,len rcall _memcpy_ii .word \dst .word \src .word \len .endm

; это всё гораздо красивее выглядит, если есть возможность сделать ; jsr R5,_memcpy_ii ; а в самой подпрограмме ; mov (R5)+,R0 ; mov (R5)+,R1 ; mov (R5)+,R2 ; ... ; rts R5 ; но так тоже терпимо: _memcpy_ii: popZcptr lpm XL,Z+ lpm XH,Z+ lpm YL,Z+ lpm YH,Z+ lpm R24,Z+ lpm R25,Z+ rjmp 2f

1: ld r0,Y+ st X+,r0 2: sbiw R24,1 brcc 1b rjmp iret

memcpy_ii buf1, buf2, 10

Reply to
Oleksandr Redchuk
15-Mar-05 21:50 Olga Nonova wrote to Leha Bishletov:

ON>>> Поэтому, для перехода на другую платформу

---------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ OM>>> перелопачивать килобайты ассемблера вовсе не требуется.

LB>> Можно увидеть хотя бы фрагмент этих макросов? Особенно интересно, как LB>> решается задача по контролю соответствия типов (на С это происходит LB>> автоматически). Еще было бы не плохо, если бы была возможность LB>> организовать т.н. "компилированый стек".

ON> "Компилированный стек" тоже не реализуется. Ибо от лукавого. ON> Формальные параметры условилась всегда передавать в функции через ON> рабочие регистры. Очень лихо согласуется с подчёркнутым выше. То, что именно для AVR компилированный стек ни к чему - ещё не означает, что ограничение объёма аргументов и локальных переменных количеством регистров не возникнет на *другой* платформе.

ON> MovDD MACRO Src,Dst,Len ON> ldi R16,Low(Src) ON> ldi R17,High(Src) ON> ldi R18,Low(Dst) ON> ldi R19,High(Dst) ON> ldi R20,Len ON> EXTERN _MovDD ON> call _MovDD ;--to string library ON> ENDM

"и эти люди запрещают ковыряться мне на С" :-) Во-превых, передача адресов в подпрограмму через не-адресные регистры - это себе сишники могут позволить, да и то - многие реализации C содержат расширения. Спасибо, отличная иллюстрация того, что в сложных программах на ассемблере программисты как правило всё равно вынуждены выдумывать разные соглашения о вызовах, которые в существенной мере сводят на нет преимущества "оптимального" ручного распределения регистров и появляется присущий ЯВУ "оверхед". Там случайно ещё и _MovDD "на всякий случай" не сохраняет/восстанавливает указательные регистры??

ON> LoadConst MACRO IntegerVar, LongConst ON> ;------------------------------------- ON> ; Load Integer Variable with a 32-bit constant. ON> ldi R16, Low(IntegerVar) ON> ldi R17, High(IntegerVar) ON> ldi R18, Low (LWRD LongConst) ON> ldi R19, High (LWRD LongConst) ON> ldi R20, Low (HWRD LongConst) ON> ldi R21, High (HWRD LongConst) ON> EXTERN _LoadConst ON> call _LoadConst ;--to math library ON> ENDM Хм... И сколько раз такое чудо встречается в программе? Если один-два, то макрос и подпрограмма - только ради макросости и подпрограммности. А если больше, то .macro const2mem var,const ldi YL,lo8(var) ldi YH,hi8(var) call _const2mem_ .long const .endm

_const2mem_: pop ZH pop ZL lsl ZL rol ZH .rept 4 #if defined(__AVR_ENHANСED__) lpm r0,Z+ #else lpm adiw ZL,1 #endif st Y+,r0 .endr lsr ZH ror ZL ijmp .endm

2 слова выиграша на каждом вызове, 10-14 слов проигрыша на самой подпрограмме (если указатель в LoadConst сразу пишется куда надо, иначе - 8-12 слов проигрыша). Итого после 5-го..7-го применения - пошёл чистый выигрыш. В особо экономном случае - под условную компиляцию две версии макроса и функции :-)

15-Mar-05 22:05 Olga Nonova wrote to Anatoly Mashanov:

ON> Оптимизация нынче неактуальна. Hа злобу дня встал пресловутый Time To ON> Market.

Тогда я вообще не понимаю этих стонов по поводу C-шного и RTOS-ного "раздувания кода". Освоенная RTOS этот time2market как раз сокращает.

Reply to
Oleksandr Redchuk
16-Mar-05 01:37 Alex Kouznetsov wrote to Olga Nonova:

ON>>>> Кроме того, вы сказали "копирование строки" несколько поспешно, т.к. ON>>>> речь идет об особых строках типа char, с нулем в конце.

AK>>> Что в ней особого? Это стандартная сишная строка.

ON>> Закидаем шапками? Й-ех, молодежь!

2ON: Хм... Вы нам льстите. Или же нам давно пора поинтересоваться отчеством и перейти на очень уважительный тон (это только писатели/поэты в нашем возрасте при союзе назывались "молодыми"). Нет, стариком я себя не считаю, но за "молодёжь" спасибо :-) Хотя, как показывает практика, эти вещи (шапкозакидательство и наоборот, вера в панацеи, "серебрянные пули" и т.п.) слабо связаны с возрастом. Как недавно где-то прочёл - "если вам ни с того ни с сего нахамили в форуме, где вы появились впервые с невинным вопросом - не воспринимайте близко к сердцу - возможно, ваш собеседник просто переживает сложный период становления личности... уже 50-тый год....).

AK> Ты не oтветила на вопрос: что в ней особого? Какие строки, по-твоему, не AK> являются особыми?

Да ты не понял :-) Сама строка нормальная, только вот strcat/strncat обязаны определять, что программист забыл в конце '\0' задать (интересно, как он на C это может сделать, кроме как посимвольно массив заполнить?) - и при этом как-то "корректно" реагировать, должны как-то разбираться с тем, что программист пытается прицепить строку туда, где нет места и т.п. Короче, strcat сама обязана исправлять все ошибки программиста. А вот ассемблерный макрос, наверно, это всё умеет :-)

wbr,

Reply to
Oleksandr Redchuk
Reply to
Andy Mozzhevilov

Wed Mar 16 2005 14:00, Olga Nonova wrote to Dima Orlov:

ON>>> И предусмотреть защиту от "забыли ноль в конце строки"?

DO>> Зачем? Компилятор ноль не забывает, в библиотечной функции никаких защит DO>> от этого нет, кстати размер буфера она тоже не контролирует.

ON> Компилятор может и не "забывает" ноль. Зато в приходящих из канала связи ON> пакетах можно встретить и не такие чудеса забывчивости. И последствия ON> фатальны для скомпилированной на Си программы.

Чушь.

Нет никакой разницы на чем скомпилирована программа, принимающая z-строки. Что на ассемблере, что на паскале, что на сях - обрабатываться строки должны одинаково. Это не языком определяется, а разработчиком.

Также нет никакой разницы, на каком языке написана программа, выдающая строки в канал связи. Если разработчик решил передавать z-строки, он их передаст и на паскале, и на сях. Если же он решил использовать строки со счетчиком, он опять же сделает их и на си и на паскале.

Что касается самого канала связи с потерями, то не видно принципиальной разницы между использованием строки со счетчиком или z-строки. И в том и в другом случае потери/изменения каких-то байтов/битов могут оказаться "фатальными" для принимающей программы, если у написавшего эту программу сильно кривые руки, а в голове опилки.

Тем не менее, даже если какая-то разница есть, си не ограничивает свободу разработчика и не навязывает ему z-строки как _обязательные_ к использованию. Так же как паскаль не навязывает использования строк со счетчиком. Преобразовать z-строку в строку со счетчиком и обратно - пустяковая задача на любом языке.

И, наконец, никто в здравом уме не будет передавать "голые" строки по каналу с ошибками. Передаются пакеты, где должны быть предусмотрены соответствующие средства обнаружения ошибок и защиты. Если разработчик не использует эти механизмы, а допускает дальнейшую обработку битых пакетов, то ему надо бы менять профессию. Язык си не виноват, что этот человек взялся не за свое дело.

Пока, Алексей

Reply to
Alex Kouznetsov
Reply to
Leha Bishletov
Reply to
Leha Bishletov
Reply to
Leha Bishletov
Reply to
Leha Bishletov
Reply to
Michael Belousoff

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.