实验3-2 查找最大数
编写汇编代码
参考指导书,编写实现查找最大数功能的汇编代码,将我学号后四位1218作为最大数
.section .data
.align 3
my_data:
.quad 1
.quad 2
.quad 5
.quad 1218
.quad 10
.quad 12
my_data_count:
.quad 6
.align 3
print_data:
.string "big data: %d
"
.section .text
.globl main
main:
stp x29, x30, [sp, -16]!
ldr x0, =my_data
ldr x1, my_data_count
add x4, x0, #40
mov x3, xzr
1:
ldr x2, [x0], #8
cmp x2, x3
csel x3, x2, x3, hi
cmp x0, x4
b.ls 1b
ldr x0, =print_data
mov x1, x3
bl printf
ldp x29, x30, [sp], 16
ret
编译运行
汇编代码
上学期我们在计算机组成原理课上曾学习过MIPS架构,再结合这学期在ARM架构的树莓派上实践,总结MIPS和ARM有如下区别:
- MIPS指令很简单,格式很规整,就可以做很快(频率很高)。这符合RISC的初衷,但是功耗可能会比较大些(和频率有关),然后编译生成的代码很长(你不得不用大一点的Cache )。
- ARM指令很复杂,而且电路实现起来会比精简的指令相对复杂,当面积和功耗优先级高时,最高运行频率可能不会太高。
下面使用gcc maxnum.s -o maxnum -g --static
进行编译,运行结果如下
成功找出最大数
使用gdb单步调试汇编程序
发现OpenEuler操作系统并没有安装gdb,于是sudo yum install gdb
使用gdb --tui ./maxnum
来进行调试。
使用b main
在主函数设置断点
使用run
使用n
和s
单步执行
使用info reg xn
查看寄存器的值
实验3-3 通过C语言调用汇编函数
编辑两个代码文件:
第一个是arm汇编代码文件compare.s:
.section .text
.globl compare_data
compare_data:
cmp x0, x1
csel x0, x0, x1, hi
ret
第二个是包含主函数的C代码文件:main.c:
#include <stdio.h>
extern int compare_data(int a, int b);
int main()
{
int val;
val = compare_data(1218,1111);
printf("bigger data is:%d
",val);
}
使用gcc compare.s main.c -o compare
编译
实验3-4 通过汇编语言调用C函数
和实验3-3类似,相当于反过来,比较函数用C写的,主函数用汇编写
compare.c:
int compare_data(int a, int b)
{
return (a >= b) ? a : b;
}
main.s
.section .data
.align 3
print_data:
.string "bigger data is:%d
"
.section .text
.globl main
main:
stp x29, x30, [sp, -16]!
mov x0, #6
mov x1, #5
bl compare_data
mov x1, x0
ldr x0, =print_data
mov x1, x0
ldr x0, =print_data
bl printf
ldp x29, x30, [sp], 16
ret
运行结果如下
实验3-5 gcc内联汇编
内联汇编编译即在C代码中嵌入汇编代码
测试代码test.c如下:
#include <stdio.h>
static int compare_data(int a, int b)
{
int val;
asm volatile(
"cmp %1, %2
"
"csel %0, %1, %2, hi
"
: "+r" (val)
: "r" (a), "r"(b)
: "memory");
return val;
}
int main()
{
int val;
val = compare_data(5,6);
printf("big data: %d
", val);
val = compare_data(1111,1218);
printf("big data: %d
", val);
}
运行结果