常用汇编指令集

寄存器

在这里插入图片描述

如上是OD展示的寄存器,逐条说明常用的寄存器和标志位含义:

EIP:寄存器指向即将要执行的指令的地址(EIP中的地址,就是下一步要执行指令的地址)
ESP:里面的内容永远指向堆栈的最顶端
EAX:(十六进制EAX=12345678)(?AX=5678和和?AH=56和?AL=78)		AX是最后四位,AL是最后两位
ECX:和上面EAX一样
EBX:和上面EAX一样
EDX:和上面EAX一样

注:EIP是不能直接修改的,必须在窗口选中某处右键设置为新的EIP
	有符号就是负数,无符号就是正数

O标志:溢出标志位(O 0):当指令运算结果,即操作改变了符号的时候返回错误值设置的(0 1  :就是二进制的符号位改变了,也就是正数变负数)

A标志:辅助进位标志

P标志:基偶标志位(当指令运算结果,窗口中执行的结果用二进制表示,如果1的总个数是双数那P标志位为1)

Z标志:当指令运算结果为0的话Z标志位就是1

S标志:符号标志:当指令运算结果为负数的话,S标志结果为1

C标志:进位标志位(也可以叫借位标志位);某条指令运算的无符号运算结果,超过最大值(无符号最大数:FFFFFFFF),也就是EAX=FFFFFFFF,add eax,1,超过最大了,那么C标志位就是1了
	为什么  EAX=FFFFFFFF
			add eax,1
			EAX=00000000		变成0了?因为进位了,那个1在EAX外面了即:1 00000000
					
T标志:跟踪标志位

D标志:方向标志位

CF就是无符号溢出标志位,OF是有符号溢出标志位,拿16位举例,范围0X0000~0XFFFF,既然0减1,应该等于-1,那么就是溢出了

指令集

NOP指令:空指令
	使用位置:更改call,在字节的计算上(也就是HEX 数据栏中:2个为一组算一个字节),修改导致(数据栏中)不足的字节用NOP自动填充下去
	90NOP填充是无操作的,00NOP(一个指令)填充是有操作的
	NOP的机器码(二进制)表示:HEX的90
PUSH指令:将push指令后面的数据压入到堆栈中
POP指令:把该数据存入(变为)堆栈的最顶上,类似于剪切(pop eax、pop ebx、等等)
PUSHAD指令:将寄存器的从上向下的顺序,依次push到堆栈中,最后EDI在堆栈中的最顶端(寄存器顺序:EAX——>EDI,堆栈内对应:EAX数据——>最顶EDI数值)
POPAD指令:将堆栈内的数值从下向上pop到寄存器中(寄存器顺序:EDI——>EAX,堆栈内对应:最顶——>第八位)
PUSHA和POPA都是16位的操作指令,PUSHAD和POPAD是32位的;两个其实都差不多
(主要PUSHA和POPA,指的是EAX中的EX、CX、DX、BX、SP、BP、SI、DI,是后八位数值)
MOV指令:赋值操作指令(可以说是复制)
	mov eax,ecx:将ecx中的内容复制给eax,让eax中的内容与ecx相同。
	dword:4字节长度
	word:2字节长度
	/
	mov dword ptr ds:[0x402000],eax		// 4字节长度
	mov word ptr ds:[0x402000],ax		// 2字节长度
	mov byte ptr ds:[0x402000],al		// 1字节长度byte
	// dword word byte决定需要复制的数值
	/
MOVSX指令:(会判断原来的数值是正还是负,再根据正负用0000还是FFFF)
	MOVSX EAX,BX		// 2字节BX复制到4字节EAX,因为填充不足,所以会用占位符来占位(负数的二进制符号为1,会用FFFF填充剩下的字符)
		至于具体是0000还是FFFF填充,那么就看EAX中的前4字节是否是正数(00001234)还是负数(0000A123)了(这里A123用F填充EAX,1234用0填充EAX)
		16位的最大正数:7FFF,负数开始是:8000	 
		32位的最大正数:7FFFFFFF,负数开始是:80000000	 符号位0还是1决定正负
	(MOV指令是不行的)
MOVZX指令:(不考虑正负,直接用0000填充)
LEA指令:(两个数字为一个字节)
	mov 寄存器,[401000]			//有[],取得是[]内的地址的数值,在lea
	lea 寄存器,dword ptr ds:[ecx+0x16]			// 这里的括号是取ecx+0x16的结果,相当于:lea 寄存器,ecx+0x16
	lea意思就是:取计算结果的地址
	
	
	lea指令可以用来将一个内存地址直接赋给目的操作数
	例如:lea eax,[ebx+8]就是将ebx+8这个地址值直接赋给eax,而不是把ebx+8处的内存地址里的数据赋给eax。(与我们平时使用到的指令涉及到的[]情况是不一样的,看下面的说明即可:)
	而mov指令则恰恰相反
	例如:mov eax,[ebx+8]则是把内存地址为ebx+8处的数据赋给eax。

说明:
	如果是:
		push 0x00401000   那么就是压入这个地址
		push [00401000]	  那么就是压入这个地址对应的数据的内容(只需要选中地址,右键,在数据窗口中跟随选择,那么就能看到地址对应的数据内容)
XCHG指令:内容交换
	xchg eax,ebx    结果就是eax的内容变为ebx的,ebx的内容变成eax的。
ADD指令:加法指令
	ADD EAX,333		// 数据添加
	ADD EAX,EBX		// 寄存器相加
	ADD dword ptr ds:[0x402000],0x2	
	ADD dword ptr ds:[0x402000],ecx			// 0x402000地址的数值和ecx相加,给0x402000地址
	// 左下数据框中的数据是反着来的,即:14 01 00 00,在寄存器的ECX中就是00 00 01 14
SUB指令:减法指令(和加法一样使用)
ADC指令:
	ADC EAX,0x5      // 相当于EAX=EAX+0x5+C			// 这个C是进位标志位,为1就加1,为0就加0
SBB指令:
	SBB EAX,0x2		// 相当于EAX=EAX-0x2-C			// 这个C是进位标志位,为1就加1,为0就加0
INC指令:(递增)
	inc eax			// 每次执行都会eax自增数值1		// 类似i++
DEC指令:(递减)
	dec eax			// 每次执行都会eax自减数值1		// 类似i--
MUL指令:(无符号乘法)
	MUL ECX			// 代表的含义就是:EAX*ECX=EAX和EDX存储
		// 举例:EAX=FFF FFF9、ECX=0000 0005、那么结果应该是4 FFFF FFDD
			// 存储的时候,EAX存储FFFF FFDD,EDX存储0000 0004
				0000 0004 FFFF FFDD
				EDX       EAX
DIV指令:(无符号除法)
	div cl	(16进制的)
		// 举例:EAX=0000 0017,ECX=0000 0003
			// 结果就是:EAX=0000 02 07		// 17/3  熵7余2,那么熵在al,余数在ah
	
	div cx	(16进制的)
		// 举例:EAX=0000 0017,ECX=0000 0003
			// 结果就是:EAX=0000 0007,EDX=0000 0002		// 17/3  熵7余2,那么熵在ax,余数在dx

	div ecx	(32进制的)
		// 举例:EAX=0000 0017,ECX=0000 0003
			// 结果就是:EAX=0000 0007,EDX=0000 0002		// 17/3  熵7余2,那么熵在eax,余数在edx
IMUL指令:(有符号的乘法运算(0和F))
	IMUL al:意义就是al*al
	IMUL cl:意义就是al*cl
		// 对此来说,cl取al,cx取ax,ecx取eax
	IMUL ax,cx,0x2:意义就是cx*0x2放入ax
IDIV指令:
	执行的操作:与DIV相同,但操作数必须是带符号的数,商和余数也都是带符号的数,且余数的符号和被除数的符号相同
XADD指令:(交换并相加)(单独交换:XCHG,单独相加:ADD)
	XADD eax,ecx		// eax和ecx交换数值并相加,将结果存储在eax中
NEG指令:(取反)(即正变负)
	neg eax			// EAX = 0000 0050变为 FFFF FFB0	// 可以左下的command进行计算:? -121110得到十六进制	
				-----------------------------------------------------
				网上说的,二进制的算法:
					neg指令执行的操作是把eax的每个二进制位取反之后再加1,得到的十六进制就是结果,以F补全空位
					作用: 将操作数取反再加一, 可以用来求一个数的相反数.
					格式   NEG OPR
					执行操作
							(OPR)<-- -(OPR) 
								亦即把操作数按位求反后末位加1,因而执行的操作也可表示为:
							(OPR)<-- 0FFFFH - (OPR) + 1
								NEG指令对标志的影响与用零作减法的SUB指令一样。
				-----------------------------------------------------
	但在OD中可以左下的command进行计算:? 十六进制	
				例如 ? -50		得到FFFF FFB0		这就是neg的作用,这里的计算是直接取十六进制反数
		点击EAX修改数据时,有符号位展示的是十进制数,求十进制的取反也可以得到取反对应的十六进制
AND指令:(与)
	AND EAX,ECX		// EAX与ECX的各个位相与,得到的结果给EAX
			// 同为1,为1,只要有0就为0
OR指令:(或)
	OR EAX,ECX		// EAX与ECX的各个位相或,得到的结果给EAX
			// 只要有1就为1
XOR指令:(异或)
	XOR EAX,ECX		// EAX与ECX的各个位相异或,得到的结果给EAX
			// 相同为0,不同为1
NOT指令:(反)		// EAX与ECX的各个位相反,得到的结果给EAX
	NOT EAX
			// 各位取反
			完整的EAX:0000 0000 0000 0000 0000 0000 0101 0000   32位
				取反: 1111 1111 1111 1111 1111 1111 1010 1111
			得到十六进制: FFFF FFAF
CMP指令:(比较指令:比较的是地址空间中的数值)
	第一种情况:Z标志位
		Z标志:当指令运算结果为0的话Z标志位就是1(变红就是当前得到的结果,白色是上一步的)
		举例:cmp eax,ecx  	// cmp只做减法,但是结果不放在eax中(即不存储结果),而是将影响Z标志位为0还是1
			// 本质为 sub eax,ecx做的减法放入eax
			------------结果相同,Z标志位为1,结果不同,Z标志位为0			
		问题:
			通常情况下CMP指令都是比较寄存器里的数值
			那就是字符串相等的话,也会提示不等。(举例的这个比较寄存器里的字符串,这种例子基本上很少有的)
			这是因为比较的内容并不是字符串,而是寄存器里的数值而已,也就是字符串的地址,也就是我们语言的字符串指针。
			如果要比较字符串的话,是需要取寄存器里的数值作为地址,然后再取地址里的值(HEX 数据)进行运算,也就是我们C语言的指针,是相同的意思。
				
	第二种情况:S标志位
		S标志:符号标志:当指令运算结果为负数的话,S标志结果为1
		cmp eax,ecx   如果走本质是减法运算的话,部分情况下,S标志位也是受影响的
		
	第三种情况:cmp eax,[0x数值地址]
		cmp eax,[402000]——————>>>这样写,OD自动转为cmp eax,dword ptr ds:[0x402000]

-------------------------------------------
cmp中需要注意的:
	1、cmp eax,ecx  这种情况下,比较的是寄存器中的数值是否相等,也就是字符串的地址,也就是我们语言的字符串指针
		也叫寄存器数值比较
	
	2、cmp [0x402000],[0x402011] 或 cmp eax,[402011]其中eax=0x402000
		要比较字符串的话,是需要取寄存器里的数值作为地址,然后再取地址里的值进行运算,也就是我们C语言的指针,是相同的意思
			这叫字符串值比较
				// 将数据地址:402000的地方在左下角写入数据字符串(xxx),在402010的地方写上(aaa);写完一个字符串需要写一个00,因为以00结尾字符串数据,然后原本写402010就写成402011,修改EAX和ECX分别为上面的地址进行cmp,我们发现地址对应的ASCII字符串是不一样的,进行比较发现。Z标志位为红色0,所以不同。
				
				// 也就是说,cmp比较的就是十六进制数值地址对应的数据内容,那些地址类似与字符串指针比较操作
				
				所谓的做减法,也就是说:
					例如:402000地址对应的字符串(xxx)的数据的十六进制为:77 88 55 77 44
						  402011地址对应的字符串(aaa)的数据的十六进制为:99 44 F1 33 22
							// 将(给机器处理)该十六进制转为二进制进行减法运算,或者(给人看)二进制再转为十进制运算
		
TEST指针:(逻辑比较)
	test eax,eax		// 意义就是判断eax是否为0
		// 本质就不是减法了,本质是做了位运算(按位与的方式进行运算:都为1才为1)
	
		测试操作数是否为0
cmp与test的区别:
		cmp判断两地址中的值是否相等
		test是测试这个数是否为0

(跳转指令),影响跳转的是标志位
OD运行到指定地址:首先左键点击选中该行,然后按下F4就能运行到指定位置
查看辅助的跳转路径线,没开启的话需要开启:调试——>CPU——>显示跳转方向、路径等几个选项

JMP指令:(无条件跳转)不受标志位影响
	jmp 00401031		// 直接跳过中间代码,到00401031位置,jmp不受标志位影响,直接跳


JE指令:(有条件跳转)受标志位影响
	Z(ZF)标志位1的时候会跳转,为0不跳转。je看的Z标志位
	
	
JZ指令:(有条件跳转)受标志位影响
	JZ和JE是相同的,仅仅只是名字不同,实际上输入汇编语句使用JZ也会被OD用JE替代


JNE指令:(有条件跳转)受标志位影响
	Z(ZF)标志位0的时候会跳转,为1不跳转。JNE看也是的Z标志位
	

JNZ指令:(有条件跳转)受标志位影响
	JNZ和JNE也是相同的,仅仅名字不同,实际上输入汇编语句使用JNZ也会被OD用JNE替代



JS指令:(有条件跳转)受标志位影响
	S(SF)标志位1的时候会跳转,为0不跳转。S:符号标志位
		cmp eax,ecx		// 本质是eax-ecx,这里eax=0000 0000  ecx=0000 0001,得到-1,S标志位为1
		js 00401007

JNS指令:(有条件跳转)受标志位影响
	S(SF)标志位0的时候会跳转,为1不跳转。S:符号标志位
		cmp eax,ecx		// 本质是eax-ecx,这里eax=0000 0001  ecx=0000 0000,得到1,S标志位为0
		js 00401007


JP指令:(有条件跳转)受标志位影响
	P(PF)标志位1的时候会跳转,为0不跳转。P:奇偶标志位(就是将汇编指令计算得到的结果转为二进制,二进制中1的个数为偶数的话,那么P标志位就是1)
			// 修改寄存器中的数据时,有符号处为十进制数
	

JPE指令:(有条件跳转)受标志位影响
	JP和JPE也是相同的,仅仅名字不同,实际上输入汇编语句使用JP也会被OD用JPE替代


JNP指令:(有条件跳转)受标志位影响
		P(PF)标志位0的时候会跳转,为1不跳转。P:奇偶标志位(就是将汇编指令计算得到的结果转为二进制,二进制中1的个数为偶数的话,那么P标志位就是1)
			// 修改寄存器中的数据时,有符号处为十进制数


JPO指令:(有条件跳转)受标志位影响
		JNP和JPO也是相同的,仅仅名字不同,实际上输入汇编语句使用JNP也会被OD用JPO替代


JO指令:(有条件跳转)受标志位影响
	O(OF)标志位1的时候会跳转,为0不跳转。O:溢出标志位
		举例:修改EAX=7FFF FFFF,修改ECX=0000 0001
			add eax,ecx
			jo 0x00401008
				// 加一以后,最大正整数变为8000 0000负数,所以O标志位会变为红1 



JNO指令:(有条件跳转)受标志位影响
	O(OF)标志位0的时候会跳转,为1不跳转。O:溢出标志位



JB指令:(有条件跳转)受标志位影响
	C(CF)标志位1的时候会跳转,为0不跳转。C:借位标志位(也可以叫进位标志位)
		cmp eax,ecx
		jb 0x00401018		// JB的条件是:第一个操作数小于第二个操作数就跳转发生;即eax小于ecx就跳转
				// 发生改变的是C(CF)标志位:借位标志位置1,发生了跳转

JNB指令:(有条件跳转)受标志位影响
	C(CF)标志位0的时候会跳转,为1不跳转。C:借位标志位(也可以叫进位标志位)
		cmp eax,ecx
		jb 0x00401018		// JB的条件是:第一个操作数大于或等于第二个操作数就跳转发生;即eax大于或等于ecx就跳转
				// 发生改变的是C(CF)标志位:借位标志位置0,发生了跳转


JBE指令:(有条件跳转)受标志位影响
	受两个标志位影响:C和Z
		C为1或者Z为1的时候,都可以跳转
		// cmp eax,ecx  也可以说JBE的条件还有:第一个操作数小于或等于第二个操作数就都可以跳转发生;即eax小于或等于ecx就都可以跳转


JA指令:(有条件跳转)受标志位影响
	实际上也叫JNBE指令,OD中输入JNBE指令的时候,会自动以JA指令填充
	受两个标志位影响:C和Z
		C为0与Z为0的时候,才可以跳转
		// cmp eax,ecx  也可以说JNBE的条件还有:第一个操作数大于第二个操作数才可以跳转发生;即eax大于ecx才可以跳转
	


JL指令:(有条件跳转)受标志位影响
	S(SF)标志位1的时候会跳转,为0不跳转。S:符号标志位
	cmp eax,ecx
	JL 0x401018		// 第一操作数小于第二操作数时就跳转(影响的标志位是S(F)标志位)
	
	十进制有符号数比较,JB是转成十进制无符号数进行比较(JB只关心是否进位或者进位)
			-----可以在寄存器上右键修改看到
CALL指令:(函数指针指令)
	call就是执行了一个函数,call后面就是函数的地址;call要执行这个函数,执行完再返回这个call
		---实际上call就是函数调用(F7进入call,也就是函数的执行内容,当遇到return的时候就回到主程序;有个辅助括号,说明哪儿才是结束的return)
		---包括右下角的堆栈单元里面都会提示返回地址,也就是call的地址
	(call就是函数的代表,F7进入函数,F8直接执行过函数;很多函数调用,至于哪个才是自定义的函数,使用:
			选中call,右键跟随那么就能到call地址,不需要分析只需要小键盘的减号键就能回到主程序)

	
	如何存储call返回地址的?
		F7进call看堆栈,堆栈最开始就记录下来的初始开始地址以及最后的返回地址;
			(例如:返回到  call函数的下一个地址  来自 call内函数的起始地址)
	
	简单地说:call就是进入一个函数执行函数代码,return就是出函数
	
	举例:PUSH 0x402000
			retn
		等价于:jmp 0x402000
	
	call可以函数嵌套,所以,要耐心跟call,哪些是有用的自定义的函数或者底层用的函数,哪些就是普通函数不用管的,熟练利用F7进call,和F8单步直接执行call
	
	堆栈中的返回地址上面的内容是call的数据,这个数据可能是push压栈的也可能是生成的,需要记住观察堆栈内容
LOOPD指令:(循环指令)
	举例:xor ecx,ecx 		//清空ecx	// 需要计数器表名循环几次,基本会用ecx做计数器,不约而同的规则
			mov ecx,6		// 定义ecx循环6次
			// 开始循环
			dec ecx			// ecx自减一,每次循环减一
			test ecx,ecx		// 判断是否为0  或者用cmp ecx,0x0
			// 等于0就不循环了,执行跳转
			jne 00401007	


	LOOP举例:
		xor ecx,ecx
		mov ecx,0x6
		
		loopd 0x0040100A		// (相当于执行了:dec ecx、test ecx,ecx、jnz 0x0040100A)
		
		使用的小差别:首测循环的时候loopd没有减一,导致ecx为1的时候就执行了,而另一种方式首次减一了的所以执行的时候ecx为0的时候执行的
						-----但是都是循环定义的次数,只是ECX结果有差别

LOOP指令:是8位指令,CL
LOOPW指令:是16位指令,CX
LOOPD指令:是32位指令,ECX
shl指令是汇编语言中的一个指令:
	格式:SHL DST,1 。
  	功能:将目的操作数顺序左移1位或CL寄存器中指定的位数。左移一位时,操作数的最高位移入进位标志位CF,最低位补零。
  	特点:SHL指令将影响CF和OF两个标志位。如果移位次数为1,且移位后的符号位的值发生变化,则OF=1,否则OF=0.如果移位次数不为1,则OF的值不确定。

	SHL指令使目的操作数逻辑左移一位,最低位用0填充。最高位移入进位标志位,而进位标志位中原来的数值被丢弃。
	若将1100 1111左移1位,该数就变为 1001 1110
	
	SHL指令将影响CF和OF两个标志位。如果移位次数为1,且移位后的符号位的值发生变化,则OF=1,否则OF=0.如果移位次数不为1,则OF的值不确定。

	例如:
		BL左移一位。最高位复制到进位标志位,最低位填充0:

		mov bl, 8FH              ; BL = 10001111b
		shi bl, 1        ; CF = 1, BL = 00011110b
		当一个数多次进行左移时,进位标志位保存的是最后移出最高有效位(MSB)的数值。

		mov al, 10000000b
		shi al, 2                   ; CF = 0, AL = 00000000b
	步骤:
		1.将一个寄存器或者内存单元中过的数据向左移动bit位。
		2.将溢出的这一位放到CF中。
		3.最低位用0补充。

	位元乘法:
		数值进行左移即行了位元乘法。
		任何操作数左移 n 位,将该数乘以 2n。

		例如,十进制数 10 左移两位,其结果与10 * 2n相同。

		mov al, 10      ; 00001010 
		shl dl ,2       ; 00101000 
SHR指令
	SHR指令使目的操作数逻辑右移一位,最高位用0填充。最低位置复制到进位标志位CF,而进位标位中原来的数值被丢弃。

	例如:
		AL中的最低位0被复制到进位标志位,而AL中的最高位用0填充。

		mov al, 0D0H       ; aL = 11010000b
		shr al, 1		   ; aL = 01101000b, CF = 0
		在多位移操作中,最后一个移出位0的数值进入进位标志位。

		mov al, 00000010b
		shr al, 2                        ; AL = 00000000b, CF = 1
	总结:
		当一个数多次进行右移时,进位标志位保存的是最后移出最低有效位的数值。



移位指令分为逻辑移位指令和算术移位指令,分别具有左移与右移。
SHL逻辑左移;左移,最低位补0,最高位进入CF。
SHR逻辑右移;右移,最高位补0,最低位进入CF。
SAL算术左移;左移,与SHL功能相同。
SAR算术右移;右移,最高位不变(符号位,若为负,则进1),最低位进入CF。
CDQ扩展指令:是一个让很多人感到困惑的指令,用于扩充EAX的存储范围
	这个指令把 EAX 的第 31 bit 复制到 EDX 的每一个 bit 上。 它大多出现在除法运算之前。它实际的作用只是把EDX的所有位都设成EAX最高位的值。也就是说,当EAX <80000000, EDX 为00000000;当EAX >= 80000000, EDX 则为FFFFFFFF。
	例如 :
			 假设 EAX 是 FFFFFFFB (-5) ,它的第 31 bit (最左边) 是 1,
			 执行 CDQ 后, CDQ 把第 31 bit 复制至 EDX 所有 bit
			 EDX 变成 FFFFFFFF
			这时候, EDX:EAX 变成 FFFFFFFF FFFFFFFB ,它是一个 64 bit 的大型数字,数值依旧是 -5。

	备注:
			EDX:EAX,这里表示EDX,EAX连用表示64位数

	CDQ指令的功能是该指令先把edx的每一位置成eax的最高位,意思就是说把EAX由32位扩展成64位(EDX:EAX),EDX表示原来EAX的符号,
	这个是进行除法之前的准备操作!

	eax除以ecx,商保存在eax,余数放在edx   ,基本上没edx什么事,除了后面保存余数
	先前把符号位保存到edx里面,等除法做完了  ,符号位又回到eax里面了 

其他指令:
;CBW(Convert Byte to Word):             将 AL 扩展为 AX
;CWDE(Convert Word to Extended Double): 将 AX 扩展为 EAX
;CDQ(Convert Doubleword to Quadword):   将 EAX 扩展为 64 位数 EDX:EAX
;CWD(Convert Word to Doubleword):       将 AX 扩展为 DX:AX

;它们都是用符号位填充多出的空间
;它们对 EFLAGS 无影响, 也无参数
int3指令:断点指令(机器码为:CC)
sete指令:
	sete al
	当前标志位是什么,al就是什么

寻址方式

直接寻址:不用执行一眼就看得出来地址,写清楚地址的
		例如:直接表明地址了
			MOV DWORD PTR [00401000],EAX
			MOV AXE, WORD PTR [00401000]
			CALL 401000
			JMP 401000
			
	
	
间接寻址:需要程序执行到,才知道地址的,就是间接寻址
		例如:未写出地址,需要执行到才知道地址
			MOV DWORD PTR[EAX],ECX
			CALL EAX
			JMP [EBX + 8]
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeromeyoung666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值