GNU的汇编器是GNU Tools的一部分,可以用来ARM的汇编语言源代码编译为二进制文件.关于GNU汇编器的介绍可以搜索《GNU Assembler Manual》.这里我们只是做一个简短的介绍,对GNU汇编器有一个大概的认识,同时通过两个例子了解一下GNU ARM汇编.

给出一个模板文件:

[cpp] view plaincopyprint?
  1. .text                                               ; Executable code follows
  2. _start: .global _start                                  ; "_start" is required by the linker
  3. .global main                                        ; "main" is our main program
  4. b main                                              ; Start running the main program
  5. main:                                                   ; Entry to the function "main"
  6. ; Insert your code here
  7. mov pc,lr                                           ; Return to the caller
  8. .end

汇编器的使用:

一种汇编器是arm-elf-as,一种是arm-linux-as之类的,这两种汇编器是有细微区别.但是一般做开发,半导体厂商都会提供特定的编译器,用那个编译器应该是没错的,而且优化效果应该是最优的,毕竟是芯片公司提供的嘛.他们对体系架构最了解,很清楚的知道怎么去优化.而我们一般的开发者也可以了解处理器的体系架构和嵌入式系统的系统的特征来对汇编代码和c代码做优化.

编译过程:

arm-elf-as -marm7tdmi --gdwarf2 -o filename.o filename.s

-marm7tdmi是指定CPU,arm7tdmi是属于ARMv4T的,一般来说同是ARMv4T应该是兼容的.

--gdwarf2是表示包含debug信息.

链接过程:

arm-elf-ld -o filename.elf filename.o

和UNIX系统编程一样,我们可以根据上面的步骤写makefile,然后make一下.

具体ARM的指令集,伪指令就不写了,资料很多.

下面举两个ARM汇编的实例,一个是裸机下的蜂鸣器(简单的控制GPIO而已,比流水灯还简单),一个是ARM linux下的"hello world"(利用系统调用来实现的).

蜂鸣器的例子如下:

beep.lds  beep.S  Makefile  start.S

start.S:

[cpp] view plaincopyprint?
  1. .text
  2. .global _start
  3. _start:
  4. ldr     r3, =0x53000000     @ WATCHDOG寄存器地址
  5. mov     r4, #0x0
  6. str   r4, [r3]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启
  7. ldr     sp, =1024*2         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
  8. @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
  9. bl      _main                @ 跳转到main函数
  10. halt_loop:
  11. b       halt_loop

beep.S

[cpp] view plaincopyprint?
  1. .equ    GPBCON,   0x56000010
  2. .equ    GPBDAT,   0x56000014
  3. .global _main
  4. _main:
  5. ldr r0,=GPBCON
  6. ldr r1,=0x1
  7. str r1, [r0]
  8. loop:
  9. ldr r2,=GPBDAT
  10. ldr r1,=0x1
  11. str r1,[r2]
  12. bl delay
  13. ldr r2,=GPBDAT
  14. ldr r1,=0x0
  15. str r1,[r2]
  16. bl delay
  17. b loop
  18. delay:
  19. ldr r3,=0x4ffffff
  20. delay1:
  21. sub r3,r3,#1
  22. cmp r3,#0x0
  23. bne delay1
  24. mov pc,lr
  25. .end

beep.lds

[cpp] view plaincopyprint?
  1. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  2. OUTPUT_ARCH(arm)
  3. ENTRY(_start)
  4. SECTIONS{
  5. . = 0x33000000;
  6. .text : {
  7. *(.text)
  8. *(.rodata)
  9. }
  10. .data ALIGN(4): {
  11. *(.data)
  12. }
  13. .bss ALIGN(4): {
  14. *(.bss)
  15. }
  16. }

makefile:

[cpp] view plaincopyprint?
  1. CROSS =  arm-linux-
  2. CFLAGS = -nostdlib
  3. beep.bin: start.S beep.S
  4. ${CROSS}gcc $(CFLAGS) -c -o start.o start.S
  5. ${CROSS}gcc $(CFLAGS) -c -o beep.o beep.S
  6. ${CROSS}ld -Tbeep.lds start.o beep.o -o beep.elf
  7. ${CROSS}objcopy -O binary -S beep.elf beep.bin
  8. rm -f  *.o
  9. clean:
  10. rm -f *.elf *.o
  11. rm -f beep.bin

编译后将beep.bin文件烧写到dram中,就可以听到声音了.虽然可以运行了,但还是有两个疑问:

1.lds编译链接文件的写法和技巧    //后续要继续追

2.elf文件的格式        //elf格式是比较新的可执行文件格式,目前在很多OS上都是用这种格式.这个格式可以在有操作系统的情况下直接运行,但是对于裸机的情况,必须对elf文件                                                做objcopy处理        后续也要继续追

hello world的例子如下:

helloworld.S:

[cpp] view plaincopyprint?
  1. .data
  2. msg:  .asciz  "hello, world\n"
  3. .text
  4. .align  2
  5. .global _start
  6. _start:
  7. ldr     r1, =msg         @ address
  8. mov     r0, #1          @ stdout
  9. mov     r2, #13         @ length
  10. swi     #0x900004       @ sys_write
  11. mov     r0, #0
  12. swi     #0x900001       @ sys_exit
  13. .align  2

makefile:

[cpp] view plaincopyprint?
  1. all:
  2. arm-linux-as helloworld.S -o helloworld.o
  3. arm-linux-ld  helloworld.o -o helloworld

将elf文件放到跑有linux的arm板子中,运行就输出hello world.也可以在ubuntu中qemu-arm helloworld模拟.

对比x86下同样用系统调用来输出hello world的程序:

[cpp] view plaincopyprint?
  1. .data
  2. msg: .string "hello\n"
  3. len = . - msg
  4. .text
  5. .global _start
  6. _start:
  7. nop
  8. movl $len, %edx
  9. movl $msg, %ecx
  10. movl $1, %ebx
  11. movl $4, %eax
  12. int $0x80
  13. movl $0, %ebx
  14. movl $1, %eax
  15. int $0x80

它们有几点不同:

1.arm是用swi指令来进行软中断,陷入内核态来实现系统调用的.而x86是用int $0x80

2.x86的系统调用号是用eax寄存器表示的,是第一个参数.而arm的swi直接带有系统调用号,0x900004是0x900000+4,其中0x900000是base.

根据google,做了上面的总结,对GNU ARM汇编有了认识,并且对系统调用软中断,中断处理,uboot异常向量表等等有了探究的欲望,也对elf格式和编译链接有了兴趣,根据自己的方向和精力,后续对这些内容做一个或深或浅的学习.

转载于:blog.csdn.net/dndxhej

转载于:https://www.cnblogs.com/Daniel-G/archive/2012/10/15/2725057.html

GNU ARM汇编--(二)汇编编译链接与运行相关推荐

  1. 【Android 逆向】Android 逆向通用工具开发 ( Windows 平台运行的控制台应用程序类型 | 编译 Windows 平台运行的 Android 逆向程序 )

    文章目录 一.Windows 平台运行的控制台应用程序类型 二.编译 Windows 平台运行的 Android 逆向程序 一.Windows 平台运行的控制台应用程序类型 hacktool 工程的类 ...

  2. GNU ARM汇编--(二十)总结

    从这个系列第一篇开始,那是4月22号,到今天做一个总结,已经有7个多月的时间了,利用业余时间学习自己感兴趣的东西,进度比较慢,也是比较累的,但收获也是很多的. 这个系列之所以写出来,是因为自己在玩li ...

  3. GNU ARM汇编伪操作(Directives) 命令集

    本文是原创,转载请注明出处 本文链接:http://blog.sina.com.cn/s/blog_574d08530100hzie.html 1.符号定义伪操作 操作符      语法格式      ...

  4. GNU ARM 汇编指令[转载]

    http://blog.sina.com.cn/s/blog_59b189220100au1k.html 第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C++编写程序很方便,但汇编源程 ...

  5. C语言编译链接生成可执行文件四大步骤:预处理(-E)->编译(-S)->汇编(-c) ->链接

    文章目录 一.编译过程简介 1.预处理器 2.编译器 3.汇编器 二.链接过程简介 1.静态链接: 由链接器在链接时将库的内容直接加入到可执行程序中 2.动态链接: 一.编译过程简介 编译过程可以分为 ...

  6. Linux程序在预处理、编译、汇编、链接、运行步骤的作用

    创建一个hello.c文件,按步骤操作: 一.预编译 <生成 hello.i文件 > 操作步骤:gcc -E hello.c -o hello.i 1.将所有的#define删除,并展开所 ...

  7. ARM学习-GNU ARM汇编

    目录 1.GNU汇编语言语句格式 2.汇编程序中的标号symbol(或label) 3.GNU汇编程序中的分段 3.1 .section伪操作 3.2 汇编系统预定义的段名 4.GNU汇编语言定义入口 ...

  8. linux arm 汇编学习,如何在LINUX平台上学习GNU ARM汇编

    本例说明如何在LINUX平台上学习GNU ARM汇编. 1.软件环境 vmware 5.0 + redhat 9.0 + skyeye 1.2.4 + arm-elf 工具 2. 源文件 a.s -- ...

  9. arm gnu linux系统,GNU ARM汇编

    在大学的时候,汇编就是学的很烂.一是对汇编这门语言没概念,二是那些指令集很难记清楚,用的机会也少,自然学的不好.但是现在觉得相当有必要重头学习一下汇编.部分原因我在上一篇写完设备模型的总结时提到了而. ...

最新文章

  1. java语言适合编写什么_01--Java语言概述与开发环境 最适合入门的Java教程
  2. 数据结构实验之栈与队列三:后缀式求值
  3. 全球及中国真空管太阳能集热器行业竞争状况及投资策略研究报告2021年版
  4. python多进程关闭socket_用Python制作一个多进程UDP服务器,一个进程监听一个p
  5. libnghttp2 NDK 交叉编译
  6. gdb pwndbg插件安装
  7. 收藏 | EfficientNet模型的完整细节
  8. mysql_数据查询_单表查询
  9. 计算一路话音消耗的带宽
  10. 什么是基金转换?转换费用如何收取?
  11. DVWA中学习PHP常见漏洞及修复方法
  12. 5款最佳Linux服务器系统推荐
  13. 基于开路电压+安时积分法估算锂电池SOC(二)
  14. python统计文章中高频词汇并生成词云
  15. 三大web服务器对比(lighttpd,apache,nginx)
  16. 【Windows内核编程】Win10/Win11通过PspCidTable取得EProcess
  17. XML完整教程和什么是XML语言
  18. 【渝粤题库】广东开放大学 税务会计技术 形成性考核
  19. Python爬虫从入门到精通:(41)JS逆向_RSA加密,Steam加密逆向_Python涛哥
  20. Promox VE 一款不错的开源虚拟化软件

热门文章

  1. 各种编程语言的深度学习库整理
  2. shell中$0,$?,$!等的特殊用法
  3. gearman python 实例
  4. Tomcat服务在Eclipse中能够正常启动,但页面出现404错误的解决方法
  5. 【Objective-C学习笔记】变量和基本的数据类型
  6. MySQL中删除重复数据
  7. Rhel7 Ldap为本地用户认证方式,设置域、服务器位置和下载key
  8. 适用于System Center 2016所需前期准备工作
  9. JavaScript 学习笔记3
  10. CodeIgniter开发实际案例-新闻网站【转】