ARM架构下在qemu模拟器中汇编实现:统计输入字符串长度并且判断是否回文

参考文章:

在Ubuntu中安装Qemu模拟ARM架构                    

objdump(Linux)反汇编命令使用指南

如何在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 可执行文件,运行测试验证效果如下:

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值