参考文章:
如何在x64的Ubuntu系统下安装64bit的交叉编译工具aarch64-linux-gnu-gcc
1. 开发环境
1.1 运行操作系统为 ubuntu 16.04
1.2 qemu模拟器安装部署
不建议使用源码安装,虽然版本较新,但依赖库很多,会出现各种问题。可通过软件包管理器apt-get install qemu。但是此种安装后,在/usr/bin/目录下只有qemu-system-i386之类的命令工具,并无arm相关的工具,此时需要安装qemu-system-arm,执行命令apt-get install qemu-system。也就是默认安装Qemu是不支持ARM架构的。同时也需要安装qemu-arm,此工具可以直接运行ARM架构的二进制文件,而不必模拟整个SOC。执行命令apt-get install qemu-user。至此,Qemu基本工具都已安装完成,如下图,我们主要是以模拟ARM架构的设备为主。
2. 程序源代码
2.1 实现功能的pa1.c语言代码
/*
* pa1.c源文件
*/
#include <stdio.h>
#include <string.h>
#define N 100
int main()
{ char s[N];
char flag = 'F';
int i=0,j=0,k=0;
char *str;
printf("Input a String: \n");
//输入一个字符串赋值给s
scanf("%s",s);
str = s;
while(*str != '\0')
{
str++;
k++;
}
printf("String length: %d\n",k);
j = k -1;
//j的初始值为s字符串最后一个位置
// j=strlen(s)-1;
// printf("String length: %d\n",j+1);
//进行while判断i、j的位置和i、j位置的值的关系
while(i<=j&&s[i]==s[j]){
//每比较一次就i右移、j左移一位
i++;j--;
}
//判断最终i和j的的位置
//根据i、j的位置最终是会互相超越的,所以如果i<=j说明存在对应位置不等的情况就是不是回文串
if (i<=j)
{
flag = 'F';
printf("String is a palindrome (T/F): %c\n", flag);
// printf("不是回文字符串\n");
}
else
{
flag = 'T';
printf("String is a palindrome (T/F): %c\n", flag);
// printf("是回文字符串\n");
}
return 0;
}
2.2 实现功能的pa1.s 汇编代码
.section .data
input_prompt : .asciz "Input a string: "
input_spec : .asciz "%[^\n]"
length_spec : .asciz "String length: %d\n"
palindrome_spec : .asciz "String is a palindrome (T/F): %c\n"
.section .text
.global main
.arch armv8-a
.file "pa1.c"
.section .rodata
.align 3
.LC0:
.string "Input a String: "
.align 3
.LC1:
.string "%s"
.align 3
.LC2:
.string "String length: %d\n"
.align 3
.LC3:
.string "String is a palindrome (T/F): %c\n"
.text
.align 2
.global main
.type main, %function
main:
stp x29, x30, [sp, -160]!
add x29, sp, 0
adrp x0, __stack_chk_guard
add x0, x0, :lo12:__stack_chk_guard
ldr x1, [x0]
str x1, [x29, 152]
mov x1,0
mov w0, 70
strb w0, [x29, 27]
str wzr, [x29, 28]
str wzr, [x29, 32]
str wzr, [x29, 36]
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl puts
add x1, x29, 48
adrp x0, .LC1
add x0, x0, :lo12:.LC1
bl __isoc99_scanf
add x0, x29, 48
str x0, [x29, 40]
b .L2
.L3:
ldr x0, [x29, 40]
add x0, x0, 1
str x0, [x29, 40]
ldr w0, [x29, 36]
add w0, w0, 1
str w0, [x29, 36]
.L2:
ldr x0, [x29, 40]
ldrb w0, [x0]
cmp w0, 0
bne .L3
adrp x0, .LC2
add x0, x0, :lo12:.LC2
ldr w1, [x29, 36]
bl printf
ldr w0, [x29, 36]
sub w0, w0, #1
str w0, [x29, 32]
b .L4
.L6:
ldr w0, [x29, 28]
add w0, w0, 1
str w0, [x29, 28]
ldr w0, [x29, 32]
sub w0, w0, #1
str w0, [x29, 32]
.L4:
ldr w1, [x29, 28]
ldr w0, [x29, 32]
cmp w1, w0
bgt .L5
ldrsw x0, [x29, 28]
sub x1, x29, #3936
add x0, x1, x0
ldrb w1, [x0, 3984]
ldrsw x0, [x29, 32]
sub x2, x29, #3936
add x0, x2, x0
ldrb w0, [x0, 3984]
cmp w1, w0
beq .L6
.L5:
ldr w1, [x29, 28]
ldr w0, [x29, 32]
cmp w1, w0
bgt .L7
mov w0, 70
strb w0, [x29, 27]
ldrb w1, [x29, 27]
adrp x0, .LC3
add x0, x0, :lo12:.LC3
bl printf
b .L8
.L7:
mov w0, 84
strb w0, [x29, 27]
ldrb w1, [x29, 27]
adrp x0, .LC3
add x0, x0, :lo12:.LC3
bl printf
.L8:
mov w0, 0
adrp x1, __stack_chk_guard
add x1, x1, :lo12:__stack_chk_guard
ldr x2, [x29, 152]
ldr x1, [x1]
eor x1, x2, x1
cmp x1, 0
beq .L10
bl __stack_chk_fail
.L10:
ldp x29, x30, [sp], 160
ret
exit:
mov x0, 0
mov x8, 93
svc 0
ret
3 gcc命令编译源文件
3.1 显示pa1.c
的汇编代码
aarch64-linux-gnu-gcc -static -S -o pa1.s pa1.c
编译生成的 pa1.s 汇编代码如下:
.arch armv8-a
.file "pa1.c"
.section .rodata
.align 3
.LC0:
.string "Input a String: "
.align 3
.LC1:
.string "%s"
.align 3
.LC2:
.string "String length: %d\n"
.align 3
.LC3:
.string "String is a palindrome (T/F): %c\n"
.text
.align 2
.global main
.type main, %function
main:
stp x29, x30, [sp, -160]!
add x29, sp, 0
adrp x0, __stack_chk_guard
add x0, x0, :lo12:__stack_chk_guard
ldr x1, [x0]
str x1, [x29, 152]
mov x1,0
mov w0, 70
strb w0, [x29, 27]
str wzr, [x29, 28]
str wzr, [x29, 32]
str wzr, [x29, 36]
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl puts
add x1, x29, 48
adrp x0, .LC1
add x0, x0, :lo12:.LC1
bl __isoc99_scanf
add x0, x29, 48
str x0, [x29, 40]
b .L2
.L3:
ldr x0, [x29, 40]
add x0, x0, 1
str x0, [x29, 40]
ldr w0, [x29, 36]
add w0, w0, 1
str w0, [x29, 36]
.L2:
ldr x0, [x29, 40]
ldrb w0, [x0]
cmp w0, 0
bne .L3
adrp x0, .LC2
add x0, x0, :lo12:.LC2
ldr w1, [x29, 36]
bl printf
ldr w0, [x29, 36]
sub w0, w0, #1
str w0, [x29, 32]
b .L4
.L6:
ldr w0, [x29, 28]
add w0, w0, 1
str w0, [x29, 28]
ldr w0, [x29, 32]
sub w0, w0, #1
str w0, [x29, 32]
.L4:
ldr w1, [x29, 28]
ldr w0, [x29, 32]
cmp w1, w0
bgt .L5
ldrsw x0, [x29, 28]
sub x1, x29, #3936
add x0, x1, x0
ldrb w1, [x0, 3984]
ldrsw x0, [x29, 32]
sub x2, x29, #3936
add x0, x2, x0
ldrb w0, [x0, 3984]
cmp w1, w0
beq .L6
.L5:
ldr w1, [x29, 28]
ldr w0, [x29, 32]
cmp w1, w0
bgt .L7
mov w0, 70
strb w0, [x29, 27]
ldrb w1, [x29, 27]
adrp x0, .LC3
add x0, x0, :lo12:.LC3
bl printf
b .L8
.L7:
mov w0, 84
strb w0, [x29, 27]
ldrb w1, [x29, 27]
adrp x0, .LC3
add x0, x0, :lo12:.LC3
bl printf
.L8:
mov w0, 0
adrp x1, __stack_chk_guard
add x1, x1, :lo12:__stack_chk_guard
ldr x2, [x29, 152]
ldr x1, [x1]
eor x1, x2, x1
cmp x1, 0
beq .L10
bl __stack_chk_fail
.L10:
ldp x29, x30, [sp], 160
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
命令生成可执行文件 pa1
aarch64-linux-gnu-gcc -static -g -o pa1 pa1.s
可以看出是64-bit ARM aarch64 可执行文件,运行测试验证效果如下: