在GNU ARM汇编程序中,如果我们想定义一个浮点数,那么可以使用下面的伪操作来定义。
标签,命令
f:
.float 3.14
.equ f,3.1415
我们可以使用.float 伪操作定义一个浮点数f, 并初始化为3.14 如果你想将这个浮点数重新赋值为3.1415,则可以通过.equ 伪操作来完成。
.equ 伪操作除了给数据赋值,还可以把常量定义在代码段中,然后在代码中直接引用,这一点有点类似C语言中的#define 宏定义。
.section .data
.equ DELAY,100
...
.section .text
...
MOV R0,$DELAY
3.7.7 汇编代码分析实战
有了GNU ARM汇编语言的基础之后,接下来我们做一个实验,在linux环境下编写一个C程序,使用ARM交叉编译器将其编译为汇编文件,然后利用本节所学的知识分析汇编文件的组织结构。
C程序源码如下
hello.c
#include <stdio.h>
int global_val = 10;
int global_uvar;
int add(int a, int b)
{
return a + b;
}
int main(void)
{
int sum;
sum = add(1, 2);
printf("hello world\n");
return 0;
}
接下来我们将这个hello.c 源文件编译为汇编程序文件,并对其进行分析。
cat hello.s
.arch armvST ;//指令集版本
.fpu softvfp;//付点类型
.eabi_attribute,20,1 ;EABI 接口属性
.eabi_attribute,21,1 ;
.eabi_attribute,23,1 ;
.eabi_attribute,24,1 ;
.eabi_attribute,25,1 ;
.eabi_attribute,26,2 ;
.eabi_attribute,30,6 ;
.eabi_attribute,34,0 ;
.eabi_attribute,18,4 ;
.file "hello.c" ;当前汇编文件对应的文件名
.global global_val 声明一个全局符号,声明后其他文件可以引用
.data 声明一个数据段
.align 2 数据段对齐方式,2的2次方,即4字节对齐
.type global_val, %object 设置全局符号的类型为变量
.size global_val, 4 设置全局符号的大小为4字节。
global_val:
.word 10 ;为global_val 分配一个字大小的存储空间,初始化为10
.comm global_uvar,4,4 在.comm 临时段中申请一段命名空间
.text 代码段起始地址
.align 2 代码段对齐方式,2的2次方,即4字节对齐
.global add 声明一个全局符号,add
.syntax unified
.arm 当前代码指令为ARM指令
.type add, %function 设置符号add的类型为函数
add:
@args = 0,pretend = 0, frame = 0注释
@frame needed = 1, uses_anonymous_args = 0
@ link register save elimitnated
str fp, [sp, #-4]f
add fp, sp, #0
sub sp, sp, #12
str r0, [fp, #-8]
str r1, {fp, #-12}
ldr r2, [fp, #-8]
ldr r3, [fp, #-12]
add r3, r2, r3
mov r0, r3
sub sp, fp, #0
@sp needed
ldr fp, [sp], #4
bx lr
.size add , -add 函数大小 --当前地址(函数结束地址)-add函数开始地址
.section .rodata 定义一个新的section .rodata 只读数据段
.align 2 只读数据对齐方式,2字节对齐
.LC0
.ascli "hello world\n" 定义一个字符串
.text //新的代码段开始地址
.global main 声明一个全局符号,main
.syntax unifield
.arm
.type main, %function 将全局符号main的类型设置为函数
main:
#args 0, pretend = 0 frame = 0
#frame_needed = 1, uses_anonymous_args = 0;
push {fp, lr}
add fp, sp, #4
sub sp, sp, #8
mov, r1, #2
mov r0, #1
bl add
str r0, {fp, #-8}
ldr r0, LS
bl puts
mov r3, #0
mov r0, r3
sub sp, fp, #4
@sp needed
pop {fp, pc}
.L6
.align 2
.LS
.word .LC0 分配内存,用来存放printf 要打印的字符串地址, .LC0
.size main, -main 设置main函数大小=当前地址,-main开始地址
.ldent "GCC"
.section .note.GNU-stack