我们知道机器级代码的形式是0,1(二进制)。现在,在c语言编程中,使用gcc编写一个程序,如果cmd是--。
gcc -c ok.c
其中,ok.c是一个简单的程序,在c中打印 "hi".现在,创建了一个ok.o文件,这个文件应该是机器级别的指令。
^@^L^@UH��H�=^@^@^@^@�^@^@^@^@�^@^@^@^@�]�hi^@^@GCC: (Debian 9.3.0-10) 9.3.0^@^@^@^@^@^@^@^@^T^@^@^@^@^@^@^@^AzR^@^Ax^P^A^[^L^G^H�^A^@^@^\^@^@^@^\^@^@^@^@^@^@^@^X^@^@^@^@A^N^P�^BC
^FS^L^G^H^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^D^@��^@^@^@^@^@^@^@^@^@^
这个输出是什么意思,如果这是机器级的指令,那么为什么它不是以二进制数字(0,1)的形式,即1000110111111010101......(类似的东西),而且我怎么能看到二进制的那种代码?请,也纠正我,如果我错了的地方.谢谢。
你可以这样做来生成一个汇编文件(ok.s)。
gcc -S ok.c
ok.s文件是一个人类可读的文本文件(就像你的.c文件)。它将是一个机器指令的列表。这就是人类如何 "查看 "机器代码。
关于这些指令的更多信息,请参见:https:/en.wikipedia.orgwikiX86_assembly_language(汇编语言)
当你查看你的二进制.o文件时,你是把它看成文本(其中8个(或更多)二进制位将根据它们的值形成一个人类可查看的字符,这就是为什么它看起来像一堆随机字符。
给定一个简单的C程序,如
#include <stdio.h>
int main( void )
{
printf( "This is a test\n" );
return 0;
}
如果你想看实际 机器码 (不只是汇编器,还有实际的操作码和操作数),你有几个选择。
gcc -o simple -std=c11 -pedantic -Wall -Werror simple.c
然后使用... objdump
命令与 -d
选项 (objdump -d simple
),你会得到一个类似于这样的列表。00000000004004c7 <main>:
4004c7: 55 push %rbp
4004c8: 48 89 e5 mov %rsp,%rbp
4004cb: bf 60 05 40 00 mov $0x400560,%edi
4004d0: e8 1b ff ff ff callq 4003f0
4004d5: b8 00 00 00 00 mov $0x0,%eax
4004da: 5d pop %rbp
4004db: c3 retq
4004dc: 0f 1f 40 00 nopl 0x0(%rax)
^ ^ ^
| | |
| | +---- assembler
| +---------------------------- machine code
+-------------------------------------- instruction address
-Wa,-aldh=listing-file
选项来生成一个汇编和机器代码的列表。gcc -o simple -std=c11 -pedantic -Wall -Werror -Wa,-aldh=simple.lst simple.c
选项将创建一个类似于这样的列表文件。GAS LISTING /tmp/ccAMmy8W.s page 1
1 .file "simple.c"
2 .text
3 .section .rodata
4 .LC0:
5 0000 54686973 .string "This is a test"
5 20697320
5 61207465
5 737400
6 .text
7 .globl main
9 main:
10 .LFB0:
11 .cfi_startproc
12 0000 55 pushq %rbp
13 .cfi_def_cfa_offset 16
14 .cfi_offset 6, -16
15 0001 4889E5 movq %rsp, %rbp
16 .cfi_def_cfa_register 6
17 0004 BF000000 movl $.LC0, %edi
17 00
18 0009 E8000000 call puts
18 00
19 000e B8000000 movl $0, %eax
19 00
20 0013 5D popq %rbp
21 .cfi_def_cfa 7, 8
22 0014 C3 ret
23 .cfi_endproc
24 .LFE0:
26 .ident "GCC: (GNU) 7.3.1 20180712 (Red Hat 7.3.1-6)"
27 .section .note.GNU-stack,"",@progbits
^ ^ ^ ^
| | | |
| | | +---- assembler
| | +------------------ machine code
| +----------------------- instruction offset
+-------------------------- instruction number
如果你使用 -g
选项,你将得到与生成的输出交错的原始源代码。GAS LISTING /tmp/ccJ7L1rJ.s page 1
1 .file "simple.c"
2 .text
3 .Ltext0:
4 .section .rodata
5 .LC0:
6 0000 54686973 .string "This is a test"
6 20697320
6 61207465
6 737400
7 .text
8 .globl main
10 main:
11 .LFB0:
12 .file 1 "simple.c"
1:simple.c **** #include <stdio.h>
2:simple.c ****
3:simple.c **** int main( void )
4:simple.c **** {
13 .loc 1 4 0
14 .cfi_startproc
15 0000 55 pushq %rbp
16 .cfi_def_cfa_offset 16
17 .cfi_offset 6, -16
18 0001 4889E5 movq %rsp, %rbp
19 .cfi_def_cfa_register 6
5:simple.c **** printf( "This is a test\n" );
20 .loc 1 5 0
21 0004 BF000000 movl $.LC0, %edi
21 00
22 0009 E8000000 call puts
22 00
6:simple.c **** return 0;
23 .loc 1 6 0
24 000e B8000000 movl $0, %eax
24 00
7:simple.c **** }
25 .loc 1 7 0
26 0013 5D popq %rbp
27 .cfi_def_cfa 7, 8
28 0014 C3 ret
29 .cfi_endproc
30 .LFE0:
32 .Letext0:
33 .file 2 "/usr/lib/gcc/x86_64-redhat-linux/7/include/stddef.h"
34 .file 3 "/usr/include/bits/types.h"
35 .file 4 "/usr/include/libio.h"
36 .file 5 "/usr/include/stdio.h"