Форум программистов, компьютерный форум CyberForum.ru

__asm вставки (процессор Pentium) - C++

Восстановить пароль Регистрация
 
_Ivana
2189 / 1394 / 124
Регистрация: 01.03.2013
Сообщений: 4,151
Записей в блоге: 2
18.03.2013, 00:45     __asm вставки (процессор Pentium) #1
Пишу в вижуал Студии, делаю ассемблерные вставки, хочу вызывать си-процедуру, в которой тоже ассемблер - просто поменять значение одного регистра, не хочу никаких стеков, ОЗУ и прочего. При выходе похоже не восстанавливается из стека адрес возврата и программа вылетает. Подскажите, где ошибка? (Лишние куски кода убрал для краткости)
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
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
unsigned char expand_CL(void)
{
    //unsigned char y;
    __asm{
        //MOV CL, x
        AND CL, BIN8(00000111)
        CMP CL, 3
        JB M1
        INC CL
M1:     CMP CL, 7
        JB M2
        INC CL
M2:     RET //MOV y, CL
    }
    return 0;
}
unsigned int _8_to_10(unsigned char x)
{
 
    __asm {
    MOV EAX, 0
    MOV AL, x
    CMP AL, BIN8(11110000)
    JB N1
        //y = (x&BIN8(00001100))<<6 | BIN8(10101010);
        AND AL, BIN8(00001100) 
        SHL EAX, 6
        OR  EAX, BIN8(10101010)
        JMP M_end
 
    //else if (x >= BIN8(11000000)) {
        //y = (x&BIN8(00110000))<<4;
        //c = x&BIN8(00000111);
        //if (c>=3) c++; if (c>=7) c++;
        //if (x&BIN8(00001000)) {y = y | c<<4 | BIN8(00001010);}
        //else {y = y | BIN8(10100000) | c;}
 
N1: CMP AL, BIN8(11000000)
    JB N2
        AND AL, BIN8(00110000) 
        SHL EAX, 4
 
        MOV CL, x
        CALL expand_CL
 
//      AND CL, BIN8(00000111)
//      CMP CL, 3
//      JB M1
//      INC CL
//M1:       CMP CL, 7
//      JB M2
//      INC CL
//M2:       //RET
 
        MOV CH, x
        TEST CH, BIN8(00001000)
        JZ M3
        OR  EAX, BIN8(00001010)
        SHL CL, 4
        OR  AL, CL
        JMP M4
M3:     OR  EAX, BIN8(10100000)
        OR  AL, CL
M4:     JMP M_end
 
N2: //else {
        //y = (x&BIN8(11000000))<<2;
        //c = (x&BIN8(00111000))>>3;
        //if (c>=3) c++; if (c>=7) c++;
  
 
M_end:
    MOV y, EAX
        }
        return y;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.03.2013, 00:45     __asm вставки (процессор Pentium)
Посмотрите здесь:

C++ Ассемблерские вставки.
__asm вставка C++
Метод вставки C++
C++ бинарные вставки
нужно вставить блок на асме, но он не понимает не asm и __asm... C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
18.03.2013, 00:58     __asm вставки (процессор Pentium) #2
Здесь ты его и сломал... не забывай про пролог/эпилог функции в зависимости от конвенции вызова.
Assembler
1
2
3
4
5
6
7
8
9
10
11
    __asm{
        //MOV CL, x
        AND CL, BIN8(00000111)
        CMP CL, 3
        JB M1
        INC CL
M1:     CMP CL, 7
        JB M2
        INC CL
M2:     RET //MOV y, CL
    }
http://msdn.microsoft.com/en-us/libr...(v=vs.80).aspx
_Ivana
2189 / 1394 / 124
Регистрация: 01.03.2013
Сообщений: 4,151
Записей в блоге: 2
18.03.2013, 01:08  [ТС]     __asm вставки (процессор Pentium) #3
Спасибо, насколько я понял, при вызове CALL компилятор автоматически засовывает в стек что-то-там в неизвестном количестве, поэтому RET надо передать параметр - на сколько прыгнуть вглубь стека при возврате? Просто я прочитал, что если в процедуре не использовать определенные регистры, то компилятор и не будет их сохранять, я и старался использовать те,которые не в списке. Или я чего-то недопонимаю...

ЗЫ в чистом asm было проще - никто за тебя ничего не пушил и не попил и не портил адреса возвратов...
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
18.03.2013, 01:15     __asm вставки (процессор Pentium) #4
перед ret нужно стек исправить
Assembler
1
2
3
4
pop         <registers>   ; Restore registers
mov         esp, ebp      ; Restore stack pointer
pop         ebp           ; Restore ebp
ret                       ; Return from function
_Ivana
2189 / 1394 / 124
Регистрация: 01.03.2013
Сообщений: 4,151
Записей в блоге: 2
18.03.2013, 03:09  [ТС]     __asm вставки (процессор Pentium) #5
Скопипастил этот кусок кода в свою функцию - на этапе компиляции выдает кучу ошибок. Придется с этим разбираться... Собственно, основная функция работает, если не вызывать вложенную функцию а писать её содержимое несколько раз в коде. Хотел сделать красиво - вынести наружу, но навскидку не получилось, ни функцией ни макросом. Сама эта подфункция проста до безобразия, никаких входных-выходных параметров, использует и изменяет только один регистр, никаких окружающих контекстов не надо сохранять. Неужели нет красивого решения этого вопроса - написать не макросом а функцией несколько простейших операций с регистром без сохранения контекста в стек?
Все равно спасибо за науку, буду ковыряться дальше.

Добавлено через 40 минут
Нашел листинг - увидел много нового и интересного Не думал, что мои простые операции компилятор будет окружать таким.... вниманием
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void expand_CL(void)
{
004BCDB0  push        ebp  
004BCDB1  mov         ebp,esp 
004BCDB3  sub         esp,0C0h 
004BCDB9  push        ebx  
004BCDBA  push        esi  
004BCDBB  push        edi  
004BCDBC  lea         edi,[ebp-0C0h] 
004BCDC2  mov         ecx,30h 
004BCDC7  mov         eax,0CCCCCCCCh 
004BCDCC  rep stos    dword ptr es:[edi] 
    __asm{
        AND CL, BIN8(00000111)
004BCDCE  and         cl,7 
        CMP CL, 3
004BCDD1  cmp         cl,3 
        JB M1
004BCDD4  jb          M1 (4BCDD8h) 
        INC CL
004BCDD6  inc         cl   
M1:     CMP CL, 7
004BCDD8  cmp         cl,7 
        JB M2
004BCDDB  jb          M2 (4BCDDFh) 
        INC CL
004BCDDD  inc         cl   
M2:             
        //POP         <registers>   //; Restore registers
        //MOV         esp, ebp      //; Restore stack pointer
        //POP         ebp           //; Restore ebp
        //RET                       //; Return from function        
        RET
004BCDDF  ret              
    }
}
004BCDE0  pop         edi  
004BCDE1  pop         esi  
004BCDE2  pop         ebx  
004BCDE3  add         esp,0C0h 
004BCDE9  cmp         ebp,esp 
004BCDEB  call        @ILT+36925(__RTC_CheckEsp) (4B1042h) 
004BCDF0  mov         esp,ebp 
004BCDF2  pop         ebp  
004BCDF3  ret
Добавлено через 51 минуту
Спасибо людям - подсказали про директиву naked - а то бы долго думал почему в мире все так несправедливо
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__declspec( naked ) void expand_CL(void)
{   __asm{
        AND CL, BIN8(00000111)
004BCDB0  and         cl,7 
        CMP CL, 3
004BCDB3  cmp         cl,3 
        JB M1
004BCDB6  jb          M1 (4BCDBAh) 
        INC CL
004BCDB8  inc         cl   
M1:     CMP CL, 7
004BCDBA  cmp         cl,7 
        JB M2
004BCDBD  jb          M2 (4BCDC1h) 
        INC CL
004BCDBF  inc         cl   
M2:     RET
004BCDC1  ret
NEbO
583 / 451 / 49
Регистрация: 22.01.2009
Сообщений: 1,173
Записей в блоге: 1
Завершенные тесты: 1
18.03.2013, 04:00     __asm вставки (процессор Pentium) #6

Не по теме:

Цитата Сообщение от _Ivana Посмотреть сообщение
подсказали про директиву naked
везет вам, вижуал-студиевцам в gcc такой опции нет, и, видимо, не будет под x86. а жаль


по теме, все правильно, компилируйте си код в исходник на ассемблере (не знаю, каким ключом это делать в студии, извините), и увидите, какой там пролог, эпилог, заодно call convensions выучите. можно еще посмотреть, что получается при указании ключей оптимизации. интересно! правда
Цитата Сообщение от ISergey Посмотреть сообщение
pop * * * * <registers> * ; Restore registers
по-простому, можно применять pusha/popa . с другой стороны, вы и только вы знаете, какие регистры использутся внутри вашего ассемблерного кода (компилятор тупо копипастит ваши куски), поэтому можете сохранять только те регистры, которые реально используются.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
18.03.2013, 10:40     __asm вставки (процессор Pentium) #7
Цитата Сообщение от _Ivana Посмотреть сообщение
Спасибо, насколько я понял, при вызове CALL компилятор автоматически засовывает в стек что-то-там в неизвестном количестве
инструкция CALL кладет в стек адрес возврата, т.е. адрес инструкции, следующей за call.

Цитата Сообщение от _Ivana Посмотреть сообщение
поэтому RET надо передать параметр - на сколько прыгнуть вглубь стека при возврате?
RET ничего передавать не надо, она просто выталкивает из стека 4(8) байт, думает что это адрес и передает управление по этому адресу. Поэтому задача программиста позаботиться о том, чтобы RET взяла из стека валидный адрес.
_Ivana
2189 / 1394 / 124
Регистрация: 01.03.2013
Сообщений: 4,151
Записей в блоге: 2
18.03.2013, 13:56  [ТС]     __asm вставки (процессор Pentium) #8
NEbO, я не закоренелый Вижуал Студиевец, я в ней только начал разбираться, например как увидеть ассемблерный листинг компилятора без вызова отладчика пока не понял (но я в отладчике смотрю и не переживаю). А вот то, что в gcc нельзя задавать голые функции - наверное действительно неудобно. Приходится наверное использовать макросы или вырезать прологи/эпилоги прямо из готового ассемблерного кода
Насчет разных ключей оптимизации - тоже хотел попробовать, но компилятор ругается на несовместимость ключей при указании оптимизации, надо с этим тоже разбираться.
А насчет сохранения только нужных мне регистров - об этом и была речь в этом простом примере, теперь я могу сам определять какую часть контекста мне надо спасать - от нуля до полного, или положиться в этом на компилятор. Это очень развязывает руки, появляется ощущение что я сам пишу код (как было на чистом asm), и могу избавиться от помех компилятора при необходимости.


Kastaneda, да, вы правы, просто я позволил себе вольно выразиться - в стек пихается много чего после передачи управления на метку начала функции, а сама передача осуществляется CALL-ом.
В той книжке, которую я читаю, написано что можно передать RET параметр, который изменит указатель стека, по которому брать адрес возврата, без выталкивания из стека всего того, что в него было ранее засунуто. А можно изменить его вручную после вызова функции. Я это ещё не пробовал, но это первое что я сделаю, как приду с работы
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
18.03.2013, 14:07     __asm вставки (процессор Pentium) #9
Цитата Сообщение от _Ivana Посмотреть сообщение
что можно передать RET параметр
Ну да, можно, только в этом случае у RET другое поведение, она ни чего из стека не выталкивает.

Вот из Intel manual

__asm вставки (процессор Pentium)


а вот конкретно про RET imm16 (тот, что с операндом)

__asm вставки (процессор Pentium)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.03.2013, 14:09     __asm вставки (процессор Pentium)
Еще ссылки по теме:

C++ __asm Как начать? C++
__asm ошибка Access violation writing location C++
Обнулить элементы вектора через __asm C++

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

Или воспользуйтесь поиском по форуму:
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
18.03.2013, 14:09     __asm вставки (процессор Pentium) #10
Цитата Сообщение от _Ivana Посмотреть сообщение
без выталкивания из стека всего того, что в него было ранее засунуто.
а, не увидел сразу. Ну да, о чем и написал выше.
Yandex
Объявления
18.03.2013, 14:09     __asm вставки (процессор Pentium)
Ответ Создать тему
Опции темы

Текущее время: 19:29. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru