Esto ejecutará el preprocesador (cpp) sobre helloworld.c, realizará la compilación inicial y luego se detendrá antes de ejecutar el ensamblador.
Por defecto, esto generará un archivo helloworld.s. El archivo de salida todavía se puede configurar mediante la -oopción.
gcc -S -o my_asm_output.s helloworld.c
Por supuesto, esto solo funciona si tiene la fuente original. Una alternativa si solo tiene el archivo de objeto resultante es usar objdump, configurando la --disassembleopción (o -dpara la forma abreviada).
Esta opción funciona mejor si la opción de depuración está habilitada para el archivo objeto ( -gen el momento de la compilación) y el archivo no se ha eliminado.
La ejecución file helloworldle dará alguna indicación sobre el nivel de detalle que obtendrá al usar objdump.
Si bien esto es correcto, los resultados de la respuesta de Cr McDonough me parecieron más útiles.
Rhys Ulerich el
3
un uso adicional: objdump -M intel -S --desmontar helloworld> helloworld.dump para obtener el volcado del objeto en la sintaxis de Intel compatible con nasm en linux.
touchStone
2
Si tiene una única función para optimizar / verificar, entonces puede probar los compiladores interactivos de C ++ en línea, es decir, Godbolt
fiorentinoing
1
@touchStone: GAS no.intel_syntax es compatible con NASM . Es más como MASM (por ejemplo, mov eax, symboles una carga, a diferencia de NASM donde es una mov r32, imm32de las direcciones), pero tampoco es totalmente compatible con MASM. Lo recomiendo encarecidamente como un buen formato para leer, especialmente si te gusta escribir en sintaxis NASM. objdump -drwC -Mintel | lesso gcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | lessson útiles (Consulte también ¿Cómo eliminar el "ruido" de la salida del conjunto GCC / clang? ). -masm=inteltambién funciona con clang.
Peter Cordes
3
Mejor usogcc -O -fverbose-asm -S
Basile Starynkevitch
173
Esto generará código de ensamblaje con los números de línea del código C + entrelazados, para ver más fácilmente qué líneas generan qué código:
(Eso está realmente en la página (numerada) 3 (que es la 15ª página del PDF))
Grumdrig
1
Lamentablemente, asen OS X no conoce estas banderas. Sin embargo, si lo hiciera, probablemente podría usar esto en una línea -Wapara pasar opciones as.
Grumdrig el
23
g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lstsería la versión abreviada de esto.
legends2k
44
También puede usar gcc -c -g -Wa,-ahl=test.s test.cogcc -c -g -Wa,-a,-ad test.c > test.txt
phuclv
1
Una publicación de blog que explica esto con más detalle, incluida la versión de un comando como leyendas y Lu'u publicado. Pero por que -O0? Está lleno de cargas / tiendas que dificultan el seguimiento de un valor, y no le dice nada acerca de cuán eficiente será el código optimizado.
Ejecuté G ++ desde una ventana de DOS en Win-XP, contra una rutina que contiene un reparto implícito
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'
La salida se ensambla con el código generado que se mezcla con el código original de C ++ (el código de C ++ se muestra como comentarios en el flujo de asm generado)
@Paladin: no necesariamente. El OP se trataba de obtener el equivalente de salida del ensamblador del código fuente C / C ++, esto obtiene el Listado, que estoy de acuerdo es más útil para comprender lo que está haciendo el compilador y el optimizador. Pero causaría que el ensamblador mismo vomitara, ya que no espera los números de línea, y compilará los bytes a la izquierda de las instrucciones de ensamblaje.
Jesse Chisholm
Use al menos -O2, o cualquier opción de optimización que realmente use al construir su proyecto, si desea ver cómo gcc optimiza su código. (O si usa LTO, como debería, entonces debe desarmar la salida del enlazador para ver lo que realmente obtiene.)
Consulte las preguntas frecuentes: "También está perfectamente bien hacer y responder su propia pregunta de programación". El punto es que ahora StackOverflow contiene las preguntas y respuestas como un recurso para otros.
Steve Jessop
Y tal vez alguien más vendrá y te sorprenderá con una mejor respuesta, aunque la mía podría ser un poco detallada a veces ...
PhirePhly
Incluso hay un botón para responder a su propia pregunta.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
13
Si lo que quiere ver depende de la vinculación de la salida, entonces objdump en el archivo / ejecutable del objeto de salida también puede ser útil además del gcc -S mencionado anteriormente. Aquí hay un script muy útil de Loren Merritt que convierte la sintaxis objdump predeterminada en la sintaxis nasm más legible:
#!/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;
Sospecho que esto también se puede usar en la salida de gcc -S.
Aún así, este script es un truco sucio que no convierte completamente la sintaxis. Por ejemplo, mov eax,ds:0x804b794no es muy NASMish. Además, a veces simplemente elimina información útil: movzx eax,[edx+0x1]deja al lector adivinar si el operando de la memoria fue byteo no word.
Ruslan
Para desmontar la sintaxis NASM en primer lugar, use Agner Fog'sobjconv . Puede hacer que se desmonte en stdout con el archivo de salida = /dev/stdout, para que pueda canalizarlo lesspara verlo. También hay ndisasm, pero solo desmonta los binarios planos, y no conoce los archivos de objetos (ELF / PE).
Peter Cordes
9
Como todos han señalado, use la -Sopción para GCC. También me gustaría agregar que los resultados pueden variar (¡salvajemente!) Dependiendo de si agrega o no opciones de optimización ( -O0para ninguno, -O2para una optimización agresiva).
En arquitecturas RISC en particular, el compilador a menudo transformará el código casi más allá del reconocimiento al hacer la optimización. ¡Es impresionante y fascinante ver los resultados!
Bueno, como todos decían, usa la opción -S. Si usa la opción -save-temps, también puede obtener el archivo preprocesado ( .i), el archivo de ensamblaje ( .s) y el archivo de objeto (*. O). (obtén cada uno de ellos usando -E, -S y -c.)
Como se mencionó anteriormente, mira la bandera -S.
También vale la pena mirar la familia de banderas '-fdump-tree', en particular '-fdump-tree-all', que le permite ver algunas de las formas intermedias de gcc. Estos a menudo pueden ser más legibles que el ensamblador (al menos para mí) y le permiten ver cómo funcionan los pases de optimización.
No veo esta posibilidad entre las respuestas, probablemente porque la pregunta es de 2008, pero en 2018 puede usar el sitio web en línea de Matt Goldbolt https://godbolt.org
Si desea hacerlo para una gran cantidad de archivos, considere usar en su lugar:
-save-temps=obj
que guarda los archivos intermedios en el mismo directorio que la -osalida del objeto en lugar del directorio de trabajo actual, evitando así posibles conflictos de nombres básicos.
Otra cosa interesante de esta opción es si agrega -v:
gcc -save-temps -c -o main.o -v main.c
En realidad, muestra los archivos explícitos que se utilizan en lugar de los temporales feos debajo /tmp, por lo que es fácil saber exactamente lo que está sucediendo, lo que incluye los pasos de preprocesamiento / compilación / ensamblaje:
Para mostrar en el terminal, use gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less. -Spor sí mismo crea foo.s.
Peter Cordes
2
Recientemente quería saber el ensamblaje de cada función en un programa,
así es como lo hice.
$ 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
Aquí la primera parte almacena la salida del ensamblaje del programa en el mismo nombre de archivo que el Programa pero con una extensión .s modificada , puede abrirlo como cualquier archivo de texto normal.
La segunda parte aquí compila su programa para el uso real y genera un ejecutable para su programa con un nombre de archivo especificado.
El program.c utilizado anteriormente es el nombre de su programa y la salida es el nombre del ejecutable que desea generar.
Por cierto, es mi primera publicación en StackOverFlow: -}
Respuestas:
Use la
-S
opción para gcc (o g ++).Esto ejecutará el preprocesador (cpp) sobre helloworld.c, realizará la compilación inicial y luego se detendrá antes de ejecutar el ensamblador.
Por defecto, esto generará un archivo
helloworld.s
. El archivo de salida todavía se puede configurar mediante la-o
opción.Por supuesto, esto solo funciona si tiene la fuente original. Una alternativa si solo tiene el archivo de objeto resultante es usar
objdump
, configurando la--disassemble
opción (o-d
para la forma abreviada).Esta opción funciona mejor si la opción de depuración está habilitada para el archivo objeto (
-g
en el momento de la compilación) y el archivo no se ha eliminado.La ejecución
file helloworld
le dará alguna indicación sobre el nivel de detalle que obtendrá al usar objdump.fuente
.intel_syntax
es compatible con NASM . Es más como MASM (por ejemplo,mov eax, symbol
es una carga, a diferencia de NASM donde es unamov r32, imm32
de las direcciones), pero tampoco es totalmente compatible con MASM. Lo recomiendo encarecidamente como un buen formato para leer, especialmente si te gusta escribir en sintaxis NASM.objdump -drwC -Mintel | less
ogcc foo.c -O1 -fverbose-asm -masm=intel -S -o- | less
son útiles (Consulte también ¿Cómo eliminar el "ruido" de la salida del conjunto GCC / clang? ).-masm=intel
también funciona con clang.gcc -O -fverbose-asm -S
Esto generará código de ensamblaje con los números de línea del código C + entrelazados, para ver más fácilmente qué líneas generan qué código:
Se encuentra en Algoritmos para programadores , página 3 (que es la 15ª página general del PDF).
fuente
as
en OS X no conoce estas banderas. Sin embargo, si lo hiciera, probablemente podría usar esto en una línea-Wa
para pasar opcionesas
.g++ -g -O0 -c -fverbose-asm -Wa,-adhln test.cpp > test.lst
sería la versión abreviada de esto.gcc -c -g -Wa,-ahl=test.s test.c
ogcc -c -g -Wa,-a,-ad test.c > test.txt
-O0
? Está lleno de cargas / tiendas que dificultan el seguimiento de un valor, y no le dice nada acerca de cuán eficiente será el código optimizado.La siguiente línea de comando es del blog de Christian Garbin.
Ejecuté G ++ desde una ventana de DOS en Win-XP, contra una rutina que contiene un reparto implícito
La salida se ensambla con el código generado que se mezcla con el código original de C ++ (el código de C ++ se muestra como comentarios en el flujo de asm generado)
fuente
-O2
, o cualquier opción de optimización que realmente use al construir su proyecto, si desea ver cómo gcc optimiza su código. (O si usa LTO, como debería, entonces debe desarmar la salida del enlazador para ver lo que realmente obtiene.)Use el interruptor -S
o también con gcc
También vea esto
fuente
Si lo que quiere ver depende de la vinculación de la salida, entonces objdump en el archivo / ejecutable del objeto de salida también puede ser útil además del gcc -S mencionado anteriormente. Aquí hay un script muy útil de Loren Merritt que convierte la sintaxis objdump predeterminada en la sintaxis nasm más legible:
Sospecho que esto también se puede usar en la salida de gcc -S.
fuente
mov eax,ds:0x804b794
no es muy NASMish. Además, a veces simplemente elimina información útil:movzx eax,[edx+0x1]
deja al lector adivinar si el operando de la memoria fuebyte
o noword
.objconv
. Puede hacer que se desmonte en stdout con el archivo de salida =/dev/stdout
, para que pueda canalizarloless
para verlo. También hayndisasm
, pero solo desmonta los binarios planos, y no conoce los archivos de objetos (ELF / PE).Como todos han señalado, use la
-S
opción para GCC. También me gustaría agregar que los resultados pueden variar (¡salvajemente!) Dependiendo de si agrega o no opciones de optimización (-O0
para ninguno,-O2
para una optimización agresiva).En arquitecturas RISC en particular, el compilador a menudo transformará el código casi más allá del reconocimiento al hacer la optimización. ¡Es impresionante y fascinante ver los resultados!
fuente
Bueno, como todos decían, usa la opción -S. Si usa la opción -save-temps, también puede obtener el archivo preprocesado ( .i), el archivo de ensamblaje ( .s) y el archivo de objeto (*. O). (obtén cada uno de ellos usando -E, -S y -c.)
fuente
Como se mencionó anteriormente, mira la bandera -S.
También vale la pena mirar la familia de banderas '-fdump-tree', en particular '-fdump-tree-all', que le permite ver algunas de las formas intermedias de gcc. Estos a menudo pueden ser más legibles que el ensamblador (al menos para mí) y le permiten ver cómo funcionan los pases de optimización.
fuente
Si está buscando el ensamblaje LLVM:
fuente
No veo esta posibilidad entre las respuestas, probablemente porque la pregunta es de 2008, pero en 2018 puede usar el sitio web en línea de Matt Goldbolt https://godbolt.org
También puede git clone localmente y ejecutar su proyecto https://github.com/mattgodbolt/compiler-explorer
fuente
-save-temps
Esto se mencionó en https://stackoverflow.com/a/17083009/895245 pero permítanme ejemplificarlo más.
La gran ventaja de esta opción
-S
es que es muy fácil agregarlo a cualquier script de compilación, sin interferir mucho en la compilación misma.Cuando tu lo hagas:
C Principal
y ahora, además de la salida normal
main.o
, el directorio de trabajo actual también contiene los siguientes archivos:main.i
es una bonificación y contiene el archivo preprocesado:main.s
contiene el ensamblaje generado deseado:Si desea hacerlo para una gran cantidad de archivos, considere usar en su lugar:
que guarda los archivos intermedios en el mismo directorio que la
-o
salida del objeto en lugar del directorio de trabajo actual, evitando así posibles conflictos de nombres básicos.Otra cosa interesante de esta opción es si agrega
-v
:En realidad, muestra los archivos explícitos que se utilizan en lugar de los temporales feos debajo
/tmp
, por lo que es fácil saber exactamente lo que está sucediendo, lo que incluye los pasos de preprocesamiento / compilación / ensamblaje:Probado en Ubuntu 19.04 amd64, GCC 8.3.0.
fuente
Use la opción -S:
fuente
De: http://www.delorie.com/djgpp/v2faq/faq8_20.html
gcc -c -g -Wa, -a, -ad [otras opciones de CCG] foo.c> foo.lst
en alternativa a la respuesta de PhirePhly O simplemente use -S como todos decían.
fuente
Estos son los pasos para ver / imprimir el código de ensamblaje de cualquier programa C en su Windows
consola / terminal / símbolo del sistema:
Escriba un programa C en un editor de código C como bloques de código y guárdelo con una extensión .c
Compilar y ejecutarlo.
Una vez ejecutado con éxito, vaya a la carpeta donde ha instalado su compilador gcc y proporcione el
siguiente comando para obtener un archivo '.s' del archivo '.c'
C: \ gcc> gcc -S ruta completa del archivo C ENTER
Un comando de ejemplo (como en mi caso)
C: \ gcc> gcc -SD: \ Aa_C_Certified \ alternate_letters.c
Esto genera un archivo '.s' del archivo '.c' original
4) Después de esto, escriba el siguiente comando
C; \ gcc> cpp filename.s ENTER
Comando de ejemplo (como en mi caso)
C; \ gcc> cpp alternate_letters.s
Esto imprimirá / imprimirá todo el código del lenguaje ensamblador de su programa en C.
fuente
Use "-S" como una opción. Muestra la salida del ensamblaje en la terminal.
fuente
gcc foo.c -masm=intel -fverbose-asm -O3 -S -o- |less
.-S
por sí mismo creafoo.s
.Recientemente quería saber el ensamblaje de cada función en un programa,
así es como lo hice.
fuente
Aquí hay una solución para C usando gcc:
Aquí la primera parte almacena la salida del ensamblaje del programa en el mismo nombre de archivo que el Programa pero con una extensión .s modificada , puede abrirlo como cualquier archivo de texto normal.
La segunda parte aquí compila su programa para el uso real y genera un ejecutable para su programa con un nombre de archivo especificado.
El program.c utilizado anteriormente es el nombre de su programa y la salida es el nombre del ejecutable que desea generar.
Por cierto, es mi primera publicación en StackOverFlow: -}
fuente