Spowoduje to uruchomienie preprocesora (cpp) na helloworld.c, wykonanie wstępnej kompilacji, a następnie zatrzymanie przed uruchomieniem asemblera.
Domyślnie spowoduje to wyświetlenie pliku helloworld.s. Plik wyjściowy można nadal ustawić za pomocą -oopcji.
gcc -S -o my_asm_output.s helloworld.c
Oczywiście działa to tylko wtedy, gdy masz oryginalne źródło. Alternatywą, jeśli masz tylko wynikowy plik obiektowy, jest użycie objdump, ustawiając --disassembleopcję (lub -dw formie skróconej).
Chociaż jest to poprawne, wyniki z odpowiedzi Cr McDonougha były bardziej przydatne.
Rhys Ulerich,
3
dodatkowe użycie: objdump -M intel -S --disassemble helloworld> helloworld.dump, aby uzyskać zrzut obiektu w składni intel kompatybilnej z nasm na Linuksie.
touchStone 11.03.15
2
Jeśli masz jedną funkcję do optymalizacji / sprawdzania, możesz spróbować interaktywnych kompilatorów C ++ online, tj. Godbolt
fiorentinoing
1
@touchStone: GAS nie.intel_syntax jest kompatybilny z NASM . Jest bardziej podobny do MASM (np. mov eax, symbolJest obciążeniem, w przeciwieństwie do NASM, gdzie jest mov r32, imm32adresem), ale też nie jest w pełni kompatybilny z MASM. Bardzo polecam to jako przyjemny format do czytania, szczególnie jeśli lubisz pisać w składni NASM. objdump -drwC -Mintel | lesslub gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | lesssą przydatne. (Zobacz także Jak usunąć „szum” z danych wyjściowych zespołu GCC / clang? ). -masm=inteldziała również z clang.
Peter Cordes,
3
Lepsze wykorzystaniegcc -O -fverbose-asm -S
Basile Starynkevitch
173
Spowoduje to wygenerowanie kodu zestawu z przeplatanym kodem C + numery linii, aby łatwiej zobaczyć, które linie generują jaki kod:
(To tak naprawdę na stronie (ponumerowanej) 3 (która jest 15. stroną pliku PDF))
Grumdrig,
1
Niestety asw systemie OS X te flagi nie są znane. Gdyby tak było, prawdopodobnie można by to zrobić w jednym wierszu, używając -Waopcji do przekazania opcji as.
Grumdrig,
23
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lstbyłaby to krótka wersja tego.
legends2k
4
Można również użyć gcc -c -g -Wa,-ahl=test.s test.calbogcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv
1
Blogu tłumacząc to bardziej szczegółowo, łącznie z wersją jednego polecenia jak legendy i Lu'u pisał. Ale dlaczego -O0? Jest pełen ładunków / sklepów, które utrudniają śledzenie wartości i nie mówią nic o wydajności zoptymalizowanego kodu.
Uruchomiłem G ++ z okna DOS na Win-XP, z procedurą zawierającą ukrytą obsadę
c:\gpp_code>g++-g -O -Wa,-aslh horton_ex2_05.cpp >list.txt
horton_ex2_05.cpp:Infunction`int main()':
horton_ex2_05.cpp:92: warning: assignment to `int' from `double'
Dane wyjściowe są zestawione wygenerowany kod iterowany z oryginalnym kodem C ++ (kod C ++ jest wyświetlany jako komentarze w wygenerowanym strumieniu asm)
@Paladin - niekoniecznie. OP dotyczył uzyskania ekwiwalentu wyjściowego asemblera kodu źródłowego C / C ++, uzyskuje to Listing, który, jak się zgadzam, jest bardziej przydatny do zrozumienia, co robi kompilator i optymalizator. Spowodowałoby to jednak, że asembler zbankrutował, ponieważ nie spodziewał się numerów linii i skompilował bajty poza instrukcją asemblera.
Jesse Chisholm,
-O2Jeśli chcesz zobaczyć, jak gcc optymalizuje kod, użyj przynajmniej lub jakiejkolwiek opcji optymalizacji, której faktycznie używasz podczas budowania projektu. (Lub jeśli używasz LTO, tak jak powinieneś, to musisz zdemontować wyjście linkera, aby zobaczyć, co naprawdę dostajesz.)
Sprawdź często zadawane pytania: „Można również zadawać własne pytania dotyczące programowania i odpowiadać na nie”. Chodzi o to, że teraz StackOverflow zawiera pytania i odpowiedzi jako zasób dla innych.
Steve Jessop
I może ktoś inny przyjdzie i zaskoczy cię lepszą odpowiedzią, choć czasami moja może być trochę gadatliwa ...
PhirePhly
Istnieje nawet odpowiedź na własny przycisk pytania.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
13
Jeśli to, co chcesz zobaczyć, zależy od połączenia wyniku, wówczas objdump na pliku wynikowym pliku / pliku wykonywalnym może być również przydatny jako dodatek do wyżej wspomnianego gcc -S. Oto bardzo przydatny skrypt autorstwa Lorena Merritta, który konwertuje domyślną składnię objdump na bardziej czytelną składnię nasm:
#!/usr/bin/perl -w
$ptr='(BYTE|WORD|DWORD|QWORD|XMMWORD) PTR ';
$reg='(?:[er]?(?:[abcd]x|[sd]i|[sb]p)|[abcd][hl]|r1?[0-589][dwb]?|mm[0-7]|xmm1?[0-9])';
open FH,'-|','/usr/bin/objdump','-w','-M','intel',@ARGVordie;
$prev ="";while(<FH>){if(/$ptr/o){
s/$ptr(\[[^\[\]]+\],$reg)/$2/o or
s/($reg,)$ptr(\[[^\[\]]+\])/$1$3/o or
s/$ptr/lc $1/oe;}if($prev =~/\t(repz )?ret /and
$_ =~/\tnop |\txchg *ax,ax$/){# drop this line}else{print $prev;
$prev = $_;}}print $prev;
close FH;
Podejrzewam, że można tego również użyć na wyjściu gcc -S.
Mimo to ten skrypt to brudny hack, który nie do końca przekształca składnię. Np. mov eax,ds:0x804b794Nie jest bardzo NASMish. Czasami po prostu usuwa przydatne informacje: movzx eax,[edx+0x1]pozostawia czytelnikowi odgadnięcie, czy operand pamięci był, byteczy też word.
Ruslan,
Aby w pierwszej kolejności zdemontować składnię NASM, użyj Agner Fog'sobjconv . Możesz go zdemontować na standardowe wyjście z plikiem wyjściowym = /dev/stdout, dzięki czemu możesz przesyłać strumieniowo do lessoglądania. Jest też ndisasm, ale dezasembluje tylko płaskie pliki binarne i nie wie o plikach obiektowych (ELF / PE).
Peter Cordes,
9
Jak wszyscy zauważyli, skorzystaj z -Sopcji GCC. Chciałbym również dodać, że wyniki mogą się różnić (szalenie!) W zależności od tego, czy dodasz opcje optymalizacji (w -O0przypadku braku, w -O2przypadku agresywnej optymalizacji).
W szczególności na architekturach RISC kompilator często przekształca kod niemal nie do poznania w procesie optymalizacji. Spojrzenie na wyniki jest imponujące i fascynujące!
Jak wszyscy mówili, użyj opcji -S. Jeśli użyjesz opcji -save-temps, możesz również uzyskać wstępnie przetworzony plik ( .i), plik zestawu ( .s) i plik obiektowy (* .o). (pobierz każdy z nich, używając -E, -S i -c.)
Warto również przyjrzeć się rodzinie flag „-fdump-tree”, w szczególności „-fdump-tree-all”, która pozwala zobaczyć niektóre pośrednie formy gcc. Często mogą być bardziej czytelne niż asembler (przynajmniej dla mnie) i pozwalają zobaczyć, jak przebiegają optymalizacje.
Nie widzę takiej możliwości wśród odpowiedzi, prawdopodobnie dlatego, że pytanie pochodzi z 2008 r., Ale w 2018 r. Możesz skorzystać ze strony internetowej Matta Goldbolta https://godbolt.org
Jeśli chcesz to zrobić dla dużej liczby plików, rozważ użycie zamiast tego:
-save-temps=obj
który zapisuje pliki pośrednie w tym samym katalogu, co -oobiekt wyjściowy zamiast w bieżącym katalogu roboczym, unikając w ten sposób potencjalnych konfliktów nazw basename.
Kolejną fajną rzeczą w tej opcji jest dodanie -v:
gcc -save-temps -c -o main.o -v main.c
w rzeczywistości pokazuje jawne pliki używane zamiast brzydkich tymczasowych plików /tmp, więc łatwo jest dokładnie wiedzieć, co się dzieje, co obejmuje etapy wstępnego przetwarzania / kompilacji / montażu:
Aby wyświetlić w terminalu, użyj gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -Ssam tworzy foo.s.
Peter Cordes
2
Niedawno chciałem poznać zestawienie każdej funkcji w programie.
Tak to zrobiłem.
$ gcc main.c // main.c source file
$ gdb a.exe // gdb a.out in linux(gdb) disass main // note here main is a function// similary it can be done for other functions
Tutaj pierwsza część przechowuje dane wyjściowe asemblera programu pod tą samą nazwą pliku, co Program, ale ze zmienionym rozszerzeniem .s , można go otworzyć jak każdy zwykły plik tekstowy.
Druga część tutaj kompiluje twój program do faktycznego użycia i generuje plik wykonywalny dla twojego programu o określonej nazwie pliku.
Program.c użyte powyżej to nazwa programu i wyjście to nazwa pliku wykonywalnego chcesz wygenerować.
Odpowiedzi:
Użyj
-S
opcji gcc (lub g ++).Spowoduje to uruchomienie preprocesora (cpp) na helloworld.c, wykonanie wstępnej kompilacji, a następnie zatrzymanie przed uruchomieniem asemblera.
Domyślnie spowoduje to wyświetlenie pliku
helloworld.s
. Plik wyjściowy można nadal ustawić za pomocą-o
opcji.Oczywiście działa to tylko wtedy, gdy masz oryginalne źródło. Alternatywą, jeśli masz tylko wynikowy plik obiektowy, jest użycie
objdump
, ustawiając--disassemble
opcję (lub-d
w formie skróconej).Ta opcja działa najlepiej, jeśli dla pliku obiektowego (
-g
w czasie kompilacji) włączona jest opcja debugowania, a plik nie został usunięty.Uruchomienie
file helloworld
da ci pewne wskazówki co do poziomu szczegółowości, który uzyskasz za pomocą objdump.źródło
.intel_syntax
jest kompatybilny z NASM . Jest bardziej podobny do MASM (np.mov eax, symbol
Jest obciążeniem, w przeciwieństwie do NASM, gdzie jestmov r32, imm32
adresem), ale też nie jest w pełni kompatybilny z MASM. Bardzo polecam to jako przyjemny format do czytania, szczególnie jeśli lubisz pisać w składni NASM.objdump -drwC -Mintel | less
lubgcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
są przydatne. (Zobacz także Jak usunąć „szum” z danych wyjściowych zespołu GCC / clang? ).-masm=intel
działa również z clang.gcc -O -fverbose-asm -S
Spowoduje to wygenerowanie kodu zestawu z przeplatanym kodem C + numery linii, aby łatwiej zobaczyć, które linie generują jaki kod:
Znalezione w Algorytmy dla programistów , strona 3 (co stanowi ogólną 15 stronę pliku PDF).
źródło
as
w systemie OS X te flagi nie są znane. Gdyby tak było, prawdopodobnie można by to zrobić w jednym wierszu, używając-Wa
opcji do przekazania opcjias
.g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
byłaby to krótka wersja tego.gcc -c -g -Wa,-ahl=test.s test.c
albogcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? Jest pełen ładunków / sklepów, które utrudniają śledzenie wartości i nie mówią nic o wydajności zoptymalizowanego kodu.Następująca linia poleceń pochodzi z bloga Christiana Garbina
Uruchomiłem G ++ z okna DOS na Win-XP, z procedurą zawierającą ukrytą obsadę
Dane wyjściowe są zestawione wygenerowany kod iterowany z oryginalnym kodem C ++ (kod C ++ jest wyświetlany jako komentarze w wygenerowanym strumieniu asm)
źródło
-O2
Jeśli chcesz zobaczyć, jak gcc optymalizuje kod, użyj przynajmniej lub jakiejkolwiek opcji optymalizacji, której faktycznie używasz podczas budowania projektu. (Lub jeśli używasz LTO, tak jak powinieneś, to musisz zdemontować wyjście linkera, aby zobaczyć, co naprawdę dostajesz.)Użyj przełącznika -S
lub także z gcc
Patrz także to
źródło
Jeśli to, co chcesz zobaczyć, zależy od połączenia wyniku, wówczas objdump na pliku wynikowym pliku / pliku wykonywalnym może być również przydatny jako dodatek do wyżej wspomnianego gcc -S. Oto bardzo przydatny skrypt autorstwa Lorena Merritta, który konwertuje domyślną składnię objdump na bardziej czytelną składnię nasm:
Podejrzewam, że można tego również użyć na wyjściu gcc -S.
źródło
mov eax,ds:0x804b794
Nie jest bardzo NASMish. Czasami po prostu usuwa przydatne informacje:movzx eax,[edx+0x1]
pozostawia czytelnikowi odgadnięcie, czy operand pamięci był,byte
czy teżword
.objconv
. Możesz go zdemontować na standardowe wyjście z plikiem wyjściowym =/dev/stdout
, dzięki czemu możesz przesyłać strumieniowo doless
oglądania. Jest teżndisasm
, ale dezasembluje tylko płaskie pliki binarne i nie wie o plikach obiektowych (ELF / PE).Jak wszyscy zauważyli, skorzystaj z
-S
opcji GCC. Chciałbym również dodać, że wyniki mogą się różnić (szalenie!) W zależności od tego, czy dodasz opcje optymalizacji (w-O0
przypadku braku, w-O2
przypadku agresywnej optymalizacji).W szczególności na architekturach RISC kompilator często przekształca kod niemal nie do poznania w procesie optymalizacji. Spojrzenie na wyniki jest imponujące i fascynujące!
źródło
Jak wszyscy mówili, użyj opcji -S. Jeśli użyjesz opcji -save-temps, możesz również uzyskać wstępnie przetworzony plik ( .i), plik zestawu ( .s) i plik obiektowy (* .o). (pobierz każdy z nich, używając -E, -S i -c.)
źródło
Jak wspomniano wcześniej, spójrz na flagę -S.
Warto również przyjrzeć się rodzinie flag „-fdump-tree”, w szczególności „-fdump-tree-all”, która pozwala zobaczyć niektóre pośrednie formy gcc. Często mogą być bardziej czytelne niż asembler (przynajmniej dla mnie) i pozwalają zobaczyć, jak przebiegają optymalizacje.
źródło
Jeśli szukasz zestawu LLVM:
źródło
Nie widzę takiej możliwości wśród odpowiedzi, prawdopodobnie dlatego, że pytanie pochodzi z 2008 r., Ale w 2018 r. Możesz skorzystać ze strony internetowej Matta Goldbolta https://godbolt.org
Możesz także lokalnie uzyskać klon i uruchomić jego projekt https://github.com/mattgodbolt/compiler-explorer
źródło
-save-temps
Zostało to wspomniane na https://stackoverflow.com/a/17083009/895245 ale pozwólcie, że jeszcze to zilustruję.
Dużą zaletą tej opcji
-S
jest to, że bardzo łatwo jest dodać ją do dowolnego skryptu kompilacji, bez ingerowania w samą kompilację.Kiedy to zrobisz:
main.c
a teraz, poza normalnym wyjściem
main.o
, bieżący katalog roboczy zawiera również następujące pliki:main.i
jest premią i zawiera wstępnie przejęty plik:main.s
zawiera żądany wygenerowany zespół:Jeśli chcesz to zrobić dla dużej liczby plików, rozważ użycie zamiast tego:
który zapisuje pliki pośrednie w tym samym katalogu, co
-o
obiekt wyjściowy zamiast w bieżącym katalogu roboczym, unikając w ten sposób potencjalnych konfliktów nazw basename.Kolejną fajną rzeczą w tej opcji jest dodanie
-v
:w rzeczywistości pokazuje jawne pliki używane zamiast brzydkich tymczasowych plików
/tmp
, więc łatwo jest dokładnie wiedzieć, co się dzieje, co obejmuje etapy wstępnego przetwarzania / kompilacji / montażu:Testowane w Ubuntu 19.04 amd64, GCC 8.3.0.
źródło
Użyj opcji -S:
źródło
Od: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [inne opcje GCC] foo.c> foo.lst
zamiast odpowiedzi PhirePhly Lub po prostu użyj -S, jak wszyscy mówili.
źródło
Oto kroki, aby zobaczyć / wydrukować kod asemblera dowolnego programu C w systemie Windows
konsola / terminal / wiersz poleceń:
Napisz program C w edytorze kodu C, takim jak bloki kodu i zapisz go z rozszerzeniem .c
Skompiluj i uruchom.
Po pomyślnym uruchomieniu przejdź do folderu, w którym zainstalowałeś kompilator gcc i podaj
następujące polecenie, aby uzyskać plik „.s” pliku „.c”
C: \ gcc> gcc -S pełna ścieżka do pliku C. ENTER
Przykładowe polecenie (jak w moim przypadku)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Spowoduje to wygenerowanie pliku „.s” oryginalnego pliku „.c”
4 Następnie wpisz następujące polecenie
C; \ gcc> cpp filename.s ENTER
Przykładowe polecenie (jak w moim przypadku)
C; \ gcc> cpp alternate_letters.s
Spowoduje to wydrukowanie / wydrukowanie całego kodu języka asemblera twojego programu C.
źródło
Jako opcji użyj „-S”. Wyświetla dane wyjściowe zestawu w terminalu.
źródło
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
.-S
sam tworzyfoo.s
.Niedawno chciałem poznać zestawienie każdej funkcji w programie.
Tak to zrobiłem.
źródło
Oto rozwiązanie dla C przy użyciu gcc:
Tutaj pierwsza część przechowuje dane wyjściowe asemblera programu pod tą samą nazwą pliku, co Program, ale ze zmienionym rozszerzeniem .s , można go otworzyć jak każdy zwykły plik tekstowy.
Druga część tutaj kompiluje twój program do faktycznego użycia i generuje plik wykonywalny dla twojego programu o określonej nazwie pliku.
Program.c użyte powyżej to nazwa programu i wyjście to nazwa pliku wykonywalnego chcesz wygenerować.
BTW To mój pierwszy post na StackOverFlow: -}
źródło