Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Тема: Асеблерная процедура в C++ (передача указателя на неопр. тип)

279
20 июня 2005 года
bave
456 / / 07.03.2004
Задача следующая:
Есть массив данных 256 x 256 где каждый элемент массива ячейка памяти размером 3 байта.
Нужно написать ассемблерную процедуру на внешнем ассемблере, которая выполняет
взаимную замену первого и третьего байта в каждом элементе.
Т. е. при программировании уже на языке С++ эта функция должна
объявляться примерно так:
//-----------------------------------------
extern void near convert(void*);
//-------------------------------------
Мне бывало приходилось программировать на ассеблере как для реального так и
для защищённого режима, очень редко, но бывало использовал и встроенный ассеблер
(это ещё во времена программирования на паскале).
Но вот с задачей когда нужно писать ассеблерную процедуру которая будет вызываться
на С++ я решаю впервые (вообще говоря теоретически я знаю как это сделать, но
вот практически я это делаю в первый раз). Вообщем я не уверен всё ли
я правильно делаю и ещё есть некоторые вопросы, далее я приведу
ассеблерный код процедуры, где в коментариях вопросы и напишу:
(возможно есть некоторые мелкие недочёты, которые ускользнули от моих глаз
(глаза у меня последнее время красные и усталые) поэтому если вы их
увидите и укажите мне их сочту за помошь, а не за придирку.)
;Вообщем использую директивы сегментации в соотвествии с соглашениями о линковке в C
;До этого я использовал только упрощённые директивы, и хочу заметить, что тип выравнивания WORD я выбрал не осознано
;т. е. возможно он должен быть другим. Соотвественно тоже самое могу сказать о модификаторе near - возможно 16-ти
;разрядного адреса не достаточно для вызова этой функции (???).
_TEXT SEGMENT WORD PUBLIC 'CODE'
ASSUME cs: _TEXT
PUBLIC _convert
_convert PROC
push ebp
mov ebp,esp
;Вот и вопрос: аргументом является указатель на неопределённый тип,
;сколько тогда места в стеке для него отводить????
;sub esp, ???
;mov [ebp - ???], 0 ;Очистка места под локальные переменные
;..........
;---------------------------------------------------------------------------------------------
convert:
mov ecx, 256*256
mov ebx, [esp]
label:
mov al,[ebx+0]
mov ah,[ebx+2]
mov [ebx+2],al
mov [ebx+0],ah

add ebx,3
dec ecx
jnz label
exit:
mov esp,ebp ;востанавливаю
pop ebp ;регистры
ret
_convert ENDP
_TEXT ENDS
END
;-------------------------------------------------------------
Данная функция в программе на языке C++ будет вызываться как внешняя -
но чтоб её вызвать помоему недостаточно того, чтобы этот
исходник оттранслированный в .obj файл лежал в той же дирректории,
поему он тоже должен быть прилинкован к программе
(если да то как) - возможно я и ошибаюсь - вообщем вопрос в том, где должна
быть вызываемая внешняя ассемблерная процедура.
1.8K
22 июня 2005 года
Sanya DLR
123 / / 03.03.2004
Могу ошибаться...
Вроде (я по досовской памяти) нужен файл .prj, где указано имя самого .c а и всех дополнительных .obj
Этот файл указывался в настройках проекта как ProjectName.
Сишник - как Primary C file.
Потом делалось Build all.

;sub esp, ??? - это видимо отводится место под локальные переменные(типа много PUSH'ей)? Да?
;mov [ebp - ???], 0 ; - а это видимо они обнуляются...

mov ebx, [esp] - вроде esp пока не указывает на аргумент функции(для этого вроде надо add esp,4 (типа POP адрес_возврата) а не sub)??? а скорее на последнюю локальную переменную. А если они не выделялись (а там как раз закомментировано), то - на адрес возврата. И я так понимаю, что при 32 разрядной адресации и адрес возврата и указатель на что бы то ни было (тоже адрес) - 32 разрядные
279
23 июня 2005 года
bave
456 / / 07.03.2004
Цитата:

;sub esp, ??? - это видимо отводится место под локальные переменные(типа много PUSH'ей)? Да?
;mov [ebp - ???], 0 ; - а это видимо они обнуляются...

mov ebx, [esp] - вроде esp пока не указывает на аргумент функции(для этого вроде надо add esp,4 (типа POP адрес_возврата) а не sub)???


Спасибо, за ответ - возможно я опять вопрос не
подробно расписал - Мне не нужно объяснять код,
код асmov ebx, [esp] себлерной процедуры мой - что там как
работает я знаю, а вот там где заки вопроса я
поставил - там я незнаю какие значения операндов брать.
Поставлю вопрос по другому
1. Стек растёт в сторону младших, адресов.
Передача аругуметов в функцию происходит через
стек и при использовании внешнего ассеблера
эту передачу организует сам программист
(алкгоритм записи в стек я не пишу, только
поясню что раз записывается передоваемый
аргумент здесь PUSH использовать не вйдет,
надо всё в рукопашную сделать.)
Т. е. во первых надо присвоить новое значение
вершине стека - вот я это и делаю sub esp, ??? - знаки вопроса потому что Я НЕ ЗНАЮ НА
СКОЛЬКО НАДО СМЕСТИТЬ ВЕРШИНУ СТЕКА, ЧТОБ УКАЗАТЕЛЬ на неопределённый тип поместился в стек.
2. mov [ebp - ???], 0; - обнуляется место под локальные переменные - ebp - содержит старую вершину стека, ebp - ??? - соответственно получаем
адресс новой вершины стека, но т. к. я не знаю
на сколько байт в памяти сместилась вершина стека там знаки вопроса.
3. add esp,4 ?!? - ты хочешь сказать что смешение
на начало аргумента = esp + 4 - ну поробую,
так, тогда и везде место знаков вопроса
можно писать 4 по идее.

1.8K
24 июня 2005 года
Sanya DLR
123 / / 03.03.2004
///sub esp, ??? - НА СКОЛЬКО НАДО СМЕСТИТЬ ВЕРШИНУ СТЕКА, ЧТОБ УКАЗАТЕЛЬ на неопределённый тип поместился в стек.///
Я не въезжаю, почему за параметром ВНИЗ !?!?!?!? И если нету локальных переменных, то зачем их обнулять и вобще выделять место в стеке...
Вызов функции, как я понимаю идет так:
PUSH параметры
CALL функция

То есть сначала пушим параметры (если под винду, 32 разрядная адресация, значит адрес (а указатель - это адрес) - размер 4 байта)
потом уже адрес возврата (видимо тоже 4 байта, я под винду не асмил - может чего-то не знаю)
Стек растет вниз... стало быть за параметром функции надо лезть вверх, перелезая через адрес возврата. [sp]=Адрес возврата, [sp+размер_адреса_возврата]=переданный в функцию параметр.
Если речь о ДОС, тогда размер адреса возврата в зависимости от модификатора функции near/far (2/4), а размер указателя... хмм... а попробовать SizeOf(pointer) в какой-нибудь сишной проге???
279
24 июня 2005 года
bave
456 / / 07.03.2004
Цитата:
Originally posted by Sanya DLR
///sub esp, ??? - НА СКОЛЬКО НАДО СМЕСТИТЬ ВЕРШИНУ СТЕКА, ЧТОБ УКАЗАТЕЛЬ на неопределённый тип поместился в стек.///
Я не въезжаю, почему за параметром ВНИЗ !?!?!?!?


Стек растёт в сорону младших адресов.
Новая вершин стека смешается в более младшие
адреса.

Цитата:
Originally posted by Sanya DLR
/// И если нету локальных переменных, то зачем их обнулять и вобще выделять место в стеке...


Аргументы через стек передаются. И для них надо место. А аргумент в данном случае указатель -
и кастет, походу ты прав он будет 4 байта.
А sizeof я не использую потому что этот указатель
на неопределённый тип.
--------------------------------------------
Осталось выяснить как это правильно прилинковать.

12K
02 июля 2005 года
rgo
11 / / 02.07.2005
esp указывает на вершину стека, на которой лежит адрес возврата, под этим адресом возврата лежит первый аргумент, затем второй и тд тп.
размер адреса возврата зависит от разрядности адреса (32, 16 бит), размер void* зависит от разрядности данных. без специальных заморок эти разрядности совпадают. C функция получая управления должна сохранить ряд регистров (что именно за регистры зависит от системы но ebp в это списке обязательно). Возвращаемое значение возвращается через eax.
Теперь как этим пользоваться

my_proc:
push ebp ; сохраняем ebp как завещано конвенцией вызова
mov ebp, esp ; засовываем в ebp указатель на вершину стека
; чтобы удобнее до аргументов добираться
mov eax, [ebp+8] ; первый аргумент в eax
; делаем очень много полезного

pop ebp
ret

все эти add esp, ??? -- это динамическое выделение памяти из стека под локальные переменные (которые тоже, кстати, адресуются через ebp).
А по большому счёту и эти замороки с ebp не нужны, если конвенция вызова позволяет похерить значения хотя бы двух регистров.
Есть ысчо одна заморока -- искажение имён. Подчастую компилятор измывается над именами переменных, то есть если я напишу в *.h файле:
void my_proc (void*);
то компилер может записать в *.obj что нужна функция по имени _my_proc, C++ компилятор этим не обходится и выпендривается как может. И каждый компилятор делает это по разному...
279
05 июля 2005 года
bave
456 / / 07.03.2004
Я вот думаю теперь, ну нафиг прилинковывать
эту функцию, мне ещё другие функции писать надо,
которые тоже внешние и тоже на асме, может их
всех в dll'ку обособить и от туда и вызывать
проще.
1.8K
06 июля 2005 года
Sanya DLR
123 / / 03.03.2004
А может ну его, этот ассемблер - все на си писать? Знаючи как - можно написать не хуже...
253
06 июля 2005 года
Proger_XP
1.5K / / 07.08.2004
Цитата:
Originally posted by bave
Я вот думаю теперь, ну нафиг прилинковывать
эту функцию, мне ещё другие функции писать надо,
которые тоже внешние и тоже на асме, может их
всех в dll'ку обособить и от туда и вызывать
проще


Кидай все в DLL - проще, да и вдруг понадоится юзать ее несколькими прогами

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог