第十七课_几条汇编指令
前言
昨天那篇关于标志寄存器的文章,赶着12点前发出,写得有点仓促了。今天这篇估计也是仓促而就。前面几个指令,了解就好,后面几个最好认真理解一下,最好能记住,后面几个在后面讲画堆栈图的时候有用。不懂这几条汇编指令,你对堆栈的填充估计是云里雾里的。
先说明几个标记符号吧。只是为了后面方便写。
r:通用寄存器(register)
m:内存(memory)
imm:立即数(immediate)
r、m、imm这三个后面加数字,那么这个数字表示多少位。例如:r8:表示8位的寄存器。m32:表示32位的内存。imm16:表示16位的立即数。
ADC指令
ADC指令是带进位的加法。这个指令跟ADD这个加法指令有些相似,都是加法计算,但是ADC指令在进行加法计算时,会根据标志寄存器中的CF位进行加1,如果CF位是1,则运算的结果还会加上1;如果CF是0,运算的结果不加1。ADC指令中,是否加1,主要看CF位。
指令格式:ADC r/m,r/m/imm。两边不能同时为内存,宽度要一样。
测试1:
mov eax,0x1
adc eax,0x1
CF位为0
看OD上的测试:
按F8运行后的结果,可以看到结果是2,跟add(加法)指令的结果是一样的。
测试2:
mov eax,0x1
adc eax,0x1
CF位为1
看OD上的测试:
按F8运行的结果,可以看到结果是3,很明显1 + 1 +1(这个1是进位的)= 3
SBB指令
SBB指令:是带借位的减法。这个指令是做减法运算,但是它也看标志寄存器的CF位,如果CF是1,则在做减法运算时,被减数要减1。可以这么理解:CF为1,说明被减数已经被其他数借了一位,所以它减1。
指令格式:SBB r/m,r/m 。两边不能同时为内存,宽度要一样。
测试:
mov eax,0x3
sbb eax,0x1
CF位为1
在OD上测试
按F8运行,结果为1,因为标志寄存器的CF位为1,则在进行减法运算时,被减数3要先减1,则最后计算的是2 - 1 = 1,所以最后的结果是1。
XCHG指令
XCHG指令:是交换数据。
指令格式:XCHG r/m,r/m/imm 。两边不能同时为内存,宽度要一样。
MOVS指令
MOVS指令:移动数据,这条指令两边可以同时为内存。在汇编中很多指令都规定不能两边同时为内存,MOVS指令是个例外,它可能两边同时为内存。
MOVS指令常跟edi、esi寄存器一起使用,通常是把esi寄存器所指的内存的值保存到edi寄存器所指的内存中。下面三个指令:
movs byte ptr es:[edi],byte ptr ds:[esi] 可以简写为movsb
movs word ptr es:[edi],word ptr ds:[esi] 可以简写为movsw
movs dword ptr es:[edi],dword ptr ds:[esi] 可以简写为movsd
在OD中输入简写的,OD会转成相应的完整的写法。
测试:
mov edi,地址(在堆栈中随便找一个地址)
mov esi,地址(在堆栈中找另一个地址)
movsd
在OD中的测试
按F8运行,可以看到esi所指的内存的值保存到edi所指的内存中。我们还发现esi、edi中的值都加了4。这个是movs指令特有的,指令一新movs指令后,esi、edi中的值会自动加上或减去一个数。如果标志寄存器中的DF(方向标志)位是1,则是减,如果DF是0,则是加。具体加、减多少,就要看数据宽度,byte的是1,word的是2,dword的是4。
STOS指令
STOS指令是将寄存器al/ax/eax的值存到寄存器edi所指定的内存中。
STOS指令也有几个简写:
stos byte ptr es:[edi] 简写为:stosb
stos word ptr es:[edi] 简写为:stosw
stos dword ptr es:[edi] 简写为:stosd
测试:
mov eax,0x520
mov edi,地址(在堆栈中找一个地址)
movsd
在OD中进行测试:
按F8运行后的结果。可以看到edi中的值也是自动加了一个数,这个跟movs指令相似。
REP指令
REP指令是重复操作的指令,重复寄存器ecx中指定的次数,即ecx中的值是多少,则重复指令多少次。
rep常跟stos指令一起使用。这个以后再说吧。
就写这么多吧,晚安!
写于2020.6.9 0:44