Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
1

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

18.03.2013, 00:45. Показов 1099. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу в вижуал Студии, делаю ассемблерные вставки, хочу вызывать си-процедуру, в которой тоже ассемблер - просто поменять значение одного регистра, не хочу никаких стеков, ОЗУ и прочего. При выходе похоже не восстанавливается из стека адрес возврата и программа вылетает. Подскажите, где ошибка? (Лишние куски кода убрал для краткости)
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;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.03.2013, 00:45
Ответы с готовыми решениями:

Профилирование, C++ и вставки ASM, прошу совета
есть собственно программа, вот часть кода где я и колдую int radix=10; int n = 1; double...

Builder C++ и asm вставки
У меня есть задание: даны 2 массива (двумерный и одномерный), нужно умножить из на разные множители...

Вставки на asm
Можно-ли использовать subj при программировании на directx? Меня обругивает...

Asm-вставки не работают
Собственно в этом и проблема. Компилятор матерится на ассемблерный код. И не важно где я пытаюсь...

9
Maniac
Эксперт С++
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
18.03.2013, 00:58 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-u... s.80).aspx
1
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
18.03.2013, 01:08  [ТС] 3
Спасибо, насколько я понял, при вызове CALL компилятор автоматически засовывает в стек что-то-там в неизвестном количестве, поэтому RET надо передать параметр - на сколько прыгнуть вглубь стека при возврате? Просто я прочитал, что если в процедуре не использовать определенные регистры, то компилятор и не будет их сохранять, я и старался использовать те,которые не в списке. Или я чего-то недопонимаю...

ЗЫ в чистом asm было проще - никто за тебя ничего не пушил и не попил и не портил адреса возвратов...
0
Maniac
Эксперт С++
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
18.03.2013, 01:15 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
1
4817 / 2278 / 287
Регистрация: 01.03.2013
Сообщений: 5,947
Записей в блоге: 28
18.03.2013, 03:09  [ТС] 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
0
601 / 468 / 73
Регистрация: 22.01.2009
Сообщений: 1,180
Записей в блоге: 1
18.03.2013, 04:00 6

Не по теме:

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


по теме, все правильно, компилируйте си код в исходник на ассемблере (не знаю, каким ключом это делать в студии, извините), и увидите, какой там пролог, эпилог, заодно call convensions выучите. можно еще посмотреть, что получается при указании ключей оптимизации. интересно! правда
Цитата Сообщение от ISergey Посмотреть сообщение
pop * * * * <registers> * ; Restore registers
по-простому, можно применять pusha/popa . с другой стороны, вы и только вы знаете, какие регистры использутся внутри вашего ассемблерного кода (компилятор тупо копипастит ваши куски), поэтому можете сохранять только те регистры, которые реально используются.
1
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,116
Записей в блоге: 2
18.03.2013, 10:40 7
Цитата Сообщение от _Ivana Посмотреть сообщение
Спасибо, насколько я понял, при вызове CALL компилятор автоматически засовывает в стек что-то-там в неизвестном количестве
инструкция CALL кладет в стек адрес возврата, т.е. адрес инструкции, следующей за call.

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


Kastaneda, да, вы правы, просто я позволил себе вольно выразиться - в стек пихается много чего после передачи управления на метку начала функции, а сама передача осуществляется CALL-ом.
В той книжке, которую я читаю, написано что можно передать RET параметр, который изменит указатель стека, по которому брать адрес возврата, без выталкивания из стека всего того, что в него было ранее засунуто. А можно изменить его вручную после вызова функции. Я это ещё не пробовал, но это первое что я сделаю, как приду с работы
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,116
Записей в блоге: 2
18.03.2013, 14:07 9
Цитата Сообщение от _Ivana Посмотреть сообщение
что можно передать RET параметр
Ну да, можно, только в этом случае у RET другое поведение, она ни чего из стека не выталкивает.

Вот из Intel manual

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



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

__asm вставки (процессор Pentium)
1
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,116
Записей в блоге: 2
18.03.2013, 14:09 10
Цитата Сообщение от _Ivana Посмотреть сообщение
без выталкивания из стека всего того, что в него было ранее засунуто.
а, не увидел сразу. Ну да, о чем и написал выше.
0
18.03.2013, 14:09
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.03.2013, 14:09
Помогаю со студенческими работами здесь

ASM Вставки iDIV
Пишу NumX:=-40; MOV EAX,NumX MOV ECX,4 IDIV ECX MOV IntPart, EAX

Delphi + asm(Вставки), строки.
Всем приветь ! Тот заинтересовался asm вставками в Дельфи, ну понял нормально работы с цифрами ...

Asm вставки в AVR GCC
Есть у кого-то описание как писать эти _страшные_ вещи? Конструкция подразумевающая всего лишь swap...

Длинная арифметика (ASM-вставки в C++)
привет всем, нужна помощь в освоении асм вставок, нужно написать длинную арифметику сложения,...

Построчное выполнение asm-вставки в сишный код
Подскажите, возможно ли во время дебаггинга выполнять ассемблерную вставку построчно? обычно весь...

Не работает процессор pentium d 820
Проблема следующая: материка у меня такая...


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

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