Помогите пофиксить баги

Обсуждаем контроллеры компании Atmel.
Ответить
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

COKPOWEHEU писал(а):Поскольку в ассемблере нет ничего более высокоуровневого, чем подпрограмма - это она и есть.
С точки зрения программиста на ассемблере - это она и есть, поскольку, как Вы совершенно справедливо заметили, в ассемблере кроме подпрограмм более ничего нет (макросы не рассматриваем, потому что после компиляции они станут просто повторяющимися кусками кода в теле программы).

Но, тем не менее, этот вызываемый участок кода получает параметр на входе и возвращает параметр на выходе. То есть, имеет все атрибуты функции?

Пойдем далее - допустим, я пишу на Си для AVR и написал некую функцию. Отлично, но после компиляции она тоже превратится в блок команд на ассемблере, в котором, как мы знаем, никаких функций нет? А ведь непосредственно исполняться в вычислительном ядре будут машинные коды, эквивалент коих - ассемблер. Получается, там, где происходит непосредственное выполнение программы, никаких функций нет? На каком же этапе они исчезают?
COKPOWEHEU писал(а):Дело в том, что передача значений реализована вручную
Что значит "вручную"? Через регистр - это вручную? А через память (ОЗУ) - это не вручную? А какой вообще еще способ есть? Ну, через стек можно, но это капитально поизвращаться надо.

Просто у компилятора есть раз и навсегда запрограммированный его создателями механизм передачи параметров в вызываемый участок кода - допустим, путем создания некоего массива данных в ОЗУ. И возврат значений делается также, создавая другой массив. Компилятор же только меняет размер этого массива в зависимости от количества и типа передаваемых и возвращаемых параметров.
Но человек, будучи умнее компилятора Си, программируя на ассемблере, может создать свой способ передачи данных, если данных немного. Например, так, как это показано в моем примере.
COKPOWEHEU писал(а):то есть с одной версией компилятора она будет работать нормально, а с другой - нет.
Я программирую на ассемблере. И этот пример в любом ассемблере скомпилируется правильно.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Но, тем не менее, этот вызываемый участок кода получает параметр на входе и возвращает параметр на выходе. То есть, имеет все атрибуты функции?
Нет, у этого участка нет входа и выхода данных, он работает напрямую с регистрами.
Пойдем далее - допустим, я пишу на Си для AVR и написал некую функцию.
Передачей параметров между этой функцией и остальным кодом занимается компилятор, а не программист. Даже если в новой версии способ изменится, он изменится одинаково и для функции и для основного кода, при этом переписывать их не придется. В отличие от ассемблерных "подобий".
Получается, там, где происходит непосредственное выполнение программы, никаких функций нет? На каком же этапе они исчезают?
Разумеется. Ядро контроллера знать не знает о высокоуровневых абстракциях, придуманных для удобства программиста. Компилятор ЯВУ разворачивает их в набор команд более низкого уровня и передает ассемблеру.
Что значит "вручную"?
Это значит, что конкретным способом передачи занимается программист, а не компилятор. При вызове функции из Си вы же не задумываетесь, через что передаются параметры, через регистры, ОЗУ, стек или астрал. Этим занимается компилятор, и у каждой версии может быть свое представление о том, какой способ лучше.
Я программирую на ассемблере. И этот пример в любом ассемблере скомпилируется правильно.
Разумеется, если использовать его как подпрограмму. В том же Си его можно оформить как функцию. Тогда работоспособность будет зависеть от того, угадали вы принятый для компилятора способ передачи или нет. Например, avr-gcc передает первый параметр через r24, так что там ваш пример не заработает.
Но человек, будучи умнее компилятора,
Знаете, не к любому человеку это применимо...
Реклама
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

COKPOWEHEU писал(а):
Но, тем не менее, этот вызываемый участок кода получает параметр на входе и возвращает параметр на выходе. То есть, имеет все атрибуты функции?
Нет, у этого участка нет входа и выхода данных, он работает напрямую с регистрами.
А неважно, с чем этот код работает. Он параметр получает? Получает. Результат возвращает? Возвращает. Чем он не функция?
Если б я передавал параметр не через R18, а через R24 (что совершенно непринципиально для работы этого кода), сошел бы этот код за функцию, сгенерированную avr-gcc?
COKPOWEHEU писал(а):Разумеется, если использовать его как подпрограмму. В том же Си его можно оформить как функцию. Тогда работоспособность будет зависеть от того, угадали вы принятый для компилятора способ передачи или нет.
Э-э-э, стоп. Если б я писал на Си, и зачем-то решил преобразование BCD->BIN написать на ассемблере, то я написал бы заголовок функции в принятой на Си нотации и значение входного параметра внутри функции занес в некоторый адрес в ОЗУ, а уже потом перешел бы к ассемблерным командам, первая из которых была бы

Код: Выделить всё

lds R18,SOME_ADDRESS
Я немного не об этом. Я хочу сказать, что не совсем корректно сравнивать абстрактную "процедуру" и абстрактную "функцию" в отрыве от языка и платформы.
Вернемся к моему примеру. Если мы пишем на ассемблере, чем этот код не функция? Под формальное определение подходит.
Кстати, я тут нашел свою универских времен книжку по ТурбоПаскалю 7.0 1996 года издания и, прочитав раздел "Процедуры и функции", увидел, что в Паскале и процедуры, и функции могут иметь как входные, так и выходные параметры, разница заключена в способе использования.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

А неважно, с чем этот код работает. Он параметр получает? Получает. Результат возвращает? Возвращает. Чем он не функция?
Именно тем, что не получает и не возвращает никаких значений. А то так можно и sei назвать функцией, она же меняет SREG.
Наверное, на макросах можно написать что-то близкое к процедурам и функциям, то есть придумать свой интерфейс передачи данных и скрыть его от программиста, но это то еще извращение... Надо бы попробовать.
Если б я передавал параметр не через R18, а через R24 (что совершенно непринципиально для работы этого кода), сошел бы этот код за функцию, сгенерированную avr-gcc?
Зачем задавать вопрос, на который ранее был дан ответ? Я уже написал, что этот кусок остается подпрограммой. Для внешнего кода он может притворяться функцией. Но это не отменяет того, что штатным механизмом передачи параметров он не пользуется, только его ручной реализацией.
В каком-нибудь cvavr или IAR, где соглашения о передаче параметров другие, это работать не будет. В отличие от функции, написанной на самом Си. Кстати, это общая проблема совместного использования нескольких компиляторов, так что различать "функция - не функция" логичнее на родном языке. А на родном языке вашей "функции" есть только подпрограммы.
Если б я писал на Си, и зачем-то решил преобразование BCD->BIN написать на ассемблере, то я написал бы заголовок функции в принятой на Си нотации и значение входного параметра внутри функции занес в некоторый адрес в ОЗУ, а уже потом перешел бы к ассемблерным командам, первая из которых была бы
А зачем изобретать подпрограммы на Си, когда есть куда более удобные функции? Вы предлагаете загружать число мало того что из ОЗУ (не используя нормальный вход функции), так еще и по фиксированному адресу. Использовать такое в Си достаточно непросто. Обычно при использовании внешних ассемблерных функций реализуют именно штатный механизм передачи параметров (через те же r24:r23, r22:r21) и меняют только если поменяются соглашения о передаче параметров (что случается ой как нечасто).
Вернемся к моему примеру. Если мы пишем на ассемблере, чем этот код не функция? Под формальное определение подходит.
Под формальное определение подпрограммы - да, но не под определение функции. У нее нет стандартного интерфейса передачи данных в вызывающую программу.
Кстати, я тут нашел свою универских времен книжку по ТурбоПаскалю 7.0 1996 года издания и, прочитав раздел "Процедуры и функции", увидел, что в Паскале и процедуры, и функции могут иметь как входные, так и выходные параметры, разница заключена в способе использования.
А вы не путаете выходные параметры с возвращаемым значением?

Код: Выделить всё

procedure set_0(var x:integer);
begin
  x:=0;
end; 
Наверное, вы имели в виду что-то вроде этого? Как и любая другая функция, эта не обладает выходным интерфейсом. Указатель на переменную передается через входной, а дальше - прямой доступ к памяти.
Реклама
Эиком - электронные компоненты и радиодетали
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

COKPOWEHEU писал(а):Наверное, на макросах можно написать что-то близкое к процедурам и функциям, то есть придумать свой интерфейс передачи данных и скрыть его от программиста, но это то еще извращение... Надо бы попробовать.
Не удержался и попробовал. Для практического применения оно и бесполезно, но формально с его использованием можно делать функции. Правда, оперировать они могут только с 1-4 входными аргументами по 1 байту каждый, причем аргументы обязаны располагаться в ОЗУ. Возвращаемое значение - тоже 1 байт. Поскольку это делалось исключительно для доказательства возможности, на этом остановился.
Вложения
asm_func.zip
(1.91 КБ) 108 скачиваний
Реклама
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

COKPOWEHEU писал(а):Наверное, вы имели в виду что-то вроде этого?
Нет. Я приложил скан страницы из книги по ТурбоПаскалю 7.0, где на примере показано, что и функция и процедура могут принимать и возвращать параметры. Правда, используются они чуть по разному.
Изображение
COKPOWEHEU писал(а):Не удержался и попробовал.
Любопытный эксперимент
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Просмотрел ваш скан, не увидел где "процедура может возвращать параметры".
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

COKPOWEHEU писал(а):А зачем изобретать подпрограммы на Си, когда есть куда более удобные функции?
Я сказал:
Если б я писал на Си, и зачем-то решил преобразование BCD->BIN написать на ассемблере
Ключевые слова тут "если б" и "зачем-то". Понятно, что такие вычисления при программировании на Си нужно и писать на Си, ассемблер тут совершенно не нужен.

Еще раз. Мой пример написан на ассемблере и не предназначается для включения в программу на Си. Он используется ТОЛЬКО при написании программ на ассемблере.
COKPOWEHEU писал(а):Под формальное определение подпрограммы - да, но не под определение функции. У нее нет стандартного интерфейса передачи данных в вызывающую программу.
Покажите мне стандартный интерфейс передачи данных в функцию при программировании на ассемблере. Его нет, поскольку в асме нет понятия функции. Тем не менее, подпрограмма может быть подобна функции и вести себя как функция, если её снабдить интерфейсом (любого вида) передачи и возврата параметров. Я могу эту подпрограмму включить в файл *.inc и потом во всех своих программах (на ассемблере) использовать её, как вызываемую функцию.
COKPOWEHEU писал(а):Просмотрел ваш скан, не увидел где "процедура может возвращать параметры".
Посмотрите абзац "Суммирование чисел с использованием процедуры" - вызывается процедура Summing_up, после чего делается печать вычисленной суммы - значения переменной Sum_numbers. Если процедура изменяет внутри себя значение переменной, а потом эта переменная доступна вне этой процедуры, то что это, как не возврат значения?
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Понятно, что такие вычисления при программировании на Си нужно и писать на Си, ассемблер тут совершенно не нужен.
Не соглашусь. Иногда на ЯВУ нереально написать достаточно быструю обработку, приходится делать ассемблерную вставку или комбинировать исходники на разных языках. Мне таким образом удалось "ужать" прерывание хитрой динамической индикации раза в 3, точно не помню.
Ну и я удивлялся именно подходу - вместо того чтобы использовать ассемблерный код как функцию, вы предлагаете передавать параметры через глобальные переменные.
Покажите мне стандартный интерфейс передачи данных в функцию при программировании на ассемблере. Его нет, поскольку в асме нет понятия функции. Тем не менее, подпрограмма может быть подобна функции и вести себя как функция, если её снабдить интерфейсом (любого вида) передачи и возврата параметров. Я могу эту подпрограмму включить в файл *.inc и потом во всех своих программах (на ассемблере) использовать её, как вызываемую функцию.
Эм-м-м, так ведь именно это я и сделал. Вот только это извращение, в основном из-за ограничений макроязыка ассемблера. Либо придется накладывать слишком много ограничений на остальной код. Но больше меня интересует, что вы пытались сказать своей фразой.
Если процедура изменяет внутри себя значение переменной, а потом эта переменная доступна вне этой процедуры, то что это, как не возврат значения?
То есть использование var перед именем переменной? Про это я уже писал - это передача параметра внутрь, а не наружу. Прямая работа с ОЗУ - тоже не передача параметров. Или вы и sei считаете функцией?
.
Странный у вас подход - пытаться использовать мои аргументы в подтверждение своих слов, повторение одних и тех же вопросов по нескольку раз. Давайте переходить к чему-то поинтереснее копипаста, что ли.
Ответить

Вернуться в «AVR»