0 / 0 / 0
Регистрация: 05.02.2019
Сообщений: 48
1
FASM

Передача параметров из Си в процедуру в Ассемблере

05.02.2019, 18:41. Показов 10906. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, пожалуйста подскажите... никак не могу разобраться с передачей параметров из Си в Ассемблер

Assembler
1
2
3
4
5
6
;  Функция находит числа в введенной строке и записывает их в результирующую строку
;  INPUT_STR               ссылка на строку, которую необходимо исследовать
;  INPUT_STR_LEN        длина строки, которую необходимо исследовать
;  RESULT_STR             ссылка на строку, в которую будет помещен результат
;  (ссылки передаются под знаменем DWORD, но я передаю под ним еще и длину строки)
proc functionA, INPUT_STR:DWORD, INPUT_STR_LEN:DWORD, RESULT_STR:DWORD
(выше "заголовок внутри кода в Ассемблере"), я хочу получить от Си - указатель на строку, которую буду проверять, ее длину, и указатель на строку, куда я запишу результат...

Вопросов несколько...
Почему ссылку на строку я должен передавать DWORD-ом? (она по стандарту имеет размер 32 бита?)

Почему я не могу передать в AL символ таким образом?
Assembler
1
mov al, [INPUT_STR+edx]     ; N-символ из заданной строки, который будем сравнивать с цифрами
А должен (возможно), именно таким?
Assembler
1
2
mov esi, [INPUT_STR]     ; ссылка на введенную строку
mov al, [esi+edx]                    ; N-символ из заданной строки, который будем сравнивать с цифрами
...и почему я не могу передать символ из AL, в результирующую строку ...так:
Assembler
1
mov [RESULT_STR+ebx], al   ; записываем символ в строку
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.02.2019, 18:41
Ответы с готовыми решениями:

Передача параметров в программу на ассемблере
Всем привет!:) У меня проблема следующая: допустим есть некая программа program1.exe, я вызываю...

Передача параметров в процедуру
В приложении динамически создается объект(не суть важно какой) для обработки события OnClick...

Передача параметров в процедуру
Есть класс формы, я прописал процедуру для редактирования формы, но передать в нее "список" не...

Передача параметров в процедуру
Доброго времени суток. Нужна ваша помощь, знатоки! Возникла нужда в изучении процедур и передачи в...

8
Эксперт CЭксперт С++
5113 / 4552 / 854
Регистрация: 07.10.2015
Сообщений: 9,462
05.02.2019, 19:03 2
Лучший ответ Сообщение было отмечено AgonMountain как решение

Решение

AgonMountain, начнем по-порядку:
1) Ссылки на строку должны быть DWORD-ом, потому что адрес 32-битный.
2) Что такое INPUT_STR? Это адрес параметра в стеке (типа [EBP+8]), DWORD, где лежит адрес строки.
Поэтому нельзя к адресу адреса добавить смещение, чтобы получить байт строки.
Правильно, действительно, сначала необходимо получить адрес строки в регистр.
Аналогично с записью байта в результирующую строку...
1
0 / 0 / 0
Регистрация: 05.02.2019
Сообщений: 48
05.02.2019, 20:03  [ТС] 3
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
include 'include\win32a.inc'
 
format MS COFF
public functionA as '_functionA@12'
 
section '.data' data readable writeable      ; секция данных
 
NUMBER_STR db "0123456789"
LEN_NUMBER_STR dd 10
 
section '.code' code readable executable
 
;  Функция находит числа в строке и записывает их в указанную строку
;  INPUT_STR            ссылка на строку, которую необходимо исследовать
;  INPUT_STR_LEN        длина строки, которую необходимо исследовать
;  RESULT_STR           ссылка на строку, в которую будет помещен результат
;  (ссылки передаются под знаменем DWORD, но я передаю под ним еще и длину строку)
proc functionA, INPUT_STR:DWORD, INPUT_STR_LEN:DWORD, RESULT_STR:DWORD
 
        pushad
 
start:                              ; точка входа в программу
        xor ebx, ebx                ; длина результирующей строки
        xor edx, edx                ; сдвиг внутри заданной строки
compare:
        ;========================= Условие выхода ========================
        cmp edx, [INPUT_STR_LEN]    ; прошли всю заданную строку символов
        ja exit                     ; на выход
 
        ;========================= Основной блок ==========================
        mov edi, NUMBER_STR         ; строка с цифрами на которую будем опираться при сравнении
        mov ecx, [LEN_NUMBER_STR]   ; сколько символов в строке с цифрами (чтобы перебрать все цифры)
 
        mov esi, [INPUT_STR]
        mov al, [esi+edx]     ; N-символ из заданной строки, который будем сравнивать с цифрами
 
        cld                         ; направление движения вдоль строки (от левого к правому)
        repne scasb                 ; сравнение
        jnz input_cymbol            ; рассматриваемый символ не является цифрой
 
input_digit:
        ;============= Запись найденного числа в итоговую строку ==============
        mov esi, [RESULT_STR]
        mov [esi+ebx], al           ; записываем символ в строку
        inc ebx                     ; увеличиваем длину результирующей строки
        jmp after_input
 
input_cymbol:
        ;================== Запись пробела в итоговую строку ==================
        cmp ebx, 0                  ; пробел в начале - нельзя
        je after_input              ; -> выход
 
        mov esi, [RESULT_STR]
        cmp byte [esi+ebx-1], ' '        ; несколько пробелов подряд - нельзя
        je after_input              ; -> выход
 
        mov esi, [RESULT_STR]
        mov byte [esi+ebx], ' '   ; записываем пробел в результирующую строку
        inc ebx                     ; увеличиваем длину результирующей строки
 
after_input:
        inc edx                     ; перейти к следующему элементу заданной строки
        jmp compare                 ; продолжаем проверять оставшиеся символы заданной строки
 
exit:
        ;========================= Результат работы  =========================
        mov esi, [RESULT_STR]
        mov byte [esi+ebx-1], ''    ; костыль (чтобы не было на конце лишнего пробела)
        dec ebx                     ; уменьшаем длину результирующей строки
 
        popad
 
        ret 12
endp

...подскажите, в чем может быть ошибка? (она тут вроде как есть...своими глупыми глазищами не вижу o_o)


пытаюсь связать с:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "stdafx.h"
#include <conio.h>
 
extern "C" 
{
    unsigned int __stdcall functionA(char*, int, char*);
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    char str[250] = "123456789";
    int str_len = 9;
    char result_str[250];
 
    functionA(str, str_len, result_str);
 
    _getch();
    return 0;
}
кидает ошибку:

Необработанное исключение в "0x0137fa24" в "laba5.exe": 0xC0000005: Access violation.
Внутри VS, srtexe.c

...и правильно ли я обозвал тип byte 3 случаях? вроде как рассматривается один символ...и ему не нужно больше...(а без указания типа, FASM говорит, что он не гадалка и не может напророчить тип, с которым мы будем работать ._.)
0
Эксперт Hardware
Эксперт Hardware
6101 / 2345 / 390
Регистрация: 29.07.2014
Сообщений: 3,107
Записей в блоге: 4
05.02.2019, 22:06 4
AgonMountain, в исходнике фасма,
если операнды не одинаковы, то нужно указывать их явно, то-есть byte, word
Assembler
1
2
3
4
5
6
7
compare:
;....
        mov  al, byte[esi+edx]
;....
input_digit:
        mov  byte[esi+ebx], al      ; записываем символ в строку
;....
1
0 / 0 / 0
Регистрация: 05.02.2019
Сообщений: 48
06.02.2019, 15:37  [ТС] 5
... проблема не ушла... исправил код на...:

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
include 'include\win32a.inc'
 
format MS COFF
 
public functionA as '_functionA@20'
 
;  Функция находит числа в строке и записывает их в указанную строку
;  INPUT_STR            ссылка на строку, которую необходимо исследовать
;  INPUT_STR_LEN        длина строки, которую необходимо исследовать
;  NUMBER_STR           ссылка на строку с цифрами (0123456789)
;  LEN_NUMBER_STR       длина строки с цифрами (10)
;  RESULT_STR           ссылка на строку, в которую будет помещен результат
proc functionA, INPUT_STR:DWORD, INPUT_STR_LEN:DWORD, NUMBER_STR:DWORD, LEN_NUMBER_STR:DWORD, RESULT_STR:DWORD
 
        pushad                      ; сохраняем все регистры перед выполнением процедуры functionA
 
        xor ebx, ebx                ; длина результирующей строки
        xor edx, edx                ; сдвиг внутри заданной строки
compare:
        ;========================= Условие выхода ========================
        cmp edx, [INPUT_STR_LEN]    ; прошли всю заданную строку символов ->
        je exit                     ; -> выход
 
        ;========================= Основной блок ==========================
        mov edi, [NUMBER_STR]       ; ССЫЛКА на строку с цифрами (0123456789)
        mov ecx, [LEN_NUMBER_STR]   ; ЧИСЛО, количество символов в строке с цифрами (10)
 
        mov esi, [INPUT_STR]        ; ССЫЛКА на введенную строку (пользователь)
        mov al, byte[esi+edx]       ; N-символ из введенной строки, который будем сравнивать с цифрами
 
        cld                         ; направление движения вдоль строки (от левого к правому)
        repne scasb                 ; сравнение
        jnz input_cymbol            ; рассматриваемый символ не является цифрой
 
input_digit:
        ;============= Запись найденного числа в итоговую строку ==============
        mov esi, [RESULT_STR]
        mov byte[esi+ebx], al       ; записываем символ в строку
        inc ebx                     ; увеличиваем длину результирующей строки
        jmp after_input
 
input_cymbol:
        ;================== Запись пробела в итоговую строку ==================
        cmp ebx, 0                  ; пробел в начале - нельзя
        je after_input              ; -> выход
 
        mov esi, [RESULT_STR]
        cmp byte [esi+ebx-1], ' '   ; несколько пробелов подряд - нельзя
        je after_input              ; -> выход
 
        mov esi, [RESULT_STR]
        mov byte [esi+ebx], ' '     ; записываем пробел в результирующую строку
        inc ebx                     ; увеличиваем длину результирующей строки
 
after_input:
        inc edx                     ; перейти к следующему элементу заданной строки
        jmp compare                 ; продолжаем проверять оставшиеся символы заданной строки
 
exit:
        popad                       ; возвращаем все регистры после выполнения процедуры functionA
        ret 20
endp
Вызов из Си:

C
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
#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <stdio.h>
 
using namespace std;
 
extern "C" 
{
    void __stdcall functionA(char*, int, char*, int, char*);
}
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    char str[250] = "123456789";
    int str_len = 9;
    char str_num[250] = "0123456789";
    int str_num_len = 10;
    
    char result_str[250] = {"............."};
 
    functionA(str, str_len, str_num, str_num_len, result_str);
 
    _getch();
    return 0;
}
Все так же кидает ошибку в VS(2010):

Необработанное исключение в "0x0135f814" в "laba5.exe": 0xC0000005: Access violation. (внутри crtexe.c)

...прошелся по шагам по дисассемблированному коду и проверяя регистры внутри своей functionA в VS, вроде все нормально, даже работает наверное как надо, завершается, а потом переходит на другие строки и ломается

проблема во мне?
0
Эксперт CЭксперт С++
5113 / 4552 / 854
Регистрация: 07.10.2015
Сообщений: 9,462
06.02.2019, 17:05 6
Лучший ответ Сообщение было отмечено AgonMountain как решение

Решение

AgonMountain, неправильно работал стек. Сделайте вход/выход так:
Assembler
1
2
3
4
proc functionA  uses ebx esi edi, INPUT_STR:DWORD, INPUT_STR_LEN:DWORD, NUMBER_STR:DWORD, LEN_NUMBER_STR:DWORD, RESULT_STR:DWORD
 
    xor ebx, ebx            ; длина результирующей строки
    xor edx, edx            ; сдвиг внутри заданной строки
Assembler
1
2
3
exit:
    ret
endp
Кроме того, все регистры нет нужды сохранять. Вполне достаточно только указанные.
0
0 / 0 / 0
Регистрация: 05.02.2019
Сообщений: 48
06.02.2019, 17:13  [ТС] 7
....
а как определять, какие регистры нужно сохранять? те которые точно используются системой? или??

и почему ret без циферок? я думал что он очищает загруженные параметры (в моем случае пять штук, каждый по 4 байта = 20 байт) из стека и для stdcall (без макросов (не знаю)) её НУЖНО указывать... или та конструкция, которую Вы указали выше, заранее создает план действий после завершения процедуры (очистка стека от параметров)*?
0
Эксперт CЭксперт С++
5113 / 4552 / 854
Регистрация: 07.10.2015
Сообщений: 9,462
06.02.2019, 17:21 8
Лучший ответ Сообщение было отмечено AgonMountain как решение

Решение

AgonMountain, именно эти регистры и используются.
Макро proc и endp знают, сколько надо выкинуть из стека. Посмотрите в отладчике ассемблерный код.
1
Модератор
Эксперт по электронике
8475 / 4334 / 1642
Регистрация: 01.02.2015
Сообщений: 13,455
Записей в блоге: 8
06.02.2019, 18:31 9
Цитата Сообщение от AgonMountain Посмотреть сообщение
а как определять, какие регистры нужно сохранять?
Это зависит от компилятора, а кроме того, для кроссплатформенных компиляторов, ещё и от целевой ОС.
Нужно поискать что-то вроде "соглашение о передаче параметров и сохранении регистров для VisualStudio"
https://docs.microsoft.com/ru-... ew=vs-2017

Для 32-разрядных приложений C/C++ Visual Studio быстро не нашёл.

Помню, что как-то находил подобные соглашения для Delphi и FreePascal.
1
06.02.2019, 18:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.02.2019, 18:31
Помогаю со студенческими работами здесь

Передача параметров в процедуру
Пока не нашел функцию ltoa, пытался добавить подсчет количества записанных байтов. Добавил параметр...

Передача параметров в процедуру
Здравствуйте! У меня есть процедура которая строит график по заданном диапазону Sub...

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

Передача параметров в хранимую процедуру
Подскажите вот в sql у меня есть параметры @Author И мне нужно Передавать эти параметра при...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru