汇编基础

Posted by Mr.Be1ieVe on Monday, January 13, 2020

X86汇编基础

==Intel和AT&T语法区别:==

  • Intel操作数前面,AT&T的在后面

在Intel语法中: 在AT&T语法中: 有一个简单的记住它们的方法: 当你面对intel语法的时候,你可以想象把等号(=)放到2个操作数中间,当面对AT&T语法的时候,你可以放一个右箭头(→)到两个操作数之间。

  • AT&T: 寄存器名之前需要写一个百分号(%)并且在数字前面需要加上美元符($)。并用圆括号替代方括号
  • AT&T: 以下是一些添加到操作符后,用来表示数据形式的后缀: – q — quad (64 bits) – l — long (32 bits) – w — word (16 bits) – b — byte (8 bits)

重要:MOV指令在64位模式下,对低32位进行写入操作的时候,会清空高32位的内容[Int13]。比如 MOV EAX,011223344h将会把值写到RAX里,并且清空RAX的高32位区域。

寄存器

  1. EAX: 累加器
  2. EBX: 基址寄存器
  3. ECX: 计数器
  4. EDX: 数据寄存器
  5. ESI: 源变址寄存器
  6. EDI: 目的变址寄存器
  7. EBP: 扩展基址指针寄存器
  8. ESP: 栈指针寄存器
  9. EIP: 指令指针寄存器

大多数寄存器失去了特殊用途,但ESPEBP还是有特殊用途

image-20190821052642311

内存和寻址模式

.data

Var :

​ .byte 64 ; 声明一个字节型变量var,对应值为64

​ .byte 10 ;声明一个数据10,这个数据没有所谓的“标签”,它的内存地址就是 var + 1.

.byte  声明1个字节的数据
.short 声明2个字节的数据
.long  声明4个字节的数据

操作后缀

movb $2,(%ebx); 将2移入到ebx中的值所表示的地址单元中
movw $2,(%ebx); 将16位整数2移动到 ebx中的值所表示的地址单元 开始的两个字节中
movl $2,(%ebx); 将32位整数2移动到 ebx中的值所表示的地址单元 开始的四个字节中

指令

mov <reg, <reg

mov默认对寄存器值或变量值进行操作,可以从寄存器到寄存器,从立即数到寄存器,从存储单元到寄存器,从立即数到存储单元,从寄存器到存储单元

将数据从第一个参数(即寄存器中的内容,内存单元中的内容,或者一个参数值)复制到第二个参数(即寄存器或者内存单元)。

但寄存器复制到寄存器可行时,直接地从内存单元中将数据移动到另一内存单元中是不可以的,必须把内存单元中的数据加载到一个寄存器中,然后才可以通过寄存器把数据移动到目标内存单元中。

push 入栈

push先将ESP中的值减少4,然后将push 的参数移动到一个32位的地址单元(%esp).esp地址从高地址到低地址逐渐减少,就像1000到0,先占1000,再999……空间有限

pop 出栈

先将内存(%esp)中4个字节的数据放到指定寄存器或者内存单元中,然后让esp+4

lea 加载有效地址

将其第一个参数指定的内存单元 放入到 第二个参数指定的寄存器中。只计算有效地址并将其放入寄存器中。

lea和mov的区别

mov:

  • 对于变量,有无 都是取值
  • 对于寄存器,无 表示取值,有 表示取地址

Lea:

  • 对于变量,有无 都是取地址
  • 对于寄存器,无 表示取地址,有 表示取值

imul 整数相乘

  • 两个参数的:先将两个参数相乘,然后把结果存在第二个参数(必须是一个寄存器)中
  • 三个参数的:第一个(必须是常数)和第二个参数相乘,存在第三个参数(寄存器中)

idiv 整数相除

只有一个操作数,为除数,被除数为EDX:EAX中的内容,商存在EAX中,余数存在EDX

shl,shr 按位左移或者右移

对第一个参数进行位运算,移动位数由第二个参数决定


ARM

STMFD SP!, {R4, LR},这条指令类似x86平台的PUSH指令,它会把2个寄存器(R4和LR)的值写到栈里。不过为了简化,在armcc编译器输出的汇编代码里会写成`PUSH {R4, LR}

这指令首先会减少SP的值,这样它在栈中指向的空间就被释放,以留给新条目使用,然后将R4和LR的值存入被修改后的SP的储存区域中。

值得注意的是:STMFD指令是广义的PUSH指令(扩展了它的功能),因为他能操作任何寄存器,不只是SP。换句话说,STMFD可以用于将一组寄存器储存在特定的内存地址上。

MOV R0, #0这条语句,这条语句就是把0写入R0寄存器。这是因为C函数返回了0,返回值会放在R0里。

最后一条指令是LDMFD SP!, R4,PC,这是STMFD的逆指令。为了将初始值存入R4PC寄存器里,这条指令会从栈上(或任何其他的内存区域)读取保存的值,并且增加堆栈指针SP的值。这非常类似x86平台里的POP指令。

最前面那条STMFD指令,将R4,和LR寄存器成对保存到栈中。在LDMFD执行的时候,R4PC会被复原。

「真诚赞赏,手留余香」

Mr.Be1ieVe's Treasure

真诚赞赏,手留余香

使用微信扫描二维码完成支付