版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012581760/article/details/86538003
int a = 1; mov dword ptr [ebp - 8], 1
int b = 2; mov dword ptr [ebp - 14h],2
int c = a + b; mov eax, dword ptr [ebp - 8]
add eax, dword ptr [ebp - 14h]
mov dword ptr [ebp - 20h], eax
汇编语言:8086汇编(16bit),x86汇编(32bit),x64汇编(64)bit (汇编语言不区分大小写)
AT&T汇编 vs Intel汇编
寄存器命名 %eax eax Intel的不带%
操作数顺序 movl %eax,%edx mov edx, eax 将eax的值赋值给edx
常数\立即数 movl $3,%eax mov eax,3 将3赋值给eax
jmp指令 jmp *%edx jmp edx
jmp *0x4001002 jmp 0x4001002 在AT&T的jmp地址前面要加星号*
jmp *(%eax) jmp [eax]
操作数长度 movl %eax, %edx mov edx, eax
movb $0x10, %al mov al, 0x10
leaw 0x10(%dx),%ax lea ax, [dx + 0x10]
// b=byte(8-bit)
s=short(16-bit integer or 32-bit floating point)
w=word(16-bit)
l=long(32-bit integer or 64-bit floating point)
q=quad(64-bit)
t=ten bytes(80-bit floating point)
x64汇编 - 寄存器(学汇编是先学寄存器再学汇编指令)
常用寄存器(寄存器的大小跟CPU的位数挂钩,如果是64位的证明寄存器是64位的,那么一个寄存器是占8个字节)
RAX
RBX
RCX
RDX
RBP
RSI
RDI
RSP
R8
R9
R10
R11
R12
R13
R14
R15
x86是(32bit),x64汇编兼容x86
EAX
EBX
ECX
|63..32|31..16|15-8|7-0| 63位
|AH. |AL.|
|AX.........| 64位中低2个字节16位变为AX寄存器(64位兼容16位)
|EAX..................| 64位中低4个字节32位变为EAX(x64兼容x8664位兼32)
|RAX.............................|
一般的规律
R开头的寄存器是64bit,占8个字节
E开头的寄存器是32bit,占4个字节
x64汇编要点总结( 权威参考:Intel白皮书 链接地址:https://software.intel.com/en-us/articles/intel-sdm)
mov dest src // 将src的内容赋值给dest,类似于dest=src
[地址值] // 中括号里面的东西都是地址值,都是内存地址
word是2字节
dword是4字节(double word)
qword是8字节(quad word)
mov dword ptr [ebp-8],1 // 将1放到内存地址值为ebp-8这个地址对应的存储空间内容中,1的存储要覆盖掉4个字节(小端模式)
call 函数地址 // 调用函数
mov eax, [01332132H] // 将地址值对应的存储空间的内容取出四个字节的数据放到寄存器eax中,
lea dest, [地址值] // 直接将地址值赋值给dest,类似于dest = 地址值
lea eax, [01332132H] 相等于 mov eax, 01332132H 伪代码eax = 01332132H
ret // 函数返回
xor op1, op2 // 异或,将op1和op2异或的结果赋值给op1,类似于op1 = op1 ^ op2
add op1, op2 // 类似于op1 = op1 + op2
sub op1, op2 // 类似于op1 = op1 - op2
inc op // 自增,类似于op = op + 1
dec op // 自减,类似于op = op - 1
一个变量的地址值是他最小字节的
jmp 内存地址 // 跳转到某个内存地址去执行代码,以j开头的一般都是跳转,大多数是带条件的跳转,一般跟test,cmp等指令配合使用
cmp eax, ebx
jz 01332132H 比较两个寄存器的值,如果相等,就跳转,如果d比较结果不相等,就不跳
// jcc表示带条件的跳转指令jmp condition command
JE,JZ 结果为零则跳转(相等时跳转) ZF=1
JNE,JNZ 结果不为零则跳转(不相等时跳转) ZF=0
JS 结果为负则跳转 S代表sign(有符号\有负号) SF=1
JNS 结果为非负则跳转 SF=0
JP,JPE 结果中1的个数为偶数则跳转 parity even PF=1
JNP,JPO 结果中1的个数为奇数则跳转 parity odd PF=0
JO 结果溢出了则跳转 overflow OF=1
JNO 结果没有溢出则跳转 not overflow OF=0
JB,JNAE 小于则跳转(无符号数) (below,not above equal <) CF=1
JNB,JAE 大于等于则跳转(无符号数) (not below, above equal >=) CF=0
JBE,JNA 小于等于则跳转(无符号数) (below equal, not above <=) CF=1 or ZF=1
JNBE,JA 大于则跳转(无符号数) (not below equal, above >) CF=0 and ZF=0
JL,JNGE 小于则跳转(有符号数)(little, not great equal <) SF!=OF
JNL,JGE 大于等于则跳转(有符号数)(not little,great equal >=) SF=OF
JLE,JNG 小于等于则跳转(有符号数) (little equal, not great <=) ZF=1 or SF!= OF
JNLE,JG 大于则跳转(有符号数) (not little equal, great >) ZF=0 and SF=OF
硬盘 (运行软件)装载到 内存 读(写) CPU(读取内存中的代码,修改将某个变量的值改掉写内存,控制其他硬件设备(显示器,音响,话筒,其他设备))
CPU (寄存器,运算器,控制器) 比如做加法操作,先将内存中的某个值放到寄存器中,再通过运算器进行加或者减另一个值将结果再放到寄存器中,运算完再将结果送回到内存中,因为寄存器就在CPU,所以CPU操作寄存器速度比操作内存的速度快
具体事例如下:
执行一个函数的时候,编译器首先会估算一下这个函数中大概要用到多少空间,编译代码的时候就会知道,函数中用到了几个变量,这个函数应该分配多少空间,执行函数的时候,就已经分配好一段连续的内存的栈空间了(给函数分配的内存空间一般叫做栈空间,栈内存空间的特点是由CPU自动分配和回收的达到栈平衡)hex16进制,一个变量的地址值是它所有字节中最小字节的地址值.
int a = 1; mov dword ptr [ebp - 8], 1 //将1放入a的存储空间占4个字节
int b = 2; mov dword ptr [ebp - 14h],2 //将2放入b的存储空间占4个字节
int c = a + b; mov eax, dword ptr [ebp - 8] //将a中取出的1放入寄存器eax中
add eax, dword ptr [ebp - 14h] // 将a和b的值通过寄存器相加给了eax
mov dword ptr [ebp - 20h], eax // 将eax寄存器中的值a+b的结果给了c记(ebp - 20h)的内存存储空间