ARM汇编判断之如何用汇编判断数组中正负数个数

目录
  • 【ARM汇编】如何判断数组中正负数个数?
    • 写在前面:
    • 所有判断后缀
  • 如何用汇编实现判断数组中正负数的个数?
  • 1.编前准备
    • 1.1用C的伪代码表示
    • 1.2参照正向遍历的框架
  • 2.编写ARM汇编
    • 2.1先给定一串数组、输出格式
    • 2.2在循环中加入判断、计数
    • 2.3在主函数中初始化使用的寄存器
    • 2.4输出累计之和
    • 2.5源代码
    • 2.6运行结果
  • 3.总结

【ARM汇编】如何判断数组中正负数个数?

写在前面:

在很多算法中都必须要用到if语句进行判断,前面我们提到了数组,也练习了用汇编的循环框架遍历数组,但当我们运用数组时,不可能仅仅用于遍历数组并求出数组的和。当我们对数组进行其他的一些操作时,就需要用到判断语句,那汇编中的判断语句是什么呢?

所有判断后缀

在x86中我们只能在跳转指令`“B”`后加上判断符,而在ARM中我们可以在任意指令后加上判断标识

所有的判断后缀,我把常用的给做了标红:

来看看今天的问题

如何用汇编实现判断数组中正负数的个数?

在汇编语言中程序的基本框架是不变的,我们之前写过循环的框架,这里我们可以直接把正向遍历的程序给贴过来,然后我们思考怎么运用判断后缀把数组中正数和负数分开,进行判断个数和分别求和。

1.编前准备

1.1用C的伪代码表示

先用C语言来实现这个功能,便于明确要实现功能的思路

C语言代码:

#include<stdio.h>
int main(){
    int ary[10] = {0,-1,2,3,4,5,-6,7,8,9};
    int sum1=0,sum2=0, i;
    int z=0,f=0;
    for ( i = 0; i < 10; i++)
    {
       	if(ary[i]>0){
       		z=z+1;
       		sum1 =sum1 +ary[i];
		   }
		else if(ary[i]<0){
			f=f+1;
			sum2 =sum2 +ary[i];
		   }
    }
    printf("正数的个数为:%d\n负数的个数为:%d\n",z,f);
    printf("正数的和为:%d\n负数的和为:%d\n",sum1,sum2);
    return 0;
}

运行结果:

1.2参照正向遍历的框架

学习任何东西最快速的办法是,调取大脑中已有的知识,让新知识跟旧知识进行对比和延伸思考。

把正向遍历的程序贴过来,发现实现整体功能的框架基本不变,只需要把循环中的这一部分操作改一下即可。把步骤拆开,详细细分为下面几步,我们一起来看一下。

2.编写ARM汇编

2.1先给定一串数组、输出格式

这里要尝试输出正数的个数、负数的个数以及正数之和、负数之和;数组用ary自定义;通过地址长度计算出要循环的次数

.data
    fmt1:.asciz " The number of positive:%d\n The number of negative:%d\n"
    fmt2:.asciz " The positive and:%d\n The negative and:%d\n"
    ary:.word 0,-1,2,3,4,-5,6,7,8,-9
    .equ counter,( . - ary)/4

2.2在循环中加入判断、计数

这一步就是核心步骤,用汇编写if判断语句。之前给出过所有的指令,其中CMP用来判断。与CMP紧密联系在一块的就是加判断后缀的指令,这个指令可以是跳转(B)可以是(ADD)也可以是(MOV)。

要实现的功能:把数组中的第一个值取出来,然后与零进行判断,当大于零时,给正数的计数器加一,并且给正数的累加和加上当前数值。判断为负数时则相反。

ARM汇编实现方法:

    ldr r2,[r5],#4
        cmp r2,#0
        addgt r7,#1
        addgt r9,r2
        addlt r8,#1
        addlt r10,r2

如果在x86中只能是CMP比较完用BLT跳转到子程序,执行完再跳转回来,ARM对于判断就方便很多,可以直接加在想要比较后想要执行的语句上。并且只需要一次比较。后面可以跟很多个,比较后想要执行的代码。

2.3在主函数中初始化使用的寄存器

一般定义寄存器都是在完成核心代码之后,查看核心代码中用到了哪些寄存器,然后给对应的寄存器赋初始值

这里的寄存器分别表示:

r7用来存放正数的个数

r8用来存放负数的个数

r9用来存放正数之和

r10用来存放负数之和

这里用到的R4和R5和之前一样没有变化依旧是:循环变量和数组首地址

 mov r4,#0
    mov r7,#0
    mov r8,#0
    mov r9,#0
    mov r10,#0
    ldr r5, =ary

2.4输出累计之和

  1. 想要打印输出肯定是用到printf,那就得先调用输出的格式串,格式串在最开始就已经定义好。
  2. printf是从R1开始输出的所以要把我们需要的值正负数个数、正负数和,传递给R1、R2。
  3. 下面部分由于已经打印出来,所以就可以把R1、R2覆盖,并且当用B跳转一次,R0~R3的值都会变化,最好都要重写。
ldr r0,=fmt1
        mov r1,r7
        mov r2,r8
        bl printf

        ldr r0,=fmt2
        mov r1,r9
        mov r2,r10
        bl printf

2.5源代码

.data
    fmt1:.asciz " The number of positive:%d\n The number of negative:%d\n"
    fmt2:.asciz " The positive and:%d\n The negative and:%d\n"
    ary:.word 0,-1,2,3,4,-5,6,7,8,-9
    .equ counter,( . - ary)/4
.text
.globl main
 main:
    stmfd sp!,{lr}
    mov r4,#0
    mov r7,#0
    mov r8,#0
    mov r9,#0
    mov r10,#0
    ldr r5, =ary

    b testfor
loop:
        ldr r2,[r5],#4
        cmp r2,#0
        addgt r7,#1
        addgt r9,r2
        addlt r8,#1
        addlt r10,r2

        add r4,#1
testfor:cmp r4,#counter
        blt loop

        ldr r0,=fmt1
        mov r1,r7
        mov r2,r8
        bl printf
        ldr r0,=fmt2
        mov r1,r9
        mov r2,r10
    mov r0, #0
    ldmfd sp!,{lr}
    mov pc, lr
.end

这里我们值需要判断正负计数即可,因为零既不属于正数也不属于负数

2.6运行结果

可以看到结果是正确的!

3.总结

  • 对给定数组进行操作时,要把操作放入循环中,并且通过寄存器向后寻址的方式循环。
  • 给出了所有的判断后缀,在ARM中可以把判断后缀放到任意的指令后,用于判断后的执行操作;一条CMP指令可以跟很多条判断执行操作。
  • 编写汇编时,先写出核心代码部分,再给主函数、全局变量、输出语句中添加支撑条件。

到此这篇关于ARM汇编判断之如何用汇编判断数组中正负数个数的文章就介绍到这了,更多相关汇编判断正负数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • ARM汇编解决阶乘及大小写转换的问题

    环境以及硬件 一.硬件仿真基于 SAMSUNG's S3C44B0X 16/32-bit RISC microprocessor 芯片,仿真器为 J-LINK 二.编写指令软件为 Integrated Development Environment ,软件仿真为 ARMulate.dll 三.需要基于ARM7硬件平台的C语言启动代码,用于分配中断向量表,初始化ISR地址,初始化堆栈空间,初始化应用程序执行环境,配置存储器系统,设定时钟周期,呼叫主应用程序. 四.这里仅有关键算法代码 ARM汇编求

  • 浅析ARMv8汇编指令adrp和adr

    目录 1.概述 2.adrp 2.1.定义 2.2.测试 3.adr 3.1.定义 3.2.测试 参考资料 1.概述 在阅读Linux内核代码时,经常能碰到汇编代码,网上能查的资料千篇一律,大多都描述的很模糊.俗话说,实践是检验真理的唯一标准,我们就参考官方文档,自己写汇编代码并反汇编,探寻其中的奥妙. 2.adrp 在Linux内核启动代码primary_entry中,使用adrp指令获取Linux内核在内存中的起始页地址,页大小为4KB,由于内核启动的时候MMU还未打开,此时获取的Linux

  • ARM体系下的GCC内联汇编教程详解

    在操作系统级的编程中,有时候,C语言并不能完全的使用硬件的功能,这时候就需要嵌入一些汇编代码来实现功能. 有两种方式可以使C语言和assemly语言一起工作,一种是两种语言分开写成两个文件,链接的时候链接成一个文件;另一种就是在C语言中嵌入汇编代码.下面简单介绍一下如何在GCC中嵌入汇编代码. GCC规定了一个内联汇编的语法,不同硬件平台上的GCC内联汇编几乎都是这样的: asm( 汇编指令列表 :输出运算符列表 :输入运算符列表 :被更改的资源列表 }; 在GCC中插入汇编代码,需要以asm关

  • ARM汇编判断之如何用汇编判断数组中正负数个数

    目录 [ARM汇编]如何判断数组中正负数个数? 写在前面: 所有判断后缀 如何用汇编实现判断数组中正负数的个数? 1.编前准备 1.1用C的伪代码表示 1.2参照正向遍历的框架 2.编写ARM汇编 2.1先给定一串数组.输出格式 2.2在循环中加入判断.计数 2.3在主函数中初始化使用的寄存器 2.4输出累计之和 2.5源代码 2.6运行结果 3.总结 [ARM汇编]如何判断数组中正负数个数? 写在前面: 在很多算法中都必须要用到if语句进行判断,前面我们提到了数组,也练习了用汇编的循环框架遍历

  • JS 判断某变量是否为某数组中的一个值的3种方法(总结)

    1.正则表达式 js 中判断某个元素是否存在于某个 js 数组中,相当于 PHP 语言中的 in_array 函数. Array.prototype.in_array=function(e){ var r=new RegExp(','+e+','); return (r.test(','+this.join(this.S)+','));}; 用法如下: var arr=new Array(['b',2,'a',4]); arr.in_array('b');//判断'b'字符是否存在于 arr 数

  • Java中高效的判断数组中某个元素是否存在详解

    一.检查数组是否包含某个值的方法 使用List public static boolean useList(String[] arr, String targetValue) { return Arrays.asList(arr).contains(targetValue); } 使用Set public static boolean useSet(String[] arr, String targetValue) { Set<String> set = new HashSet<Stri

  • C语言中判断两数组中是否有相同的元素

    思路: 首先创建两个数组,分别为a[ ]和b[ ]先拿a数组里的第一个元素和b数组的所有元素比较是否相同,再拿a数组里的第二个元素与b数组所有元素进行比较,以此类推.运用两次for循环来完成,用i循环生成a数组的各个下标,在循环体中用j循环生成b数组下标,j循环中判断a[ i ]是否等于b[ j ],如果条件成立即相同元素.flag用来标记程序运行到某一刻的状态,来加以判断if中的语句是否执行. system函数的作用是运行以字符串参数的形式传递给他的命令,并且等待该命令的完成,形式:#incl

  • Java中高效判断数组中是否包含某个元素的几种方法

    目录 检查数组是否包含某个值的方法 使用List 使用Set 使用循环判断 使用Arrays.binarySearch() 时间复杂度 使用一个长度为1k的数组 使用一个长度为10k的数组 总结 补充 使用ArrayUtils 完整测试代码 长字符串数据 如何检查一个数组(无序)是否包含一个特定的值?这是一个在Java中经常用到的并且非常有用的操作.同时,这个问题在Stack Overflow中也是一个非常热门的问题.在投票比较高的几个答案中给出了几种不同的方法,但是他们的时间复杂度也是各不相同

  • 如何用Go判断元素是否在切片中

    目录 1.问题 2.遍历查询 3.map 查询 4.性能对比 5.转换通用化 6.借助开源库 golang-set 7.小结 参考文献 1.问题 如何判断元素是否在切片中,Golang 并没有提供直接的库函数来判断,最容易想到的实现便是通过遍历来判断. 2.遍历查询 以字符串切片为例,判断字符串切片中是否包含某个字符串. // InSlice 判断字符串是否在 slice 中. func InSlice(items []string, item string) bool { for _, eac

  • iOS汇编入门教程之ARM64汇编基础教程

    前言 对于应用层开发人员而言,仅仅掌握Objective-C和系统框架即可较好的完成开发,但在涉及到应用加固.逆向分析等内容时仅有应用层开发技能就会显得非常的无力,因此掌握汇编对于突破iOS开发水平的瓶颈十分有效. 一个例子 以反调试为例,我们知道,通过调用ptrace函数可以阻止调试器依附. ptrace(31, 0, 0, 0) 这种方式能够被函数hook轻易破解,例如使用facebook的fishhook.为了防止函数被hook,我们可以将函数调用转为通过汇编发起系统调用,即使用下面的代码

  • Nginx中if语句的判断条件与多条件判断详解

    一.if语句中的判断条件(nginx)介绍 1.正则表达式匹配: ==:等值比较; ~:与指定正则表达式模式匹配时返回"真",判断匹配与否时区分字符大小写: ~*:与指定正则表达式模式匹配时返回"真",判断匹配与否时不区分字符大小写: !~:与指定正则表达式模式不匹配时返回"真",判断匹配与否时区分字符大小写: !~*:与指定正则表达式模式不匹配时返回"真",判断匹配与否时不区分字符大小写: 2.文件及目录匹配判断: -f,

  • jQuery 判断是否包含在数组中Array[]的方法

    jQuery 判断是否包含在数组中Array[]的方法 var Menustr="1,2,3,4,5,6,7,8,9,10,11,12,"; var Menarrstr=Menustr.split(","); if ($.inArray($(this).attr("id"), Menarrstr)) { //... } 以上这篇jQuery 判断是否包含在数组中Array[]的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多

  • IOS开发之判断两个数组中数据是否相同实例详解

    IOS开发之判断两个数组中数据是否相同实例详解 前言: 工作中遇到的问题,这里记录下,也许能帮助到大家 实例代码: NSArray *array1 = [NSArray arrayWithObjects:@"a", @"b", @"c", nil nil]; NSArray *array2 = [NSArray arrayWithObjects:@"b", @"a", @"c", nil

随机推荐