Форум программистов, компьютерный форум, киберфорум
Assembler: Windows/protected mode
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/56: Рейтинг темы: голосов - 56, средняя оценка - 4.54
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433

Вызов ассемблерной процедуры из программы на C++

11.03.2019, 16:39. Показов 11899. Ответов 28

Студворк — интернет-сервис помощи студентам
Добрый день!
Требуется написать подпрограмму на ассемблере, в которую бы передавался аргумент из программы на C++, с ним производились бы некоторые вычисления (у меня подсчет котангенса) и результат возвращался назад в программу на C++.
На форуме нашёл нечто подобное Сопроцессор: вычисление гиперболического тангенса
Листинг прикладываю
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
;.model small
;e2x-1/e2x+1
 
                .386
_TEXT           segment use32 para public 'CODE'
                public  _asmth
                public  __CItanh
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+12]
 
_asmth          proc    near
                assume  cs:_TEXT
                push    ebp
                mov     ebp,esp
                fld     qword ptr [ebp+8]       ; загрузка в стек
                fld     st                      ; дублируем
                fadd                            ; 2*x
                fldl2e                          ; log по основан 2 от (e)
                fmulp   st(1),st                ; x * log base 2(e)
                fst     st(1)                   ; copy
                frndint                         ; округлен до целого
                fsub    st(1),st                ; вычитание
                fxch                            ; обмен st, st(1)
                f2xm1                           ; вычисление 2 в степени (x - 1)
                fld1                            ; загрузка единицы
                fadd                            ; сложение;2 to the x
                fscale                          ; Scale by power of 2
                fstp    st(1)                   ; Set new stack top and pop
                fld1                            ; загрузка единицы
                fadd                            ; вычисление exp(2*x)+1
                fld1                            ; загрузка единицы
                fld1                            ; загрузка единицы
                fadd                            ; Set divisor to 2
                fdivr                           ; Compute 2/(exp(2*x)+1)
                fld1                            ; загрузка единицы
                fsubr                           ; вычислен th
        ;fstp qword ptr [ebp+12];result
                pop     ebp                     ; Restore register bp
                ret
_asmth          endp
 
__CItanh        proc    near
                assume  cs:_TEXT
                sub     esp,8                   ; Allocate stack space for x
                fstp    qword ptr [esp]         ; Copy x onto stack
                call    _asmth                  ; Call tanh
                add     esp,8                   ; Remove x from stack
                ret
__CItanh        endp
 
_TEXT           ends                            ;End of segment
                end                             ;End of module
Пока такие вопросы:
1. Имя сегмента названо как "_TEXT". Это для того, чтобы связываться с C++ ? Обязательно ли должен стоять знак подчеркивания?
2. Что значат строки public _asmth и public __CItanh , объявление процедур ? Почему в одном имени используется один знак подчёркивания, а в другом два, это для связки с C++ ?

p.s. мне только удалось нагуглить имена для связки с Паскалем https://rsdn.org/article/asm/asmdirectives.xml
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.03.2019, 16:39
Ответы с готовыми решениями:

Вызов ассемблерной процедуры в программе на Си
Задание: В си-программе ввести матрицу 5х6 чисел(где каждая ячейка матрицы представляет строку символов),ввести диапазон значений. Написать...

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

Вызов функции в ассемблерной вставке C++.
Нужно ввести строку, объясните как вызвать и как параметры передать. Пусть это будет cin.getline.

28
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.03.2019, 18:34
Лучший ответ Сообщение было отмечено Timurs как решение

Решение

Посмотрите https://en.ppt-online.org/15252 - ознакомьтесь со всем, но уделите внимание страницам 49, 76-82.
Там с упрощённой сегментацией.

Здесь http://www.i-assembler.ru/34/ch3-7.html

По полному описанию сегментов - сразу и не вспомню, скорее всего нужно искать в документации на masm любой версии. Может в книгах Юрова, Зубкова, Магды есть.

Сказать по правде, такие детали как подчёркивание, названия сегментов и ещё всякое - просто принимаю как данное от разработчиков, без осмысления и критики.
По подчёркиванию имён припоминаю, что если в модели указать язык C, то самостоятельно его добавлять не нужно, а если всё прописывается "вручную", как в приведённом коде - то подчёркивание необходимо. Это просто смутное воспоминание, которое нужно проверить.
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
11.03.2019, 18:48  [ТС]
Походу всё это дело описано тут http://www.codenet.ru/progr/cpp/qc/c.php#10
Но я что-то запутался...
Например, следующая выдержка
Программа на языке СИ может вызвать процедуру на языке Ассемблер, находящуюся в другом модуле, как и при вызове СИ-функции. В дополнение к шагам, описанным в Разделе С.1 "Написание процедуры на языке Ассемблер", могут оказаться полезными следующие правила:

1.Описывайте процедуры, вызываемые из СИ-программ с ключевым словом far, если СИ-модуль был скомпилирован в большой, сверхбольшой или средней модели памяти, и с ключевым словом near, если СИ-модуль был скомпилирован в малой или компактной модели. Ключевые слова far или near отменяют любые стандартные назначения. Если вы используете директиву .MODEL, имеющуюся в Microsoft Macro Assembler версии 5.0, объявление модели памяти для процедуры делается явно.
Вот никак не пойму, если у нас написано
Assembler
1
 _TEXT segment para public 'CODE' use32
,
то мы используем стандартные директивы сегментации, а не упрощённые, а значит у нас нет никакой модели памяти.
В таком случае мы сами, по логике, должны выбирать между near и far.
Но как определить какую из них использовать?
Различие между ними заключается в следующем:
Отличия близких от далеких вызовов и возвратов заключаются в размерности изменяемых адресов:
• близкие вызовы и возвраты изменяют только смешения в сегменте и позволяют передавать управление в пределах сегмента. Фактически в этом случае изменяется только содержимое регистра IP/EIP;
• далекие вызовы и возвраты изменяют не только смещения в сегменте, но и сегментную часть адреса и позволяют передавать управление между сегментами. В этом случае изменяется не только содержимое регистра IP/EIP, но и содержимое сегментного регистра CS.
Но, честно говоря, мне, увы, не удалось понять в каких ситуациях near или far писать...
p.s. ответ на первый вопрос удалось найти тут http://files.lib.sfu-kras.ru/e... embler.pdf
прикрепил к фото
Миниатюры
Вызов ассемблерной процедуры из программы на C++   Вызов ассемблерной процедуры из программы на C++   Вызов ассемблерной процедуры из программы на C++  

Вызов ассемблерной процедуры из программы на C++  
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
11.03.2019, 18:51  [ТС]
ФедосеевПавел, спасибо! Сейчас до дома добегу почитаю, батарея на ноуте садится уже. Имя сегмента кода _TEXT приняли просто, чтобы путаницу убрать, т.е. ни к какому языку оно не привязано. А вот с названиями процедур привязка какая-то к языкам походу точно есть...
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.03.2019, 19:29
Лучший ответ Сообщение было отмечено Timurs как решение

Решение

По вашим ссылкам и скринам. Забудьте и выбросьте. Это пояснения для программ QuickC и MASM для 16-разрядной DOS.
В Windows используется ТОЛЬКО модель FLAT и соответственно только переходы и вызовы процедур типа NEAR.
Что-то из этих описаний осталось справедливым и сейчас, но представьте, что читаете техническую литературу типа "верю-не верю".
1
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
11.03.2019, 20:14  [ТС]
ФедосеевПавел, понял этот момент. А сегмент данных если прицепить, то он ведь не нарушит передачу процедуры? Сегмент данных я хочу использовать для итератора, который по коэффициентам иксов будет бегать, а также под эпсилон, для условия когда прекратить вычисление.

А на форуме здесь вычисление котангенса через его разложение вряд делалось?
Прикинул сейчас, не очень понятно в какой именно точке его раскладывать, в нуле не раскладывается. Ещё большую озабоченность вызывает, что не удалось найти формулы в виде суммы в общем виде, непонятные коэффициенты перед иксами.
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
11.03.2019, 21:16
Т.к. название темы - "Вызов ассемблерной процедуры из программы на C++", то имеет смысл разбирать в ней именно "вызов...".
По котангенсу создавайте отдельную тему.

В ассемблерном листинге можно добавлять глобальные переменные через сегмент данных.
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 00:35  [ТС]
ФедосеевПавел, с котангенсом согласен, это дело десятое. Завтра попробую доразобраться с вызовом, а потом на котангенс уже переключусь.
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 14:52  [ТС]
ФедосеевПавел,
Assembler
1
2
3
4
5
6
7
8
9
;используем директиву .386 для того, чтобы компилятор
;TASM формировал 32-битные команды
.386
;в Windows используется плоская (flat) модель памяти
.model flat
;сегмент данных
.data
;i=4
i dd 4
А дальше у меня ступор. Если функция из C++ имела два аргумента, то как их принять на ассемблере? Я что-то так и не понял... Также не понял в каком сегменте этот приём осуществлять - в сегменте данных или сегменте кода?
Строки
Assembler
1
2
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+12]
Что значат? Почему именно так написано. Под qword выделяется 4 байта. А адрес возврата на верхушку стека закидывает команда call, которой у нас тут в принципе быть не может. Как вообще узнать сколько байт выделено тут под адрес возврата, почему именно 8 ?
Собственно эти моменты не дают возможности написать ассемблерную процедуру. А остальное вроде понятно как делать.
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 15:07
Пусть
C
1
int myfunc(int first, int second)
Вызов подпрограммы cdecl
Assembler
1
2
3
push dword ptr [second]
push dword ptr [first]
call myfunc
Начало подпрограммы
Assembler
1
2
push ebp
mov ebp, esp
Таким образом в стеке располагаются:
Code
1
2
3
4
[second]
[first]
адрес возврата
прежнее содержимое ebp
Таким образом, обращение к first - dword ptr [bp+8]

И т.д.

Читайте соглашение о вызовах. Для соглашения Pascal порядок параметров будет обратный
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 16:23  [ТС]
ФедосеевПавел, такое будет работать?

C
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
extern "C" int _sum(double source, double result)
int main(){
double source = 7.7, double result = 0.0;
cout << _sum(source, result) << '\n';
return 0;
}
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
;используем директиву .386 для того, чтобы компилятор
;TASM формировал 32-битные команды
.386
;в Windows используется плоская (flat) модель памяти
.model flat, C
;сегмент данных
.data
;i=4
i dd 4
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+16]
;сегмент кода
.code
public _sum
_sum proc
finit ;инициализация
fld source ;кладём в стек источник
fld i ;итератор
fadd st(0), st(1) ;складываем
fst result
_sum endp
end
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 16:32
Нет. По тем же причинам, что и
C
1
2
3
4
5
int _sum(double source, double result);
{
  result=source+i;
  return 1;
}
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 16:40  [ТС]
ФедосеевПавел, а так ?

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.386
.model flat, C
.data
i dd 4
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+16]
;сегмент кода
.code
public _sum
_sum proc
finit ;инициализация
fld qword ptr [ebp+8] ;кладём в стек источник
fld i ;итератор
fadd st(0), st(1) ;складываем
fst qword ptr [ebp+16]
_sum endp
end
Вроде бы в кусок qword памяти по указателю ptr [ebp+16] должно писаться вычисленное значение...

p.s. fadd даже не синим подсвечивается почему то...
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 16:47
Передача не через указатель. В стеке result изменится, после завершения функции - стек освободится и изменения забудутся. Я привёл эквивалент такой же нерабочей на C.

Почитайте по моим ссылкам. Что вы гадаете? Возврат double через вершину стека FPU.

Добавлено через 43 секунды
Да и пробуйте проверять выполнением.
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 17:30  [ТС]
ФедосеевПавел, как-то запутано написано.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.386
.model flat
.data
i dd 4
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+16]
;сегмент кода
.code
public _sum
_sum proc
push ebp
mov ebp, esp
finit ;инициализация
fld qword ptr [ebp+8] ;кладём в стек источник
fld i ;итератор
fadd st(0), st(1) ;складываем
ret
_sum endp
end
Смысла этих строк не очень понимаю, то есть пока не положим ebp в стек и не перепишем его регистром esp не увидим
source и result ?
Assembler
1
2
push ebp
mov ebp, esp
И про ret написано целое количество байт извлекаемых из стека, тоже не очень понял.
Или имеется ввиду так сделать
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.386
.model flat, C
.data
i dd 4
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+16]
;сегмент кода
.code
public _sum
_sum proc
push ebp
mov ebp, esp
finit ;инициализация
fld qword ptr [ebp+8] ;кладём в стек источник
fld i ;итератор
fadd st(0), st(1) ;складываем
fst ebp
ret
_sum endp
end
Но опять же где гарантия, что он вернёт значение именно в result

p.s. запускать в visual studio 2017 буду, а там разбираться с этим ещё минимум час. И то не факт, что получится. А когда знаешь, что хотя бы сама процедура правильная, то уже лучше, как минимум ошибка не в ней
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 17:47
А так, предлагаете мне разобраться без visual studio 2017 (vc мне не нужна и потому не установлена)?

Читайте соглашения о вызовах, о передаче параметров. По double я вам ровно 1 час назад писал - как передать результат из подпрограммы.
0
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 17:50  [ТС]
Цитата Сообщение от Timurs Посмотреть сообщение
Смысла этих строк не очень понимаю, то есть пока не положим ebp в стек и не перепишем его регистром esp не увидим
source и result ?
Assembler
1
2
push ebp
mov ebp, esp
Имел ввиду, что внутри ассемблерной процедуры не увидим значения source например.
И продолжая логику. Если это действительно так, то в сегменте данных эти строки
Assembler
1
2
source equ qword ptr [ebp+8]
result equ qword ptr [ebp+16]
не отработают, так как сегмент данных идёт раньше сегмента кода.
Тогда вроде бы так логично написать
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.386
.model flat, C
.data
i dd 4
;сегмент кода
.code
         public _sum
_sum  proc
         push ebp
         mov ebp, esp
         source equ qword ptr [ebp+8]
         result equ qword ptr [ebp+16]
         finit ;инициализация
         fld qword ptr [ebp+8] ;кладём в стек источник
         fld i ;итератор
         fadd st(0), st(1) ;складываем
         fst ebp
         ret
_sum  endp
end
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 17:53
https://docs.microsoft.com/ru-... ew=vs-2017
https://docs.microsoft.com/ru-... ew=vs-2017
0
Модератор
Эксперт по электронике
 Аватар для ФедосеевПавел
8644 / 4479 / 1669
Регистрация: 01.02.2015
Сообщений: 13,883
Записей в блоге: 11
12.03.2019, 17:59
https://ru.wikipedia.org/wiki/Соглашение_о_вызове
1
59 / 49 / 14
Регистрация: 23.02.2016
Сообщений: 433
12.03.2019, 17:59  [ТС]
ФедосеевПавел, пойду экспериментировать. Как получится, выложу результат.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.03.2019, 17:59
Помогаю со студенческими работами здесь

Заменить вызов функции ассемблерной вставкой
Добрый вечер ! Вот такая проблема, мне нужно заменить вызов функции ассембл вставкой , я вот тут сделал но у меня выдает ошибку в 33...

Вызов функции WinAPI в ассемблерной вставке
Доброго времени суток! Необходимо получить значение времени вызовом функции WinAPI в ассемблерной вставке. Программа компилируется, но...

Ошибка в вычислениях, вызов ассемблерной функции из С кода
Есть несложное выражение. X = K - B/2 + D + E*4; K - константа, D - трехбайтное число, В и Е - двухбайтовые. Проблема в том, что...

Разбор кода ассемблерной программы
Добрый день, у меня возникла такая проблема, я при помощи функции strtok() считываю слова из перенной buffer в переменную word. В buffer...

Ошибка программы с ассемблерной вставкой
Коллеги! Есть у меня такой код: uses crt; var max,er:integer; str_,out_s:string; answer:char; procedure...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru