原文地址:
-------------------------------------------------------------------------------分割线--------------------------------------------------------------------------------
在上一篇我们学会了赋值部分的常用汇编指令,这次我们来学习一下运算指令。
运算指令包括加减乘除、位操作指令等可以进行运算的指令,下面我们来了解一下。
ADD加法指令(add)
此指令会设置相关Eflags寄存器,格式如下:
伪C代码为dst += src,dst可以是寄存器、地址,不可以是立即数;src可以是寄存器、地址和立即数,dst和src不能同时为地址。例如:
1 | ADD dst,src |
1 2 3 4 | ADD EAX,1 // 寄存器EAX的值加1 ADD EAX,EBX // 寄存器EAX等于寄存器EAX加上寄存器EBX的值 ADD EAX,[20401000] // 寄存器EAX等于寄存器EAX加上地址为20401000处的值 ADD [02401000],EAX // 地址02401000处的值为其原值加上寄存器EAX的值 |
INC加一指令(increase)
此指令会设置相关Eflags寄存器,格式如下:
伪C代码为dst ++,dst可以是寄存器和地址,不可以是立即数。例如:
1 | INC dst |
1 2 | INC EAX // 寄存器EAX等于寄存器EAX加1 INC BYTE PTR [02401000] // 地址02401000处的值为其1byte大小的原值加1 |
SUB减法指令(subtract)
此指令会设置相关Eflags寄存器,格式如下:
此指令与ADD类似,伪C代码为dst -= src,示例如下:
1 | SUB dst,src |
1 2 3 4 | SUB EAX,1 // 寄存器EAX的值减去1 SUB EAX,EBX // 寄存器EAX等于寄存器EAX减去寄存器EBX的值 SUB EAX,[20401000] // 寄存器EAX等于寄存器EAX减去地址为20401000处的值 SUB [02401000],EAX // 地址02401000处的值为其原值减去寄存器EAX的值 |
DEC减一指令(decrease)
此指令会设置相关Eflags寄存器,格式如下:
此指令与INC指令类似,伪C代码为dst --,例如:
1 | DEC dst |
1 2 | DEC EAX // 寄存器EAX等于寄存器EAX减1 DEC BYTE PTR [02401000] // 地址02401000处的值为其1byte大小的原值减1 |
MUL/IMUL乘法指令(multiplie)
此指令会设置相关Eflags寄存器,MUL是无符号乘法指令,IMUL是带符号乘法指令,格式如下:
此指令有点特殊,需要区别记忆。 在32位下,规定寄存器EAX为乘数,dst为被乘数,其结果最大为64位,所以把EDX作为结果的高位,EAX作为结果的低位,即EDX:EAX。 在16位下,规定寄存器AX为乘数,dst为被乘数,其结果最大为32位,DX作为结果的高位,AX作为结果的低位,即DX:AX。 在8位下,规定寄存器AL为乘数,dst为被乘数,其结果最大为16位,存放于AX。 例如:
1 | MUL/IMUL dst |
1 2 3 4 5 6 7 8 | MOV EDX,6 // 寄存器EDX赋值6 MOV EAX,2 // 寄存器EAX赋值2 MOV EBX,3 // 寄存器EBX赋值3 MUL EBX // 执行后,EBX * EAX = 2 * 3 = 6,寄存器EDX为0,寄存器EAX为6 MOV EDX,6 // 寄存器EDX赋值6 MOV EAX,2 // 寄存器EAX赋值2 MOV EBX,3 // 寄存器EBX赋值3 MUL BL // 执行后,BL * AL = 2 * 3 = 6,寄存器EDX不受影响,值为6,寄存器AX为6 |
DIV/IDIV除法指令(divide)
此指令会设置相关Eflags寄存器,DIV是无符号乘法指令,IDIV是带符号乘法指令,格式如下:
此指令有点特殊,需要区别记忆。 在32位下,规定EDX:EAX为被除数,dst为除数,其商放于寄存器EAX,余数放于寄存器EDX; 在16位下,规定DX:AX为被除数,dst为除数,其商放于寄存器AX,余数放于寄存器DX; 在8位下,规定AX为被除数,dst为除数,其商放于寄存器AL,余数放于寄存器AH。例如:
1 | DIV/IDIV dst |
1 2 3 4 5 6 7 8 | MOV EDX,0 // 寄存器EDX赋值0 MOV EAX,7 // 寄存器EAX赋值7 MOV EBX,2 // 寄存器EBX赋值2 DIV EBX // 执行后,EDX:EAX / EBX = 7 / 2 = 3 % 1,EAX值为3,EDX值为1 MOV EDX,6 // 寄存器EDX赋值6 MOV EAX,7 // 寄存器EAX赋值7 MOV EBX,2 // 寄存器EBX赋值2 DIV BL // 执行后,AX / BL = 7 / 2 = 3 % 1,AL值为3,AH值为1,AX的值为0x103 |
AND逻辑与指令(and)
此指令会设置相关Eflags寄存器,格式如下:
把dst与src进行逻辑与操作,位同时为1则设为1,其他情况设为0,伪C代码dst &= src,例如:
1 | AND dst,src |
1 2 3 | MOV AL,30 // 寄存器AL赋值00110000(0x30) MOV BL,25 // 寄存器BL赋值00100101(0x25) AND AL,BL // AL = AL & BL = 100000(0x20) |
OR逻辑或指令(or)
此指令会设置相关Eflags寄存器,格式如下:
把dst与src进行逻辑或操作,位同时为0则设为0,其他情况设为1,伪C代码dst |= src,例如:
1 | OR dst,src |
1 2 3 | MOV AL,30 // 寄存器AL赋值00110000(0x30) MOV BL,25 // 寄存器BL赋值00100101(0x25) OR AL,BL // AL = AL | BL = 00110101(0x35) |
XOR逻辑异或指令(xor)
此指令会设置相关Eflags寄存器,格式如下:
把dst与src进行逻辑异或操作,位相同时设为0,相反时设为1,伪C代码dst ^= src,例如:
1 | XOR dst,src |
1 2 3 4 5 | MOV AL,30 // 寄存器AL赋值00110000(0x30) MOV BL,25 // 寄存器BL赋值00100101(0x25) XOR AL,BL // AL = AL ^ BL = 0010101(0x15) XOR AL,BL // AL = AL ^ BL = 00110000(0x30),执行两次之后会还原原值,多用于可解密加密 XOR AL,AL // AL = AL ^ AL = 0,多用于清0寄存器 |
NOT逻辑非指令(not)
此指令会设置相关Eflags寄存器,格式如下:
把src进行逻辑非操作,所有位设为相反,伪C代码src ~= src,例如:
1 | NOT src |
1 2 | MOV AL,30 // 寄存器AL赋值00110000(0x30) NOT AL // AL = ~AL = 11001111(0xCF) |