1.1 如果在命令行下执行 gcc -DNEG -E sample.c -o sample.i 生成的 sample.i 与之前的有何区别?
-D
定义了NEG
变量,因此在预处理时,M
将被替换为-4,而不加-DNEG
,M
将赋值为4。
1.2 请对比 sample-32.s 和 sample.s ,找出它们的区别,并上网检索给出产生这些区别的原因。如:
pushq 和 pushl
pushl
与pushq
的区别在于操作的位数不同,具体来说pushl
压入一个双字的长度即32位,而pushq
压入一个四字的长度即64位。在32位系统中,ebp
为32位,而在64位系统中,rbp
为64位。
补充:
- pushb:压入一个 byte(8 位)
- pushw:压入一个 word(16 位)
- pushl:压入一个 long(32 位)
- pushq:压入一个 quadword(64 位)
rsp 和 esp
- 他们都是栈顶指针
esp
为32位栈顶指针rsp
为64位栈顶指针
1.3 你可以用 clang 替换 gcc ,重复上面的各步,比较使用 clang 和 gcc 分别输出的结果有何异同。【本题可选】
GCC的输出如下:
点击查看GCC生成的sample.s
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
.file "sample.c" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $4, -4(%rbp) cmpl $0, -4(%rbp) je .L2 addl $4, -4(%rbp) jmp .L3 .L2: sall $2, -4(%rbp) .L3: movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits
clang的输出如下:
点击查看clang生成的sample-clang.s
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
.text .file "sample.c" .globl main # -- Begin function main .p2align 4, 0x90 .type main,@function main: # @main .cfi_startproc # %bb.0: pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset %rbp, -16 movq %rsp, %rbp .cfi_def_cfa_register %rbp movl $0, -4(%rbp) movl $4, -8(%rbp) cmpl $0, -8(%rbp) je .LBB0_2 # %bb.1: movl -8(%rbp), %eax addl $4, %eax movl %eax, -8(%rbp) jmp .LBB0_3 .LBB0_2: movl -8(%rbp), %eax shll $2, %eax movl %eax, -8(%rbp) .LBB0_3: xorl %eax, %eax popq %rbp retq .Lfunc_end0: .size main, .Lfunc_end0-main .cfi_endproc # -- End function .ident "clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)" .section ".note.GNU-stack","",@progbits