Форум программистов, компьютерный форум, киберфорум
Наши страницы
Assembler для начинающих
Войти
Регистрация
Восстановить пароль
 
somwan
2 / 2 / 1
Регистрация: 15.04.2014
Сообщений: 8
#1

Не работает ассемблерная вставка - Assembler

15.04.2014, 12:29. Просмотров 839. Ответов 9
Метки нет (Все метки)

Здравствуйте!

Прблема следующего характера. Пишу проект на С++ в среде BORLAND C++ 3.1, с ассемблером совсем не знаком (знаю что это такое, но не более того). Ранее взял пример из книги А.Фролова "библиотека системного программиста", позволяющий работать с протоколом IPX. Пример включает следующую ассемблерную вставку, добавляемую в проект С++ как отдельный модуль:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
; ===================================================
; Листинг 2. Инициализация и вызов драйвера IPX/SPX
; Файл ipxdrv.asm
;
; (C) A. Frolov, 1993
; ===================================================
 
.286
.MODEL SMALL
; ---------------------------------------
; Структура для вызова драйвера IPX/SPX
; ---------------------------------------
 
        IPXSPX_REGS struc
                rax     dw ?
                rbx     dw      ?
                rcx     dw      ?
                rdx     dw      ?
                rsi     dw      ?
                rdi     dw      ?
                res     dw      ?
        IPXSPX_REGS ends
 
.DATA
 
; Точка входа в драйвер IPX/SPX
 
_ipxspx_drv_entry       dd ?
 
.CODE
 
        PUBLIC  _ipxspx_entry, _ipx_init
        PUBLIC  _ipxspx_drv_entry
 
; ---------------------------------------
; Процедура, вызывающая драйвер IPX/SPX
; ---------------------------------------
 
_ipxspx_entry PROC FAR
 
; Готовим BP для адресации параметра функции
 
                push    bp
                mov      bp,sp
 
; Сохраняем регистры, так как драйвер IPX/SPX
; изменяет содержимое практически всех регистров
 
                push    es
                push    di
                push    si
                push    dx
                push    cx
                push    bx
                push    ax
 
; Загружаем регистры из структуры,
; адрес которой передается как параметр
 
                push    ds
                mov     bx, [bp+6]   ; смещение
                mov     ds, [bp+8]   ; сегмент
                mov     es, ds:[bx].res
                mov     di, ds:[bx].rdi
                mov     si, ds:[bx].rsi
                mov     dx, ds:[bx].rdx
                mov     cx, ds:[bx].rcx
                mov     ax, ds:[bx].rax
                mov     bx, ds:[bx].rbx
                pop     ds
 
; Вызываем драйвер IPX/SPX
 
                call    [dword ptr _ipxspx_drv_entry]
 
; Сохраняем регистры
 
                push    ds
                push    dx
                mov     dx, bx
 
; Записываем в структуру содержимое регистров после вызова драйвера
 
                mov     bx, [bp+6]       ; смещение
                mov     ds, [bp+8]   ; сегмент
                mov     ds:[bx].rax, ax
                mov     ds:[bx].rcx, cx
                mov     ds:[bx].rbx, dx
                pop     dx
                mov     ds:[bx].rdx, dx
                pop     ds
 
; Восстанавливаем регистры
 
                pop     ax
                pop     bx
                pop     cx
                pop     dx
                pop     si
                pop     di
                pop     es
 
                pop     bp
                retf
_ipxspx_entry ENDP
 
; ---------------------------------------------
; Процедура инициализации драйвера IPX/SPX
; ---------------------------------------------
 
_ipx_init PROC NEAR
                push    bp
                mov      bp,sp
 
; Определяем наличие драйвера в системе и его точку входа
 
                mov     ax, 7a00h
                int     2fh
 
; Если драйвера нет, завершаем процедуру
 
                cmp     al, 0ffh
                jne     _ipx_init_exit
 
; Сохраняем адрес точки входа
 
                mov     word ptr _ipxspx_drv_entry+2, es
                mov     word ptr _ipxspx_drv_entry, di
 
_ipx_init_exit:
 
; В регистре AX - код завершения процедуры
 
                mov     ah, 0
                pop     bp
                ret
_ipx_init ENDP
end
Изначально всё работало хорошо, но при этом модель памяти основного проекта была COMPACT. Код ассемблера никак не изменялся мной, и при этом работал. Однако современем проект разросся, и потребовалось перевести его на модель HUGE. При этом возникла проблема с показанным кодом. Он отказывается работать. В процедуре ipx_init доходит до команды ret и зависает. Подозреваю что возникли проблемы с адресацией из - за смены модели с COMPACT на HUGE, вероятнее всего нужно подправить показанный код ассемблера, но как это сделать я не знаю, в этом и прошу помощи.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.04.2014, 12:29
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Не работает ассемблерная вставка (Assembler):

Ассемблерная вставка работает неправильно
Имеется такой код: #include <conio.h> // Для работы с функцией _getch()...

Не работает ассемблерная вставка Masm32 в C++
Добрый вечер мы в институте учим ассемблерные вставки. Я пользуюсь Visual...

Ассемблерная вставка, С++
Доброе утро. Достался "по наследству" код __declspec(dllexport) int...

Факториал (ассемблерная вставка в C++)
int c=1; _asm {mov ecx,4 lb1: mul c,ecx

Факториал (ассемблерная вставка в C++)
#include "stdafx.h" #include <iostream> using namespace std; int...

Ассемблерная вставка. Деление со знаком
На консоль выводит непонятно что - 8.40779e-045 float res; _asm{ mov...

9
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
15.04.2014, 19:24 #2
неТварь NetWare Client от Novell или от глюкософта?

Добавлено через 6 минут
Цитата Сообщение от somwan Посмотреть сообщение
_ipx_init PROC NEAR
Цитата Сообщение от somwan Посмотреть сообщение
ret
_ipx_init ENDP
Может всё-таки _ipx_init PROC FAR и retf?
0
somwan
2 / 2 / 1
Регистрация: 15.04.2014
Сообщений: 8
15.04.2014, 19:34  [ТС] #3
Microsoft Net Client 3.0

Самое интересное, что с моделью памяти COMPACT, которая выставляется в свойствах проекта BORLAND C++ 3.1, всё работает. А при изменении модели на HUGE виг вам. При этом С++ коду без разницы какая модель (разница имеется для объёма кода но не для его исполнения), а для данной ассемблерной вставки очевидно, разница имеет смысл. Где именно она имеет смысл немиогу понять.

Добавлено через 5 минут
"Может всё-таки _ipx_init PROC FAR и retf?" >> это я уже пробовал. Описанная проблема решается, но возникает другая. В процедуре ipxspx_entry есть строка coll [dword ptr _ipxspx_drv_entery] как я понимаю это вызов драйвера IPX по точке входа полученный процедурой ipx_init. При описанном изменении в данной строке всё зависает, т.к. вероятнее веего неверная точка входа. Сам я в ассемблере нуль, применяю аналогию с С++, поэтому и прошу помощи.
0
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
15.04.2014, 19:42 #4
А так пробовали? Попробуйте сравнить, что получает _ipx_init для _ipxspx_drv_entry(сегмент/оффсет)
call [far ptr _ipxspx_drv_entry]
Цитата Сообщение от somwan Посмотреть сообщение
Microsoft Net Client 3.0
Пичалька. Под это поделие наработок нет, только под NIOS, если найду архив.
0
somwan
2 / 2 / 1
Регистрация: 15.04.2014
Сообщений: 8
15.04.2014, 19:52  [ТС] #5
call [far ptr _ipxspx_drv_entry]
только что попробовал как вы сказали, результат тот же, зависание на данной строке. А разьве имеет значение от кого IPX используется ? имеется ввиду MICROS или NOVEL ? Я думал что разницы нет ведь IPX - этож стандарт такой.
0
AFP
649 / 336 / 37
Регистрация: 04.04.2012
Сообщений: 887
15.04.2014, 21:10 #6
IPX еще используется?
Под ДОС лет 5-7 забросил. Нравилось с использованием запросов к драйверу.
Былаь малая пропускная способность (561 байт) на пакет по-моему.
Хотел приспособить с помощью SoftIce к передаче больших объемов данных, но не судьба, и немного обидно – много потрачено ч/часов.
0
Charles Kludge
Клюг
7641 / 3156 / 382
Регистрация: 03.05.2011
Сообщений: 8,382
15.04.2014, 21:49 #7
Вы перед этой строчкой
Цитата Сообщение от somwan Посмотреть сообщение
mov word ptr _ipxspx_drv_entry+2, es
поставьте int 3 , запустите под турбодебагером и посмотрите, что туда пишется в рабочем и нерабочем варианте.
Цитата Сообщение от somwan Посмотреть сообщение
Я думал что разницы нет ведь IPX - этож стандарт такой.
Я тоже так думал, пока не стал писать реквестеры. Btrieve RMS requester под МС-клиентом не работает в принципе.
IPX - пропиетарный протокол Xerox/Novell, который стал стандартом де-факто для LAN, и делиться всеми тонкостями с мелкософтом фирма Novell не собиралась, отсюда получилось МС-глюкало.
И попробуйте так, похоже у вас загаживается bp после вызова:
Assembler
1
2
3
4
5
; Вызываем драйвер IPX/SPX
                push bp 
                call    [dword ptr _ipxspx_drv_entry]
                pop bp
; Сохраняем регистры
Добавлено через 6 минут
Цитата Сообщение от AFP Посмотреть сообщение
IPX еще используется?
А почему нет? на 100мбит очень даже шустро бегает. И самое главное - под ИПХу нет вирусов.
0
AFP
649 / 336 / 37
Регистрация: 04.04.2012
Сообщений: 887
15.04.2014, 22:24 #8
Иль я сильно пьян сегодня, но не смог найти в меню - ответить для Charles Kludge.
Для клонирования винта/системы, основная задача в то время, 512 байт (1 сектор) данных в пакете было мало.
А куда вирус может залезть, если все под контролем?
0
somwan
2 / 2 / 1
Регистрация: 15.04.2014
Сообщений: 8
15.04.2014, 22:53  [ТС] #9
Charles Kludge благодарствую за помощь, вашем советом воспользуюсь и попробую обязательно, но только завтра, сегодня уже спят все, Ещё раз спасибо.
0
somwan
2 / 2 / 1
Регистрация: 15.04.2014
Сообщений: 8
17.04.2014, 19:29  [ТС] #10
Лучший ответ Сообщение было отмечено Taatshi как решение

Решение

Как я и подозревал дело было в полторах закорючках!
Нашол книгу "исскуство программирования на ассемблере" в которой нашёл тему о использовании ассемблера совместно с С++. Показанный в первом сообщении код модифицировал следующим образом:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
; =================================================== 
; Листинг 2. Инициализация и вызов драйвера IPX/SPX 
; Файл ipxdrv.asm 
; 
; (C) A. Frolov, 1993 
; =================================================== 
 
.286 
.MODEL HUGE, C
; --------------------------------------- 
; Структура для вызова драйвера IPX/SPX 
; --------------------------------------- 
 
        IPXSPX_REGS struc 
                rax     dw ? 
                rbx     dw      ? 
                rcx     dw      ? 
                rdx     dw      ? 
                rsi     dw      ? 
                rdi     dw      ? 
                res     dw      ? 
        IPXSPX_REGS ends 
 
.DATA 
 
; Точкавходавдрайвер IPX/SPX 
 
 
.CODE 
 
               EXTRN C  ipxspx_drv_entry 
; --------------------------------------- 
; Процедура, вызывающая драйвер IPX/SPX 
; --------------------------------------- 
                    PUBLIC  C  ipxspx_entry
 ipxspx_entry PROC C FAR 
 
; Готовим BP для адресации параметра функции 
 
               push     bp
               mov      bp,sp
 
; Сохраняем регистры, так как драйвер IPX/SPX 
; изменяет содержимое практически всех регистров 
 
                push    es
                push    di 
                push    si 
                push    dx 
                push    cx 
                push    bx 
                push    ax 
 
; Загружаем регистры из структуры, 
; адрес которой передается как параметр 
 
                push    ds 
                mov     bx, [bp+6]   ; смещение
                mov     ds, [bp+8]   ; сегмент
                mov     es, ds:[bx].res 
                mov     di, ds:[bx].rdi 
                mov     si, ds:[bx].rsi 
                mov     dx, ds:[bx].rdx 
                mov     cx, ds:[bx].rcx 
                mov     ax, ds:[bx].rax 
                mov     bx, ds:[bx].rbx 
                pop      ds
 
; Вызываем драйвер IPX/SPX 
 
               call    [dword ptr ipxspx_drv_entry] 
 
; Сохраняем регистры 
 
               push    ds
               push    dx
               mov     dx, bx
 
; Записываем в структуру содержимое регистров после вызова драйвера 
 
                mov     bx, [bp+6]       ; смещение 
                mov     ds, [bp+8]   ; сегмент 
                mov     ds:[bx].rax, ax 
                mov     ds:[bx].rcx, cx 
                mov     ds:[bx].rbx, dx 
                pop     dx 
                mov     ds:[bx].rdx, dx 
                pop     ds 
 
; Восстанавливаем регистры 
 
                pop     ax
                pop     bx
                pop     cx 
                pop     dx 
                pop     si 
                pop     di 
                pop     es 
 
                pop     bp 
                retf 
 ipxspx_entry ENDP 
 
; --------------------------------------------- 
; Процедураинициализациидрайвера IPX/SPX 
; --------------------------------------------- 
               PUBLIC  C ipx_init 
 ipx_init PROC C FAR 
                push  bp
                mov   bp,sp
 
; Определяем наличие драйвера в системе и его точку входа 
 
                mov   ax, 7a00h 
                int     2fh 
 
; Если драйвера нет, завершаем процедуру 
 
                cmp     al, 0ffh 
                jne     _ipx_init_exit 
 
; Сохраняемадресточкивхода
 
                mov     word ptr ipxspx_drv_entry+2, es 
                mov     word ptr ipxspx_drv_entry, di 
 
_ipx_init_exit: 
 
; В регистре AX - код завершения процедуры 
 
               mov     ah, 0 
                pop     bp 
                retf 
 ipx_init ENDP 
end
вобщем перед процедурами вызывамыми из кода С нужно было убрать подчёркивание и добавить символ С, что скажет компилятору о том, как именно интерпритировать код. Так же изменил модель самого кода на HUGE (чтобы была такая же как модеть в коде С), и добавил символ С для тех же целей. А кроме того объявил переменную ipxspx_drv_entry как long int в основном модуле сишного кода, а в ассемблерной вставке объявил её как внешнюю EXTRN C ipxspx_drv_entry. После этого всё заработало. Интересно то, что я так и непонял как в исходном варианте значение переменной ipxspx_drv_entry передавалось из одной процедуры (ipx_init где оно заполнялось) в другую (ipxspx_entry где использовалось для вызова IPX драйвера). Ну да ладно, главное что всё заработало, и даже в HUGO. Проблема решена, всем спасибо.
2
17.04.2014, 19:29
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.04.2014, 19:29
Привет! Вот еще темы с решениями:

Ассемблерная вставка, реализующая вычитание
вообщем вот #include <stdio.h> // необходим для работы printf #include...

Транспонирование матрицы (Ассемблерная вставка)
На Си создать с помощью датчика случайных чисел(random) файл F1 с...

Вычислить выражение (ассемблерная вставка)
Не могу понять как исправить ошибки. Программа работает неправильно при...

Ассемблерная вставка из 10 строк в код с++
Доброго времени суток, уважаемые товарищи! В проекте на с++, который передали...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru