常用汇编

汇编只不过是机器代码的美化宏语言。 汇编指令与实际机器代码之间存在一对一的关系,汇编使用助记符来处理器所能够运行的操作,这比原始二进制文件更容易记忆。 将asm代码Assembly Code转换为机器代码的工具是汇编程序。

每个处理器都会进行的操作:算术(加减乘除),位操作
每个处理器都会有的能力:访问内存内存跳转
但是每个处理器,都有不同的方法来做这些工作

ARM没有除法指令、并且不能在内存上直接处理数据
但是,ARM有大量通用寄存器简单指令集,还有优秀的处理位转移方式

add r0, r0, #2    //加立即数,r0 +=  2
add r0, r0, r1    //加寄存器,r0 += r1
add r0, r1, r2    //加多个寄存器, r0 = r1 + r2
//ldr 类似x86里的MOV
ldr  r0, [r1]          //从内存中加载int,r0 = r1[0]
ldr  r0, [r1, #4]    //从内存中加载下一个int,r0 = r1[1]
ldmia  r2, {r0, r1}  //多次加载,r0 = r2[0], r1 = r2[1]

在高级语言HLLs中,使用变量,在汇编中使用寄存器变量(特定范围的内存),

寄存器是芯片的内置变量,所以访问速度最快,但数量有限。内存临近芯片,速度仅次于寄存器,而且空间很大,所以将变量放在内存里,访问变量就是访问内存。

寄存器和变量都是全局属性,想要操作局部变量,使用栈。

栈Stack

  • Stack Point(SP)寄存器
    包含栈顶的地址
    13671484-426a69f7065f0ace.png
    函数调用1.png
  • 栈用完之后需要清理,从而保证栈针用之前后用之后,指向一个位置,否则

例子:加入存在一个函数FOO,它会使用寄存器A,B,C,D,同时会调用函数BAR,但是BAR也将使用A、B、C。
分析:因为BAR也会使用到寄存器A、B、C,为了不打扰FOO的使用,BAR首先将A,B,C的原始值压入堆栈,使用完之后,返回给寄存器A,B,C,让FOO接着使用

//函数FOO
FOO:
    //将A,B,C,D 压入堆栈,保存他们的原始值
    push    {A, B, C, D}

    mov     A, #1
    mov     B, #2
    mov     C, #3
    call    BAR
    //global_var0 is 14 from BAR
    mov     D, global_var0
    //global_var1 = A+B+C = 20
    add     A, B    //A = A+B = 3
    add     A, C    //A = A+C = 6
    add     A, D    //A = A+D = 20
    mov     global_var1, A  //global_var1 = 20
    //恢复A,B,C,D
    pop     {A-D}
    return  

//函数BAR
BAR:
    //此时,A=1, B=2, C=3
    push    {A-C}
    mov     A, #2   //A = 2
    mov     B, #5   //B = 5
    mov     C, A    //C = 2
    add     C, B    //C = B + A = 7
    //global_var0 = 2*C = A+B+C;全局变量global_var0,一个内存地址
    add     C, C    //C = 14
    mov     global_var0, C  
    //恢复A, B, C
    pop     {A-C}
    return 

这段代码中,只是实现了global_var0、global_var1这两个内存变量的赋值

分支和条件代码 Branching and condition codes

  • PC (程序计数器program Counter): 指向下一条指令的地址

正常情况下:执行到PC时,读取他的值,然后给他一个增量,让他指向下一个命令,这是一个相对直线的过程,他十一个比较规律的值

但是,如果出现条件语句,或者直接跳转,重定向这个程序的执行流程,PC会指向一个完全不规律的地址,技术术语(technical term)是分支branching,对于分支的助记符(mnemonic)是b或者j(jump)

endless:
    .....  //代码块
    b endless    //跳转到无限循环的代码块去

但是,只有存在条件并且可以实现的分支才是完整的分支,这些条件依赖处理器
Zero(Z) :操作的结果为0
Negative(N) :操作的结果是负数
Carry bit set(C) :进位设置,如果mostest有效位被设置
Arithmetic overflow :算数溢出,例如:两个正数相加得到一个负数
这些标志位flags,都存储在Program status Register(PSR)程序状态寄存器,每一个数据操作指令根据操作的结果,设置这些标志位中的一个或多个

//汇编程序的描述是: for (int i=0; i != 16; i++)

    mov     A, #0       //A = 0
//循环体
loop_start:
    ...     //循环体内的代码

    add     A, #1       //A += 1
    //compare A to 16,实际上会进行减法,来更改Z(Zero)
    cmp     A, #16      
    //branch if not equal,如果不相等就跳转
    //其实这里也是根据Z标志位,来跳转
    bne     loop_start

条件代码(i.e. cmp,ne...)的数量取决与平台,ARM只有16个

https://www.coranac.com/tonc/text/asm.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值