1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 一个简单的C语言程序代码演示GCC的编译

一个简单的C语言程序代码演示GCC的编译

时间:2024-04-02 09:46:00

相关推荐

一个简单的C语言程序代码演示GCC的编译

实验1:GCC编译

1.实验目的

1)熟悉GCC的编译过程,学会使用ARM GCC交叉工具链编译应用程序并放入QEMU上运行。

2)学会写简单的Makefile。

2.实验详解

本实验通过一个简单的C语言程序代码演示GCC的编译过程。下面是一个简单的test.c的程序代码。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define PAGE_SIZE 4096

#define MAX_SIZE 100*PAGE_SIZE

int main()

{

char *buf = (char *)malloc(MAX_SIZE);

memset(buf, 0, MAX_SIZE);

printf("buffer address=0x%p", buf);

free(buf);

return 0;

}

1)预处理。

GCC的“-E”选项可以让编译器在预处理阶段就结束,选项“-o”可以指定输出的文件格式。

arm-linux-gnueabi-gcc -E test.c -o test.i

预处理阶段会把C标准库的头文件中的代码包含到这段程序中。test.i文件的内容如下所示。

extern void *malloc (size_t __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;

int main()

{

char *buf = (char *)malloc(100*4096);

memset(buf, 0, 100*4096);

printf("buffer address=0x%p", buf);

free(buf);

return 0;

}

2)编译。

编译阶段主要是对预处理好的.i文件进行编译,并生成汇编代码。GCC首先检查代码是否有语法错误等,然后把代码编译成汇编代码。我们这里使用“-S”选项来编译。

$ arm-linux-gnueabi-gcc -S test.i -o test.s

编译阶段生成的汇编代码如下。

.LC0:

.ascii "buffer address=0x%p"

.text

.align 2

.global main

.thumb

.thumb_func

.type main, %function

main:

@ args = 0, pretend = 0, frame = 8

@ frame_needed = 1, uses_anonymous_args = 0

push {r7, lr}

sub sp, sp, #8

add r7, sp, #0

mov r0, #409600

bl malloc

mov r3, r0

str r3, [r7, #4]

ldr r3, [r7, #4]

mov r2, r3

mov r3, #409600

mov r0, r2

mov r1, #0

mov r2, r3

bl memset

movw r3, #:lower16:.LC0

movt r3, #:upper16:.LC0

mov r0, r3

ldr r1, [r7, #4]

bl printf

ldr r0, [r7, #4]

bl free

mov r3, #0

mov r0, r3

add r7, r7, #8

mov sp, r7

pop {r7, pc}

.size main, .-main

.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"

.section .note.GNU-stack,"",%progbits

3)汇编。

汇编阶段是将汇编文件转化成二进制文件,利用“-c”选项就可以生成二进制文件。

$ arm-linux-gnueabi-gcc -c test.s -o test.o

4)链接。

链接阶段会对编译好的二进制文件进行链接,这里会默认链接C语言标准库(libc)。我们的代码里调用的malloc()、memset()以及printf()等函数都由C语言标准库提供,链接过程会把程序的目标文件和所需的库文件链接起来,最终生成可执行文件。

Linux的库文件分成两大类:一类是动态链接库(通常以.so结尾),另一类是静态链接库(通常以.a结尾)。在默认情况下,GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才使用静态链接库。下面使用“--static”来让test程序静态链接C语言标准库,原因是交叉工具链使用的libc的动态库和QEMU中使用的库可能不一样。如果使用动态链接,可能导致运行报错。

$ arm-linux-gnueabi-gcc test.o -o test --static

以ARM GCC交叉工具链为例,C函数库动态库的目录在/usr/arm-linux-gnueabi/lib里,最终的库文件是libc-2.23.so文件。

$ ls -l /usr/arm-linux-gnueabi/lib/libc.so.6

lrwxrwxrwx 1 root root 12 Apr 16 /usr/arm-linux-gnueabi/lib/libc.so.6 -> libc-2.23.so

C语言标准库的静态库地址如下。

$ ls -l /usr/arm-linux-gnueabi/lib/libc.a

-rw-r--r-- 1 root root 3175586 Apr 16 /usr/arm-linux-gnueabi/lib/libc.a

5)放到QEMU上运行。

把test程序放入runninglinuxkernel-4.0/kmodules目录里,启动QEMU并运行test程序。

/ # ./mnt/test

buffer address=0x0xb6f73008

/ #

6)编写一个简单的Makefile文件来编译。

cc = arm-linux-gnueabi-gcc

prom = test

obj = test.o

CFLAGS = -static

$(prom): $(obj)

$(cc) -o $(prom) $(obj) $(CFLAGS)

%.o: %.c

$(cc) -c $< -o $@

clean:

rm -rf $(obj) $(prom)

EDN

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。