汇编基础入门

1,148 阅读4分钟

1.编程语言的发展

  • 汇编语言与机器语言一一对应,每一条机器指令都有与之对应的汇编指令 
  • 汇编语言可以通过编译得到机器语言,机器语言可以通过反汇编得到汇编语言 
  • 高级语言可以通过编译得到汇编语言\机器语言,但汇编语言\机器语言几乎不可能还原成高级语言 

/*
_stu:
    .long    10                      ; 0xa
    .long    10                      ; 0xa
_array:
    .long    10                      ; 0xa
    .long    10                      ; 0xa
*/    

struct Student{
    int age;
    int num;
} stu = {10, 10};

int array[] = {10, 10};

2.汇编语言种类

  • 8086汇编(8086处理器是16bit的CPU) 
  • Win32汇编 
  • Win64汇编 
  • AT&T汇编(Mac、iOS模拟器) 
  • ARM汇编(嵌入式、iOS设备真机)

2.寄存器

  • 通用寄存器x0-x28(w0-w28是x0-x28的低32bit) 
  • x0-x7通常用来存放函数的参数, 更多的参数需要使用栈堆来传递
  • x0通常用来存放函数的返回值
  • 堆栈指针 fp(Frame Pointer) 也就是x29
  • 链接寄存器:lr(Link Resister) 也就是x30, 存储着函数的返回地址
  • pc:(program counter) 记录真当前cpu指令是哪一条指令, 存储着当前cpu正在执行的指令地址
  • 程序状态寄存器: spsr, 异常状态下使用

3.指令(不分大小写)

  • ret:函数返回
  • mov:
       完成从另一个寄存器、或者立即数加载到目的寄存器, 其中s项决定操作是否影响 

       CPRS条件标志位的值, 没有s指令时, 不更新CPRS条件标志位的值

CPRS标志位:https://juejin.cn/post/6844903968888324110
格式: {条件}{s} 目的寄存器, 源操作数
mov x0, x1; 将寄存器x1的值传递给寄存器x0
mov x8, #20; 将立即数20传递给寄存器x8

  • add:加法

    add x0, x1, x2; x0 = x1 + x2, 将寄存器x1和x2的内容相加, 并将结果存放载寄存器x0中    
    add x0, x1, #1; x0 = x1 + 1    

  • sub:减法, 定义同上面
  • cmp:比较指令

格式:{条件} 操作数1, 操作数2
cmp: x1, x0; 将寄存器x1的值与寄存器x0的值相减, 并根据结果设置CPRS的标志位
cmp: x1, #100; 将寄存器x1的值与立即数100相减, 并根据结果设置CPRS的标志位

  • b:跳转指令, 可以带条件跳转, 一般和cmp指令配合使用, 相当于8086汇编的jmp

b: label; 程序无条件的调到标号label处执行cmp: x1, #0;当CPRS寄存器中的z条件码置位时,程序跳转到label处执行
b.eq:label

常见的条件域:
  eq:相等
  ne:不相等
  gt:great than, 大于
  ge:greate equel, 大于等于
  lt:less than, 小于
  le:less equel, 小于等于
  • bl:带返回的跳转指令

执行的操作
将下一条指令的地址存储在lr(x30)寄存器中
跳转到标记处开始执行代码

与b指令不同之处:只有使用bl 使用ret才有用,才能回到bl指令调用的下一行
  • 内存操作

load:从内存中读取数据
  ldr x0, [x1]; 将内存地址为x1的字数据读取到x0, 读取多少字节由(x0是w0还是x0决定, 4或者8个字节) 
  ldr x0, [x1, x2]; 将内存地址为x1+x2的字数据读取到x0
  ldr x0, [x1, #ox8]; 将内存地址x1+8的字数据读取到x0
  ldr x0, [x1, x2]!;将内存地址x1+x2的字数据读取到x0, 并将新地址x1+x2写入x1(加感叹号不仅影响x0也影响x1)  
  ldr(右边立即数为正)、ldur(立即数为负数)
     比如:ldr x0, [x1, #0x8]; ldp x0, [x1, #-0x8]

  ldp(p是pair, 一对的意思), 从内存中读取数据,放到一对寄存器中, 
    ldp w0, w1, [w2, #ox4], 连续赋值比如前四个字节给w0, 后四个给w1

  store: 往内存中写入数据 用法同load
  str、stur
  stp
  str x0, [x1], #ox8; 将x0中的字数据写入以x1为地址的存储器中,并将新地址x1+8写入x1
  str x0, [x1, #ox8]; 将x0中的字节数写入到以x1+8为地址的存储器中
  stp x0, x1, [sp, #0x8]; 将x29+x30的字数据写入以sp+0x8为地址的存储器中,


wzr, xzr零寄存器, 里面存储的值是0, word zero register



浮点数, float, double是怎么存的?

函数的堆栈

了解汇编的有什么用?