x86_64汇编之二:x86_64的基本架构(寄存器、寻址模式、指令集概览)_ponnylv的博客-CSDN博客_x86_64指令集
汇编语言cs:是代码段寄存器,ds是数据段寄存器。cs*16+IP得到的是代码段地址,ds*16加偏移地址得到的是数据段地址。
段代码CS:存放当前正在运行的程序代码所在段的段基值,表示当前使用的指令代码可以从该段寄存器指定的存储器段中取得
cs:[ip]一起决定了下一条指令的地址,在调用的时候,CALL指令将保存返回地址,调用结束时,RET指令将恢复返回地址。
如果是段内跳转,则只需要修改IP,如果是远跳转,则需CS和IP同时修改和恢复。
IP:相应的偏移值。 CS+IP
1. call word ptr + 内存单元地址
这个指令的是先将call指令的下一条指令的IP入栈,然后跳到以内存单元地址为IP的代码处
2.call dword ptr + 内存单元地址
call是汇编指令,用来调用子过程。后面的Dword ptr[40105c]是一个内存地址,就是要调用的子过程的首地址。这个指令先将call指令的下一条指令的CS(代码段寄存器)入栈,再将call指令的下一条指令的IP入栈,然后跳到以内存单元的高位为CS,低位为IP的代码处
3.eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。
4.乘法运算对应的汇编指令有有符号imul和无符号mul两种。由于乘法指令的执行周期较长,在编译过程中,编译器会首先尝试吧乘法转换为加法,或者使用移位指令。不能转换时,才会使用乘法指令。
5.SHL(左移)指令使目的操作数逻辑左移一位,最低位用 0 填充。最高位移入进位标志位,而进位标志位中原来的数值被丢弃
6.ESP 就是一直指向栈顶的指针,而 EBP 只是存取某时刻的栈顶指针
7.inc 加1指令 dec 减1指令
8.有的汇编指令需要16位地址对齐,这样的话速度更快,注意c代码中的地址。
9.movups
不必16字节对齐
移动指令 表示打包的单精度
浮点数
10.movaps
16字节对齐
移动指令 表示打包的单精度
浮点数
11. movd 指令在通用寄存器或内存和XMM或MMX寄存器之间复制双字或四字。
12.Shr是逻辑右移指令,它和shl所进行的操作刚好相反。
(1)将一个寄存器或内存单元中的数据向右移位;
(2)将最后移出的一位写入CF中;
(3)最高位用0补充。
13.lea
1、lea eax,[addr] 就是将表达式addr的值放入eax寄存器,
2、lea eax,dword ptr [ebx];将ebx的值赋值给eax
3、lea eax,c;其中c为一个int型的变量,该条语句的意思是把c的地址赋值给eax;
14.XMM 寄存器是一个完全独立的寄存器集,随 SSE 一起引入,至今仍被广泛使用.它们是 128 位宽,指令可以将它们视为 64、32(整数和浮点)、16 或 8 位(仅限整数)值的数组.其中 8 个在 32 位模式下,16 个在 64 位模式下.实际上,所有浮点数学运算都是在 64 位模式下在 SSE(以及 XMM 寄存器)中完成的,因此,与 MMX 寄存器不同,它们仍然非常相关.
15.CMP(比较)指令执行从目的操作数中减去源操作数的隐含减法操作,并且不修改任何操作数。
16. LDR{条件} 目的寄存器,<存储器地址>
LDR
伪指令用于加载32位的立即数或一个地址值到指定寄存器
17.cmp r0, r1 beq run1. 如上是beq一个最简单的示例,比较r0和r1寄存器的值,如果相等,则跳转到run1;这时由于r0和r1寄存器的值相等,CPSR状态寄存器的Z=1。
18. sub r0, r0, r1, lsl #2. r0=r0-r1*4 #2的意思是就是代表数字2,但是LSL2的意思是向左移两位也就是乘以4
19. pxor指令功能,按位做or运算。
20. b 跳转指令,跳转到指定地址的指令
arm指令之beq和bnq_夜风~的博客-CSDN博客_beq指令
21. 指令:.MACRO/.ENDM
汇编 .MACRO – 未曾走远 – 博客园
22. BX LR的作用等同于 mov pc,lr
BX LR指令_班花i的博客-CSDN博客_bx lr 汇编
23.INIT_MMXsse2,会将寄存器定义为mmx的寄存器,但是会将指令和函数后缀设置为sse。
24.pshufb 举例:pshufb xmm1,xmm2 根据xmm2重写xmm1 xmm2共16个字节,
解释:每个src 寄存器是128bit=16byte, 每个byte的最高位存放是否shuffle, 如果是1,则dest对应byte 置零。否则,该byte的低4byte对应了相应的移动位置。
25.pmaddubsw 矩阵相乘,进行一个组合整型乘法,该指令采用16个无符号的8位整数(激活),16个带符号的8位整数(权重),并对它们执行并行的乘法和加法运算以产生8个16位的整数。
26.paddw,该指令是对128位寄存器的每16位做加法运算,在保证不出现进位的情况下,paddw指令比paddd一次能处理更多字节的数据。
使用方法
:paddw xmm, xmm
功能
:源存储器与目的寄存器按字对齐无符号普通相加,内存变量必须对齐内存16字节
27.
PMADDWD mm,mm/m64 |
数据组(字组)的乘加: 将MMX寄存器与MMX寄存器/内存单元中的字组数据相乘,然后将32位结果逐对相加并作为双字存于MMX寄存器中. eg:PMADDWD mm,mm/m64 |
28. packssdw XMM,XMM/m128
此指令与前面的MMX指令packsswb MM,MM/m64操作相同,只是变成了128位
把目的寄存器按双字有符号数压缩为字有符号数放入目的寄存器低64位
把源寄存器按双字有符号数压缩为字有符号数放入目的寄存器高64位
压缩时小于-32768负数变为8000h,大于32767的正数变为7fffh,内存变量必须对齐内存16字节.
高64位 | 低64位
目的寄存器: a0 | a1 | a2 | a3
源寄存器: b0 | b1 | b2 | b3
目的寄存器压缩结果: b0 | b1 | b2 | b3 | a0 | a1 | a2 | a3
29.TEST 指令在两个操作数的对应位之间进行 AND 操作,并根据运算结果设置符号标志位、零标志位和奇偶标志位。
30.对于AVX指令集来说,要充分发挥其作用,需要将乘法表复制到256bit的YMM寄存器。为了做到这一点,我们可以利用XMM寄存器为YMM寄存器的低位这一特性,仅使用一条指令来完成表的复制(Intel风格):
vinserti128 ymm0, ymm0, xmm0,1
这条指令作用是将xmm0寄存器中的数据拷贝到ymm0中,而剩余128位数据通过ymm0得到,其中立即数1表明xmm0拷贝的目的地是ymm0的高位。这条指令提供了两个sourceoperand(源操作数)以及一个destinationoperand(目标操作数),我们在这里使用ymm0寄存器同时作为源操作数和目标操作数来实现了表的复制操作。接下来我们便可以使用与SSSE3下同样的方式来进行单指令32byte的编码运算过程了。
31.VEXTRACTI128. xmm1/m128, ymm2, imm8 Extract 128 bits of integer data from ymm2 and store results in xmm1/m128.
32.跳转
汇编语言——跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP_jena_wy的博客-CSDN博客_jz跳转
33.times是nasm的指令
;开辟200字节内存空间. times 200 db 0
(十六进制)
0x2000
=(二进制)10000000000000
34.
vpbroadcastd
广播扩展
35. psubw MM,MM/m64 按字对齐,普通相减,与sub指令类似.
36.
MOVA
,#data 该
指令
将立即数data传送到累加器A中,双字节
指令
37.
psrad,按双字算术右移
38.packuswb [a0, a1, a2, a3], [b0, b1, b2, b3] = [a0, a1, a2, a3, b0, b1, b2, b3]
40.VPERMD ymm1, ymm2, ymm3/m256 使用ymm2中的索引排列ymm3/m256中的双字,并将结果存储在ymm1中。
41.movlps在内存和SSE寄存器低qword之间移动两个压缩单精度数据。movhps在内存和SSE寄存器高qword之间移动两个压缩单精度数据。其中一个操作数必须为SSE寄存器,另一个必须为64位内存地址。
42.PUNPCKLBW
mm, mm/m32
交叉组合
mm
与
mm/m64
低位双字中的字节,将结果放入
mm
。
PUNPCKLBW
xmm1
,
xmm2/m128
交叉组合
xmm1
与
xmm2/m128
低位四字中的字节,将结果放入
xmm1
。
43.
psrldq XMM,imm8
把目的寄存器128位按imm8(立即数)指定字节数逻辑右移,移出的字节丢失.
imm8 == 1时,代表右移8位,imm8 == 2时,代表右移16位.
movups
mov //移动指令
u
//不必16字节对齐
ps //(packed single-precision floating-point)表示打包的单精度
浮点
数
movaps
mov //移动指令
u
//必需16字节对齐
ps //(packed single-precision floating-point)表示打包的单精度浮点数
44.
高64位按字交错排列指令:punpckhwd
使用方法
:punpckhwd xmm, xmm
功能
:源存储器与目的寄存器高64位按字交错排列,内存变量必须对齐内存16字节
高64位 | 低64位
目的寄存器: a7 a6 a5 a4 a3 a2 a1 a0
源寄存器: b7 b6 b5 b4 b3 b2 b1 b0
目的寄存器结果:b7 a7 b6 a6 b5 a5 b4 a4
低64位按字交错排列指令:punpcklwd
使用方法
:punpcklwd xmm, xmm
功能
:源存储器与目的寄存器低64位按字交错排列,内存变量必须对齐内存16字节
高64位 | 低64位
目的寄存器: a7 a6 a5 a4 a3 a2 a1 a0
源寄存器: b7 b6 b5 b4 b3 b2 b1 b0
目的寄存器结果:b3 a3 b2 a2 b1 a1 b0 a0
45.
shufps shufpd pshuflw pshufhw pshufd pshufw
SSE特殊指令集系列之一—-各种数据重排指令_chuifuhuo6864的博客-CSDN博客
46.punpcklqdq将2个寄存器的下半部分合并为一个。
47.db等
符号:
1.#代表的是寻址方式为立即寻址。比如指令: MOV A,#21H 该指令的意思是:将值21H送给寄存器A中暂存;MOV A,21H 为直接寻址,意思为:将21H这个地址里面中的内容送给
寄存器
A中暂存。
2 [. w0,
[sp,#28]
w0存到sp+#28的位置
3.
INIT_XMM
宏的作用:1、统一操作数是不同类型的寄存器指令(如sse寄存器用movdqa指令
4.
[
]
表示是间接寻址
5.q 四字 d 双字
字节长度1:db(Byte), 字长度2:dw(word), 双字长度4:dd(dword)。只有全局变量可以用缩写。
6.SIMD寄存器
支持AVX512指令集的CPU:
32个512位寄存器,分别称为ZMM0~31,其中低256位复用为YMM0~31,低128位复用为XMM0~31
仅支持AVX指令集的CPU:
16个256位寄存器,分别称为YMM0~15,其中低128位复用为XMM0~15。
汇编程序的
.
伪操作
1.比如 .section .rodata
汇编程序伪操作指令_Eddy_l的博客-CSDN博客_汇编伪操作
2..global
.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用。
.global _start 让_start符号成为可见的标示符,这样链接器就知道跳转到程序中的什么地方并开始执行。linux寻找这个 _start标签作为程序的默认进入点。在汇编和C混合编程中,在GNU ARM编译环境下,汇编程序中要使用.global伪操作声明汇编程序为全局的函数,意即可被外部函数调用,同时C程序中要使用extern声明要调用的汇编语言程序。
.extern XXXX 说明xxxx为外部函数,调用的时候可以遍访所有文件找到该函数并且使用它。\
3.IFIDN<参数1>,<参数2>
IFDIF<参数1>,<参数2>
这两个伪指令用于对两个宏定义的参数1和参数2进行比较。
IFIDN为比较参数1和参数2相同时,汇编条件语句块,否则不汇编条件语句块或者汇编反条件语句块。
而IFDIF为比较参数1和参数2不相同时,汇编条件语句块,否则不汇编条件语句块或者汇编反条件语句块。
两个参数的尖括号不能省略。
若用IFIDNI替代IFIDN,用IFDIFI替代IFDIF,则表示对参数拼写的大小写不敏感。
nasm 宏参数macro
nasm 宏参数macro_fantasy_arch的博客-CSDN博客_nasm 宏
rep指令
(repeat)重复
x86_64函数传参规范
https://www.jianshu.com/p/7ba368036e96
宏定义: