Как передать параметры ассемблерной вставке?
Как передать параметры ассемблерной вставке?
Всем добрый день.
Есть функция на "си" cvavr. Скажем int SUM(int a, int b).
Сложение необходимо сделать на ассемблере, как можно этой вставке передать два двухбайтных параметра, и как потом вернуть результат из вставки обратно в функцию?
Подскажите, как это можно реализовать?
Спасибо!
Есть функция на "си" cvavr. Скажем int SUM(int a, int b).
Сложение необходимо сделать на ассемблере, как можно этой вставке передать два двухбайтных параметра, и как потом вернуть результат из вставки обратно в функцию?
Подскажите, как это можно реализовать?
Спасибо!
- Реклама
Re: Как передать параметры ассемблерной вставке?
eсли это СVAVR, то может быть использовать переменные типа register unsigned char
- pyzhman
- Друг Кота
- Сообщения: 7016
- Зарегистрирован: Вс июл 12, 2009 19:15:29
- Откуда: Ижевск
- Контактная информация:
Re: Как передать параметры ассемблерной вставке?
Жмякаем F1 и ищем Calling Assembly Functions from C
Docendo discimus
Re: Как передать параметры ассемблерной вставке?
Как вариант конечно можно попробовать.
Но хотелось бы более "правильное" решение.
Как понимаю, такой тип переменных есть фичером cvavr, и другие компиляторы будут ругаться.
И не есть такое решение "религиозно правильное".
Пока, нашел только эту статью, но она для авр-гцц...
http://we.easyelectronics.ru/AVR/assemblernye-vstavki-v-avr-gcc.html
Но хотелось бы более "правильное" решение.
Как понимаю, такой тип переменных есть фичером cvavr, и другие компиляторы будут ругаться.
И не есть такое решение "религиозно правильное".
Пока, нашел только эту статью, но она для авр-гцц...
http://we.easyelectronics.ru/AVR/assemblernye-vstavki-v-avr-gcc.html
Re: Как передать параметры ассемблерной вставке?
Выше уже дали ответ - ищем Calling Assembly Functions from C, или лучше C Calling conventions для интересующего компилятора. В найденном документе будет описаны соглашения о вызове функций: как параметры передаются и возвращаются.
Вариант номер два, для ленивых. Создаем простейшую функцию с желаемой сигнатурой, компилируем, изучаем полученный ассемблерный код, ..., профит!
Вариант номер два, для ленивых. Создаем простейшую функцию с желаемой сигнатурой, компилируем, изучаем полученный ассемблерный код, ..., профит!
- Реклама
Re: Как передать параметры ассемблерной вставке?
Calling Assembly Functions from C
там написано, что параметры передаются через стек, к ним можно обратится через "y+", эта часть понятна.
Но непонятен один момент.
Если я в своей ассемблерной функции, захочу записать какое-то значение в рекистр R30, скажем. К чему это может привести?
Ведь у меня, в этом регистре, может хранится какая-то переменная, скажем глобальная? Не получится ли так, что записав туда свое значение, я потеряю то, что там было раньше?
там написано, что параметры передаются через стек, к ним можно обратится через "y+", эта часть понятна.
Но непонятен один момент.
Если я в своей ассемблерной функции, захочу записать какое-то значение в рекистр R30, скажем. К чему это может привести?
Ведь у меня, в этом регистре, может хранится какая-то переменная, скажем глобальная? Не получится ли так, что записав туда свое значение, я потеряю то, что там было раньше?
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Как передать параметры ассемблерной вставке?
про размещение глобальных переменных аналогично читаем в мануале к компилятору F1.
Ставим плюсы: )
Re: Как передать параметры ассемблерной вставке?
Почитал Allocation of variables to registers.
А так понял, что если я буду где-то в ассемблерной вставке использовать какие-то регистры, то должен держать эти регистры пустыми, и не позволять компилятору ничего глобального в них размещать.
Я так понял, что заблокировать какие-то регистры нельзя напрямую.
Но можно к регистру приписать какую-то переменную (как посоветовали в первом ответе), и выключить Smart register allocation.
В таком случае проподает необходимость из ассемблера обращаться к параметрам функции через стек, а просто пере вызовм такой функции, записывать необходимое значение в регистровую переменную, и из ассемблера она уже будет доступна "там где нужно".
Не совсем красиво конечно, но тоже может быть. Похоже, что это издержки компилятора.
Правильно думаю будет, перед вызовом ассемблерной вставки (либо внутри вставки), сохранить текущее значение используемого регистра, записать в него то, что нужно, сделать действия, а при выходе из вставки, восстанавливать старое значение.
А так понял, что если я буду где-то в ассемблерной вставке использовать какие-то регистры, то должен держать эти регистры пустыми, и не позволять компилятору ничего глобального в них размещать.
Я так понял, что заблокировать какие-то регистры нельзя напрямую.
Но можно к регистру приписать какую-то переменную (как посоветовали в первом ответе), и выключить Smart register allocation.
В таком случае проподает необходимость из ассемблера обращаться к параметрам функции через стек, а просто пере вызовм такой функции, записывать необходимое значение в регистровую переменную, и из ассемблера она уже будет доступна "там где нужно".
Не совсем красиво конечно, но тоже может быть. Похоже, что это издержки компилятора.
Правильно думаю будет, перед вызовом ассемблерной вставки (либо внутри вставки), сохранить текущее значение используемого регистра, записать в него то, что нужно, сделать действия, а при выходе из вставки, восстанавливать старое значение.
Re: Как передать параметры ассемблерной вставке?
Ерунда какая тоА так понял, что если я буду где-то в ассемблерной вставке использовать какие-то регистры, то должен держать эти регистры пустыми, и не позволять компилятору ничего глобального в них размещать.
Вы можете в своей asm вставке сделать следующее
Код: Выделить всё
В самом начале
push нужный вам регистр
а в самом конце вставки
pop нужный Вам регистрПеред командой ret
Re: Как передать параметры ассемблерной вставке?
Всем спасибо за помощь.
из-за чего весь сыр-бор.
http://code.google.com/p/boot-loader-atmega32/source/browse/trunk/cvmegaload.c?spec=svn9&r=9
Бутлодер в кодвижене.
Например, имеем такую вставку:
CurrentAddress обявлена как register unsigned int @6.
Но так вставку использовать не хочется.
А хочется передать ей параметры через стек.
Правильно ли ее вынес во вставку?
R30-31 и еще вопрос, для чего и как используется этот регистр?
из-за чего весь сыр-бор.
http://code.google.com/p/boot-loader-atmega32/source/browse/trunk/cvmegaload.c?spec=svn9&r=9
Бутлодер в кодвижене.
Например, имеем такую вставку:
Код: Выделить всё
#asm
movw r30, r6 ;//move CurrentAddress to Z pointer
mov r1, r3 ;//move Pagedata MSB reg 1
mov r0, r2 ;//move Pagedata LSB reg 1
sts SpmcrAddr, r10 ;//move spmcrval to SPM control register
spm ;//store program memory
#endasm
CurrentAddress обявлена как register unsigned int @6.
Но так вставку использовать не хочется.
А хочется передать ей параметры через стек.
Правильно ли ее вынес во вставку?
Код: Выделить всё
void fill_temp_buffer(unsigned int CurrentAddress, unsigned int Pagedata, char cmd){
#asm
push r30
push r31
push r1
push r0
movw r30, y+3 ;//move CurrentAddress LSB to Z pointer
movw r31, y+4 ;//move CurrentAddress MSB to Z pointer
mov r1, y+2 ;//move Pagedata MSB reg 1
mov r0, y+1 ;//move Pagedata LSB reg 1
sts SpmcrAddr, y ;//move spmcrval to SPM control register
spm ;//store program memory
pop r0
pop r1
pop r31
pop r30
#endasm
}
R30-31 и еще вопрос, для чего и как используется этот регистр?
Re: Как передать параметры ассемблерной вставке?
http://www.avr-asm-tutorial.net/avr_en/beginner/REGISTER.html
A very special extra role is defined for the register pairs R26:R27, R28:R29 and R30:R31. The role is so important that these pairs have extra names in assembler: X, Y and Z. These pairs are 16-bit pointer registers, able to point to adresses with max. 16-bit into SRAM locations (X, Y or Z) or into locations in program memory (Z).
Всем спасибо!
A very special extra role is defined for the register pairs R26:R27, R28:R29 and R30:R31. The role is so important that these pairs have extra names in assembler: X, Y and Z. These pairs are 16-bit pointer registers, able to point to adresses with max. 16-bit into SRAM locations (X, Y or Z) or into locations in program memory (Z).
Всем спасибо!
Re: Как передать параметры ассемблерной вставке?
Получилось сделать следующим образом:
Но, остался непонятен один вопрос, теоретический.
Почему вызов команды push не вызывает увеличение указателя стека?
С помощью push, я сохраняю в стеке значение пяти регистров (я так думаю). Соответственно, что-бы после этого обратится к моим параметрам функции, я должен делать так:
Но если я так делаю, то у меня ничего не работает.
С чем это может быть связано?
Подозреваю, что команда push сохраняет значение в другой стек "hardware stack"? а передача параметров в функцию идет через "data stack", на его вершину казывает "y". Так ли это?
Код: Выделить всё
void fill_temp_buffer(unsigned int data, unsigned int adr){
while (SPMCSR&1); //wait for spm complete
#asm
push r30
push r31
push r20
push r0
push r1
ldi r20, 1 ;//put CMD to r20
ld r30, y ;//move CurrentAddress LSB to Z pointer
ldd r31, y+1 ;//move CurrentAddress MSB to Z pointer
ldd r0, y+2 ;//move data LSB
ldd r1, y+3 ;//move data MSB
sts 0x68, r20 ;//move CMD to SPM control register
spm ;//store program memory
pop r1
pop r0
pop r20
pop r31
pop r30
#endasm
}
Но, остался непонятен один вопрос, теоретический.
Почему вызов команды push не вызывает увеличение указателя стека?
С помощью push, я сохраняю в стеке значение пяти регистров (я так думаю). Соответственно, что-бы после этого обратится к моим параметрам функции, я должен делать так:
Код: Выделить всё
ldd r30, y+5 ;//move CurrentAddress LSB to Z pointer
ldd r31, y+6 ;//move CurrentAddress MSB to Z pointer
ldd r0, y+7 ;//move data LSB
ldd r1, y+8 ;//move data MSB
Но если я так делаю, то у меня ничего не работает.
С чем это может быть связано?
Подозреваю, что команда push сохраняет значение в другой стек "hardware stack"? а передача параметров в функцию идет через "data stack", на его вершину казывает "y". Так ли это?
Re: Как передать параметры ассемблерной вставке?
Почему вызов команды push не вызывает увеличение указателя стека?
А куда он должен увеличится, Вы так сказать физически представляете где он находится?
Это ведь самый конец области SRAM-в стандартном (default) его определении.Правда его можно переназначать куда угодно , но Вам пока это не надо. И называется этот адрес ВЕРШИНА стека. Выше этой точки , для человека, только облака, озоновый слой, Господь Бог.
Для процессора- неконтролируемое падение вниз и "убивание" всех данных начиная с регистров и заканчивая SRAM.
Поэтому команда PUSH , уменьшает указатель адреса т.е. спускает Вас с горы плавненько так и без эксцессов. А команда POP увеличивает - поднимает Вас в гору.
Re: Как передать параметры ассемблерной вставке?
Да, в даташите так и есть.
The Stack Pointer Register always points
to the top of the Stack. Note that the Stack is implemented as growing from higher memory locations
to lower memory locations. This implies that a Stack PUSH command decreases the Stack
Pointer.
Еще там есть такое:
The Stack is mainly used for storing temporary data, for storing local variables and for storing
return addresses after interrupts and subroutine calls.
А через какой stack передаются параметры в функуию, при ее вызове?
почему после вызова 5раз push.
вот этот код не работает?
а работает так:
т.е. почему после вызовов push не нужно увеличивать и y?
The Stack Pointer Register always points
to the top of the Stack. Note that the Stack is implemented as growing from higher memory locations
to lower memory locations. This implies that a Stack PUSH command decreases the Stack
Pointer.
Еще там есть такое:
The Stack is mainly used for storing temporary data, for storing local variables and for storing
return addresses after interrupts and subroutine calls.
А через какой stack передаются параметры в функуию, при ее вызове?
почему после вызова 5раз push.
вот этот код не работает?
Код: Выделить всё
ldd r30, y+5 ;//move CurrentAddress LSB to Z pointer
ldd r31, y+6 ;//move CurrentAddress MSB to Z pointer
ldd r0, y+7 ;//move data LSB
ldd r1, y+8 ;//move data MSB
а работает так:
Код: Выделить всё
ld r30, y ;//move CurrentAddress LSB to Z pointer
ldd r31, y+1 ;//move CurrentAddress MSB to Z pointer
ldd r0, y+2 ;//move data LSB
ldd r1, y+3 ;//move data MSB
т.е. почему после вызовов push не нужно увеличивать и y?
Re: Как передать параметры ассемблерной вставке?
почему после вызова 5раз push.
Если уж быть точным то как минимум 7. Всё зависит от памяти программ процессора.
Первым , и от вас не зависящим в стек уходит адрес возврата из функции, затем стек отдается на "разгробление" программисту. Сколько он посчитает нужным сохранить данных , столько раз он напишет push.
Что же касается вот этого
То это косвенная адресация к SRAM , комманда LDD давно заменена на LD. Расшифрую , что здесь написано
Загрузить регистр R30, данными которые надо взять из ячейки SRAM находящейся по адресу Y (какой-то базовый адрес) +5 . Если Y=60 , то данные в R30 загрузятся из адреса 65
Следующая строка R31 получит данные с адреса 66 ну и т.д 67/ Но , что Вы хотите сделать - мне не ясно
Если уж быть точным то как минимум 7. Всё зависит от памяти программ процессора.
Первым , и от вас не зависящим в стек уходит адрес возврата из функции, затем стек отдается на "разгробление" программисту. Сколько он посчитает нужным сохранить данных , столько раз он напишет push.
Что же касается вот этого
Код: Выделить всё
ldd r30, y+5 ;//move CurrentAddress LSB to Z pointer
ldd r31, y+6 ;//move CurrentAddress MSB to Z pointer
ldd r0, y+7 ;//move data LSB
ldd r1, y+8 ;//move data MSBТо это косвенная адресация к SRAM , комманда LDD давно заменена на LD. Расшифрую , что здесь написано
Код: Выделить всё
ldd r30, y+5Следующая строка R31 получит данные с адреса 66 ну и т.д 67/ Но , что Вы хотите сделать - мне не ясно
Re: Как передать параметры ассемблерной вставке?
Немогу объяснить чего я хочу...
Получается так, что адрес хранящийся в y и адрес вершины стека это разные "вещи"?
И вызов команды push не вызывает увеличение y?
Куда в таком случае указывает у, на какую часть памяти проца, где она физически находится (по умолчанию)?
Получается так, что адрес хранящийся в y и адрес вершины стека это разные "вещи"?
И вызов команды push не вызывает увеличение y?
Куда в таком случае указывает у, на какую часть памяти проца, где она физически находится (по умолчанию)?
- U235
- Встал на лапы
- Сообщения: 135
- Зарегистрирован: Вт фев 21, 2012 20:42:26
- Откуда: Санкт-Петербург, Россия, Земля
Re: Как передать параметры ассемблерной вставке?
Использование оперативной памяти расписано на странице "RAM Memory Organization and Register Allocation", вот картинка оттуда.

Стек данных используется для динамического хранения локальных переменных, передачи параметров функций и для сохранения значений регистров при прерывании.
Стек данных используется для динамического хранения локальных переменных, передачи параметров функций и для сохранения значений регистров при прерывании.
- Вложения
-
- cvar.PNG
- (25.63 КБ) 1894 скачивания
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Re: Как передать параметры ассемблерной вставке?
Согласен, именно эта картинка из хелпа меня и смущает... 
Есть два стека, один аппаратный, другой програмный.
"Стек данных используется для динамического хранения локальных переменных, передачи параметров функций и для сохранения значений регистров при прерывании."
Обращение к этому стеку идет через Y, так понимаю для ассемблера y и Y и R32/33 это одно и то же?
И команда push, кладет значение регистра в аппаратный стек, а не в програмный? Правильно?
Для этого у меня не происходит "съезд" указателья Y, после вызова push?
Есть два стека, один аппаратный, другой програмный.
"Стек данных используется для динамического хранения локальных переменных, передачи параметров функций и для сохранения значений регистров при прерывании."
Обращение к этому стеку идет через Y, так понимаю для ассемблера y и Y и R32/33 это одно и то же?
И команда push, кладет значение регистра в аппаратный стек, а не в програмный? Правильно?
Для этого у меня не происходит "съезд" указателья Y, после вызова push?
Re: Как передать параметры ассемблерной вставке?
Так, если честно не читал всю ветку, но.
Обычно, доступ к параметрам из asm представляется внутри функции.
При вызове функции в листинге ассемблера происходит слудующее:
обязательно вычищаем всё что push, pop. Иначе ret не сможет отработать нормально, потому-что адрес возврата тоже кладётся в стек. Сейчас лень вспоминать многое. Поэтому можете рассказать подробнее что нужно. Приходилось изучать вопрос этого симбиоза.
Естественно, если мы используем си, то там за нас уже всё сделали. И по идее можно подставлять параметры уже готовые. Например:
А вот живой и рабочий пример в C++
Обычно, доступ к параметрам из asm представляется внутри функции.
При вызове функции в листинге ассемблера происходит слудующее:
Код: Выделить всё
push param3
push param2
push param1
call FucnAddr
FuncAddr:
pop param1
pop param2
pop param3 //Куда попать полученные данные без разницы. хоть в выделеную память хоть по регистрам, на выбор.
//производим действия с параметрами
//размещаем в eax результат выполнения (
mov eax, result
ret
обязательно вычищаем всё что push, pop. Иначе ret не сможет отработать нормально, потому-что адрес возврата тоже кладётся в стек. Сейчас лень вспоминать многое. Поэтому можете рассказать подробнее что нужно. Приходилось изучать вопрос этого симбиоза.
Естественно, если мы используем си, то там за нас уже всё сделали. И по идее можно подставлять параметры уже готовые. Например:
Код: Выделить всё
int Test(char a,char b) {
__asm {
mov eax, a
mov ebx, b
sub eax, ebx
ret // по логине это затрёт наше нижнее значение и вернёт результат.
};
return 0;
}
А вот живой и рабочий пример в C++
Код: Выделить всё
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
int Test(int a,int b);
int main(int argc,char* argv[])
{
int res=Test(10,5);
printf("Hello World! %d",res);
cin.get();
return 0;
}
int Test(int a,int b) {
__asm {
mov eax, a
mov ebx, b
sub eax, ebx
//начиная отсюда, реализуется код который вставляет компилятор для обработки.
pop edi
pop esi
pop ebx
add esp,0C0h
cmp ebp,esp
mov esp,ebp
pop ebp
ret // по логине это затрёт наше нижнее значение и вернёт результат.
};
return 0;
}
Re: Как передать параметры ассемблерной вставке?
Спасибо за помощь.
Чем дальше, тем больше вопросов...С ассемблером знаком пару дней, много не ясно.
1 (основной).
В какой стек команда push кладет свой аргумент. В аппаратный стек или програмный (стек данных)?
2. почему сделано разделение на два стека?
Почему бы все не хранить в одном стеке (локальные переменные, параметры функций, значения записанные туда с помощью push, адреса возвратов. Ведь все-равно, после выхода из функции, все локальные переменные удаляются, соответственно компилятор мог-бы автоматически удалять все эти временные данные.
Вопросы относительно кодвижена.
Вот.
Чем дальше, тем больше вопросов...С ассемблером знаком пару дней, много не ясно.
1 (основной).
В какой стек команда push кладет свой аргумент. В аппаратный стек или програмный (стек данных)?
2. почему сделано разделение на два стека?
Почему бы все не хранить в одном стеке (локальные переменные, параметры функций, значения записанные туда с помощью push, адреса возвратов. Ведь все-равно, после выхода из функции, все локальные переменные удаляются, соответственно компилятор мог-бы автоматически удалять все эти временные данные.
Вопросы относительно кодвижена.
Вот.


