• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Wstawki assemblerowe w C

Object Storage Arubacloud
+2 głosów
514 wizyt
pytanie zadane 12 czerwca 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 13 czerwca 2018 przez Jakub 0

Witam, wiem że rozwiązanie problemu może być banalne ale nie zupełnie nie wiem co mam robić.

Korzystałem z tego poradnika: http://informatyka.wroc.pl/node/382

Napisałem taki kod:

#include <stdio.h>

int i;
int main(){
    asm(" mov eax,7; mov i,eax; ");

    printf("%i\n", i); //i==7
    return 0;
}

Mam błąd kompilacji: to many memory references to 'mov', co dziwniejsze pokazuje mi że error wystąpił na 30 linii kodu ( a takiej tu w ogóle nie ma - chyba że po linkowaniu ).

Program kompilowałem pod Ubuntu kompilatorem gcc oraz pod code::blocks ( też gcc ) na Windows. Wszędzie to samo...

Jestem zupełnie zielony w asm'ie. Chciałem się trochę pobawić jego wstawkami w C dla zabawy ;)

Będę bardzo wdzięczny za wykazanie przyczyny błędu oraz jak go naprawić, serdecznie pozdrawiam

 

komentarz zamknięcia: temat wyczerpany

3 odpowiedzi

+2 głosów
odpowiedź 12 czerwca 2018 przez niezalogowany

Dodaj do opcji kompilatora -masm=intel

komentarz 12 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)
A jak mam AMD?
komentarz 12 czerwca 2018 przez niezalogowany
Intel i AMD używają tego samego zestawu instrukcji.
2
komentarz 12 czerwca 2018 przez Eryk Andrzejewski Mędrzec (164,260 p.)

Nie chodzi tutaj o producenta procesora, ale o składnię języka asemblera. Poczytaj o składniach Intela i AT&T. smiley

komentarz 12 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)
Kurcze... strasznie złożony ten temat. Od czego proponujesz mi zacząć? Zawsze chciałem poznać assemblera ale teraz widzę że zanim zacznę pisać jego wstawki to może warto poznać go od podstaw... Bo widzę że jego kod można wstawić na bardzo wiele sposobów :/

* Najbardziej czytelnie wygląda według mnie ten ze strony do której dałem link ( tam też mam wrażenie że podstawy asm'a są od podstaw ), jednak teraz po dodaniu opcji kompilatora mam z kolei taki błąd:

" undefined reference to 'i' "

Natomiast przykłady podane poniżej kompilują mi się już poprawnie.
1
komentarz 12 czerwca 2018 przez Chess Szeryf (76,710 p.)
edycja 13 czerwca 2018 przez Chess

Wydaje mi się, że jeśli nie kompilujesz tego z jakimiś dodatkowymi opcjami, to wtedy powinno Tobie zwracać taki błąd o niezdefiniowaniu "i". Jeśli chcesz, aby kompilator, czy linker wiedział o tym, że chcesz wziąć wartość ze zmiennej "i", to musisz dodać te opcje przy kompilowaniu. Takiej opcji chyba nie ma, trzeba użyć Extended Asm.

#include <stdio.h>
 
int i=10;
int arg1=3;
int main(){
	__asm__("xor %eax,%eax;");
	__asm__("xor %ebx,%ebx;");
    __asm__("mov %%eax,%%ebx;" : "=a" (i) : "a" (arg1));
 
    printf("%i\n", arg1);
    return 0;
}

 

komentarz 12 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)
Uzmysłowiłem sobie że w artykule w którym znalazłem kod jest napisane jak go skompilować, na Ubuntu wszystko mi śmiga :)

Mam tylko jedno pytanie, będę wdzięczny za linka lub krótką odpowiedź,

dlaczego można pisać:

1 -> asm(...)

2 -> __asm__(...)

3 -> widziałem też: _asm(..)

Czy to zależy od implementacji, systemu, kompilatora, procesora/wersji asemblera bos nie wiem :/
1
komentarz 12 czerwca 2018 przez Chess Szeryf (76,710 p.)
edycja 12 czerwca 2018 przez Chess

To wynika ze zdefiniowanego standardu kompilacji GCC, popatrz na ten link:

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

The format of basic inline assembly is very much straight forward. Its basic form is

asm("assembly code");

 

You might have noticed that here I’ve used asm and __asm__. Both are valid. We can use __asm__ if the keyword asm conflicts with something in our program. If we have more than one instructions, we write one per line in double quotes, and also suffix a ’\n’ and ’\t’ to the instruction. This is because gcc sends each instruction as a string to as(GAS) and by using the newline/tab we send correctly formatted lines to the assembler.

Poczytaj jeszcze ten punkt:

5. Extended Asm.

https://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Alternate-Keywords.html#Alternate-Keywords


Napisali, że różne składnie są dozwolone i będą kompilowane, czy są jakieś różnice, musisz doczytać.

https://en.cppreference.com/w/cpp/language/asm <-- Na samym dole masz link'i.

https://gist.github.com/dweinstein/5310752

https://en.wikibooks.org/wiki/X86_Disassembly/Assemblers_and_Compilers

Opcje kompilacji: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#x86-Options.

Używanie Asm'a w C/C++: https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html.

Link1, link2.

komentarz 12 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)
edycja 12 czerwca 2018 przez Jakub 0

Wiem że jestem natrętny ale niepokoi mnie jeszcze jedna rzecz:

Na linuxie z opcją kompilatora gcc:  -masm=intel  taki kod mi zadział poprawnie:

asm(" mov eax,7; mov i,eax; ");

Na windows niby ten sam kompilator, ta sama jego opcja ale mam błąd że 'i' jest niezdefiniowane ( nie mogę odwoływać się do zmiennych C wewnątrz wstawki assemblerowej ). Zamiast tego muszę stosować "rozszerzoną" czy jakoś tak wersję wstawki.

 (...) : "=a" (i) : "a" (arg1) (...)

Tam muszę określić zmienne wejściowe, wyjściowe i odwoływać się do nich przez znak '%'. ( wiem że używam mało fachowych określeń, na pewno doczytam więcej na ten temat ale teraz chcę zakończyć już moją desperacką walkę, nie lubię pogodzić się z problemem nie wiedząc z czego on wynika ) Od czego to zależy? Niby składnia Intela chodzi mi poprawnie ale... no nie mogę odnosić się bezpośrednio do zmiennych z poza wstawki. A na systemie Ubuntu takie coś się już skompiluje :/ Pytam się bo nie wiem gdzie jest mój błąd a gdzie kwestia np. systemowa.

 

 

1
komentarz 13 czerwca 2018 przez Chess Szeryf (76,710 p.)
edycja 13 czerwca 2018 przez Chess

Nie chcę skłamać (przekreśliłem, to co napisałem wyżej), ale na IRC'u napisali na FREENODE, ##asm, że to nie jest możliwe na GCC nie używając Extended Asm. Jeśli, więc kompilujesz GCC, to musisz użyć tej rozszerzonej formy w wstawce.

Cytat z IRC'a:

it can only be accessed relative to the stack pointer (or the frame pointer if you have one)

Translate Google:

dostęp do niego można uzyskać tylko względem wskaźnika stosu (lub wskaźnika ramki, jeśli taki posiadasz)

Reasumując, jeśli kompilując GCC chcesz dostać się do wartości w zmiennej np. z C, to musisz wykonać przesunięcie offset i odczytać wartość.

and only the compiler would know the correct offset

i tylko kompilator zna poprawne przesunięcie

you COULD try to figure out the offset for one particular compilation and use that but that is prone to breaking and not recommended

MOŻESZ spróbować obliczyć przesunięcie dla jednej konkretnej kompilacji i użyć, ale jest to podatne na zerwanie i nie jest zalecane

then you would have to write something like mov eax, [esp+x]

wtedy musiałbyś napisać coś w stylu mov eax, [esp + x]

If "a" is a global on the stack hence it has symbol, also it's not possible?

it's possible if it's a global hence NOT on the stack

and that depends on knowing the name mangling

which mostly means whether you need an underscore prefix or not

OK, so how write this in code?

don't.

Why?

because it's wrong.

https://stackoverflow.com/questions/1034852/adding-leading-underscores-to-assembly-symbols-with-gcc-on-win32

https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html

Można jeszcze za pomocą symboli i znaku podkreślenia, czy czegoś w tym stylu napisać to, ale jest to niezalecane i niewspierane jeśli dobrze zrozumiałem w GCC, więc po co kombinować, jeśli można użyć Extended Asm. To co chcesz zrobić będzie miało chyba niezdefiniowanie zachowanie (undefined behavior). W standardzie tego chyba nie ma i jeśli zrobiłbyś to, to tylko jakimś trick'iem. Prawie wszędzie, gdzie patrzyłem na strony związane z GCC, to był tylko Extended Asm, więc to też coś znaczy.

Pomagali na IRC'u: Jester01, moony. Inni, którzy coś pisali: Xgc, dave0, plastic, korans, candide.

+1 głos
odpowiedź 12 czerwca 2018 przez Bondrusiek Maniak (61,370 p.)

Witam,

nie za bardzo ogarniam assemblera ale znalazłem coś na necie co może Ci pomóc rozwiązać ten problem. Troszkę przerobiłem Twój program i u mnie(Windows gcc) działa.

#include <stdio.h>

int i;
int main(){

    int a=7;
            asm ("movl %1, %%eax; \
                  movl %%eax, %0;"
                 :"=r"(i)        
                 :"r"(a)        
                 :"%eax"         
                 );

        printf("\n%d\n", i);
        return 0;
}

Dokładniejsze opisanie powyższego programu

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#toc3

+1 głos
odpowiedź 12 czerwca 2018 przez Chess Szeryf (76,710 p.)
edycja 12 czerwca 2018 przez Chess

Zobacz może na ten kod, trochę go zmodyfikowałem, znaleziony w czeluściach internetu.

https://www.codeproject.com/Articles/15971/Using-Inline-Assembly-in-C-C

#include <stdio.h>

int main() {

    int arg1, arg2, add;

    printf( "Enter two integer numbers : " );
    scanf( "%d%d", &arg1, &arg2 );

    /* Perform Addition, Subtraction, Multiplication & Division */
    __asm__ ( "add %%ebx, %%eax;" : "=a" (add) : "a" (arg1) , "b" (arg2) );

    printf( "%d + %d = %d\n", arg1, arg2, add );

    return 0 ;
}

Proces kompilacji (Windows 10, Nasm):

gcc your_file.c
a

Rezultat:

Enter two integer numbers : 15 6
15 + 6 = 21

Link1, link2, link3.

Podobne pytania

0 głosów
1 odpowiedź 395 wizyt
pytanie zadane 12 kwietnia 2018 w Assembler przez Isild Użytkownik (580 p.)
0 głosów
0 odpowiedzi 258 wizyt
pytanie zadane 6 kwietnia 2022 w Assembler przez Artur12555 Nowicjusz (120 p.)
0 głosów
0 odpowiedzi 228 wizyt
pytanie zadane 15 czerwca 2021 w C i C++ przez pawel_000 Początkujący (450 p.)

92,572 zapytań

141,423 odpowiedzi

319,645 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...