Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.04.2018, 22:43   #1
Alexis_777
Пользователь
 
Регистрация: 08.11.2017
Сообщений: 48
По умолчанию Использование процедур

Мб кто сталкивался с такой проблемой.
Нужно передать мат. выражения с помощью процедур.
Написал модуль на Си вроде бы правильно, скомпилировал gcc -c main.c.
Написал модуль на ассемблере собрал командой nasm -f elf32 asm.asm -o asm.obj.
Cкомпоновал модуль на Си и асм командой gcc -o start main.o asm.obj -lm.
Считает нормально значения х и у: х=-2.52, у=9.65, но ху неправильно: ху=-2 только не пойму. Где-то ошибка в стеке видимо, пробовал исправить, но значения то больше, то меньше бывали и всегда разные выдает при запуске. Должна быть сумма х и у.
Мб кто нибудь сможет найти где ошибка.
Код main.c:
Цитата:
#include <stdio.h>
#include <math.h>

extern __attribute__((cdecl)) int x(int _a, int _b, int _c)
{
return (sin(_a-_b)*_c);
}

extern __attribute__((stdcall)) int y(int _a, int _b, int _c, int _d)
{
return ((_a+_b)*_c-cos(_d));
}

extern __attribute__((fastcall)) int xy(int _a, int _b, int _c, int _d);

void main()
{
int a=1;
int b=2;
int c=3;
int d=4;
printf("x:%d\ny:%d\nxy:%d\n",x(a,b, c),y(a,b,c,d),xy(a,b,c,d));
}
Код asm.asm:
Цитата:
global xy
extern x
extern y

section .text

xy:

;fastcall
push ebp
mov ebp, esp

;cdecl
push ecx
push edx

mov eax, [ebp+8] ;c
push eax
push edx ;b
push ecx ;a
call x
sub esp, 12
pop edx
pop ecx
push eax ;значение x(a,b,c)

;stdcall
push ecx ;a
push edx ;b
mov eax, [ebp+8] ;c
push eax
mov eax, [ebp+12] ;d
push eax
call y

pop ebx
;в этом месте eax=y, ebx=x
add eax, ebx

mov esp, ebp
pop ebp

ret

Последний раз редактировалось Alexis_777; 06.04.2018 в 00:40.
Alexis_777 вне форума Ответить с цитированием
Старый 11.04.2018, 20:31   #2
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

Вместо sub esp, 12 нужно написать add esp,12 (стек растёт вниз).
Сделайте это, а там посмотрим
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru
7in вне форума Ответить с цитированием
Старый 11.04.2018, 20:35   #3
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

Кстати, вы в курсе, что в соглашении fastcall (GNU) параметры передаются через ecx и edx, а дальше через стек?
http://agner.org/optimize/calling_conventions.pdf (глава 7)

upd: Да, вижу, что знаете, зато не знаете, что в stdcall параметры передаются в обратном порядке, как в cdecl. Разница только в том, что у stdcall параметры из стека вынимает вызываемая функция, а не вызывающая.
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru

Последний раз редактировалось 7in; 11.04.2018 в 20:55.
7in вне форума Ответить с цитированием
Старый 17.04.2018, 11:32   #4
Alexis_777
Пользователь
 
Регистрация: 08.11.2017
Сообщений: 48
По умолчанию

Цитата:
Сообщение от 7in Посмотреть сообщение
Кстати, вы в курсе, что в соглашении fastcall (GNU) параметры передаются через ecx и edx, а дальше через стек?
http://agner.org/optimize/calling_conventions.pdf (глава 7)

upd: Да, вижу, что знаете, зато не знаете, что в stdcall параметры передаются в обратном порядке, как в cdecl. Разница только в том, что у stdcall параметры из стека вынимает вызываемая функция, а не вызывающая.
Т.к. значения с плавающей точкой функцией add сложить не получиться.
Написал что-то похожее на правду, но результат пока что не совсем правильный, какое то значение теряется. Что это может быть?
Код:
global xy
extern x
extern y
 
section .text
 
    xy:
        ;fastcall
        push ebp
        mov ebp, esp
        ;cdecl
        push ecx
        push edx
        mov eax, [ebp+8]    ;c
        push eax
        push edx
        push ecx
        call x
        pop edx         ;b
        pop ecx         ;a
        push eax
        fstp st1
        ;stdcall
        push ecx
        push edx
        mov eax, [ebp+8]    ;c
        push eax
        mov eax, [ebp+12]   ;d
        push eax
        call y
        fadd st1, st0
        mov esp, ebp
        pop ebp
    ret
Код на Си:
Код:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
 
__attribute__((cdecl)) double x(int _a, int _b, int _c)
{
    return (sin(_a-_b)*_c);
}
 
__attribute__((stdcall)) double y(int _a, int _b, int _c, int _d)
{
    return ((_a+_b)*_c-cos(_d));
}
 
__attribute__((fastcall)) double xy(int _a, int _b, int _c, int _d);
 
void main(int argc, char **argv)
{
    int a, b, c, d;
    if (argc != 5)
    {
        printf("Ошибка, количество аргументов %d. Нужно ввести 4 агрумента", argc-1);
        exit(1);
    }
    a = 1;//atoi(argv[1]);
    b = 2;//atoi(argv[2]);
    c = 3;//atoi(argv[3]);
    d = 4;//atoi(argv[4]);
    printf("Параметры функций a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);
    printf("Результат функции x = sin(a-b)*c = %f\n", x(a,b,c));
    printf("Результат функции y = (a+b)*c-cos(d) = %f\n", y(a,b,c,d));
    printf("Результат функций xy = x+y = %f\n", xy(a,b,c,d));
}

Последний раз редактировалось Alexis_777; 17.04.2018 в 11:41.
Alexis_777 вне форума Ответить с цитированием
Старый 17.04.2018, 13:41   #5
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

Alexis_777, вы читали, что я написал?
1. Параметры в stdcall заносятся в обратном порядке
2. У вас x – cdecl, значит параметры нужно убрать после вызова вручную (add esp,12), зачем это убрали?

И зачем делаете fstp st1 ?
Ну и ret 8 всё-таки, а не просто ret – в fastcall параметры удаляет вызываемая процедура.
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru

Последний раз редактировалось 7in; 17.04.2018 в 14:22.
7in вне форума Ответить с цитированием
Старый 17.04.2018, 14:18   #6
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

А вообще, всё проще можно сделать:
Код:
    xy: ; fastcall
	; готовим параметры сразу и для cdecl, и для stdcall
	push dword [esp+8]  ; d
	push dword [esp+8]  ; c (т.к. после предыдущего push'а указатель стека сдвинулся)
	push edx  ; b
	push ecx  ; a
	call x  ; cdecl
	; все параметры остались в стеке
	call y  ; stdcall
	faddp
	ret 8
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru
7in вне форума Ответить с цитированием
Старый 17.04.2018, 14:19   #7
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

Как вариант (если не понятно, почему и там, и там [esp+8]):
Код:
    xy: ; fastcall
	; готовим параметры сразу и для cdecl, и для stdcall
	mov eax,[esp+4]  ; c
	push dword [esp+8]  ; d
	push eax
	push edx  ; b
	push ecx  ; a
	call x  ; cdecl
	; все параметры остались в стеке
	call y  ; stdcall
	faddp
	ret 8
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru
7in вне форума Ответить с цитированием
Старый 17.04.2018, 14:20   #8
7in
(aka Jin X) !RTFM!
Форумчанин
 
Аватар для 7in
 
Регистрация: 14.12.2014
Сообщений: 295
По умолчанию

Ну или если надо прямо-таки с фреймом (но смысл?):
Код:
    xy: ; fastcall
	push ebp
	mov ebp,esp
	; готовим параметры сразу и для cdecl, и для stdcall
	push dword [ebp+12]  ; d
	push dword [ebp+8]  ; c
	push edx  ; b
	push ecx  ; a
	call x  ; cdecl
	; все параметры остались в стеке
	call y  ; stdcall
	faddp
	pop ebp
	ret 8
Делаю лабы на Asm/Delphi/C++/Python/VBA(Excel): asmlabs.ru
7in вне форума Ответить с цитированием
Старый 17.04.2018, 14:47   #9
Alexis_777
Пользователь
 
Регистрация: 08.11.2017
Сообщений: 48
По умолчанию

Цитата:
Сообщение от 7in Посмотреть сообщение
Ну или если надо прямо-таки с фреймом (но смысл?):
Код:
    xy: ; fastcall
	push ebp
	mov ebp,esp
	; готовим параметры сразу и для cdecl, и для stdcall
	push dword [ebp+12]  ; d
	push dword [ebp+8]  ; c
	push edx  ; b
	push ecx  ; a
	call x  ; cdecl
	; все параметры остались в стеке
	call y  ; stdcall
	faddp
	pop ebp
	ret 8
Да, действительно всё можно намного проще сделать. Спасибо за пример)) Совсем запутался в том, что писал, слишком много инфы сразу пока делал))

Последний раз редактировалось Alexis_777; 17.04.2018 в 14:52.
Alexis_777 вне форума Ответить с цитированием
Старый 17.04.2018, 14:51   #10
Alexis_777
Пользователь
 
Регистрация: 08.11.2017
Сообщений: 48
По умолчанию

del

Последний раз редактировалось Alexis_777; 17.04.2018 в 14:51. Причина: del
Alexis_777 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Использование процедур в С++ Tagimasad Общие вопросы C/C++ 1 12.12.2012 20:01
ИСПОЛЬЗОВАНИЕ ПРОЦЕДУР в C++ baximaxik Помощь студентам 7 17.11.2012 14:51
Использование процедур WTF??? Паскаль, Turbo Pascal, PascalABC.NET 0 21.12.2011 14:24
Использование процедур cyt Паскаль, Turbo Pascal, PascalABC.NET 1 09.10.2010 13:15
использование процедур street-walker Общие вопросы Delphi 4 14.09.2010 21:38