9.0更多的伪代码
这儿有更多的伪代码
TEST
Test对两个参数(目标,源)执行AND逻辑操作,并根据结果设置标志寄存器。结果本身不会保存。Test用来测试一个位,例如寄存器:
Test eax, 100b;b后缀意为二进制
jnz bitset
如果eax右数第三个位被设置了,jnz将会跳转。Test的一个非常普遍的用法是用来测试一方寄存器是否为空:
test ecx, ecx
jz somewhere
如果ecx为零,Jz跳转
关于栈的伪代码
在我讲栈的伪代码之前,我会先解释什么是栈。栈是内存的一个地方,esp为指向栈的指针。栈是用来保存临时数值的地方,有两个指令来放入一个指和再把它取出来:push和pop。Push把一个指压入栈。Pop再把它弹出来。最后一个放入的值最先出来。一个值被放入栈中,栈指针步减,当它移出来的时候,栈指针步增。看这个例子:
(1)mov ecx, 100
(2) mov eax, 200
(3) push ecx ; save ecx
(4) push eax
(5) xor ecx, eax
(6) add ecx, 400
(7) mov edx, ecx
(8) pop ebx
(9) pop ecx
解释
1、 把100放入ecx中
2、 把200放入eax中
3、 把ecx(等于100)压入栈中(第一个压入)
4、 把eax(等于200)压入栈中(最后压入)
5、 /6/7:对ecx执行操作,使ecx的值改变
8弹出ebx:ebx成为200(最后压入,最先弹出)
9弹出ecx:ecx又成为100(最先压入,最后弹出)
为了说明再压栈和弹栈时,内存中发生了什么,看下图:
Offset
1203
1204
1205
1206
1207
1208
1209
120A
120B
Value
00
00
00
00
00
00
00
00
00
ESP
(栈在这里是初始化为0,但实际上并不是这样。ESP表示ESP指向的offset)
mov ax, 4560h
push ax
Offset
1203
1204
1205
1206
1207
1208
1209
120A
120B
Value
00
00
60
45
00
00
00
00
00
ESP
mov cx, FFFFh
push cx
Offset
1203
1204
1205
1206
1207
1208
1209
120A
120B
Value
FF
FF
60
45
00
00
00
00
00
ESP
pop edx
Offset
1203
1204
1205
1206
1207
1208
1209
120A
120B
Value
FF
FF
60
45
00
00
00
00
00
ESP
Edx现在是 4560FFFFh 了.
CALL和RET
Call跳转到某段代码而且一发现RET指令就返回。你可以把它们看成在其他编程语言中的函数或子程序。例如:
……代码……
call 0455659
……更多代码……
455659处的代码:
add eax, 500
mul eax, edx
ret
当执行这条指令时,处理器跳到455659处的代码,执行指令一直到ret为止,并返回到调用处的下一条。Call跳转到的代码被成为过程(procedure)。你可以把你反复使用的代码写进一个过程并在你每次需要它的时候调用。
更深入的细节:call把EIP(指向将要执行指令的指针)压入栈,而ret指令在它返回的时候把它弹出来。你也可以给一个call指定的参数。这是由压栈来完成的:
push something
push something2
call procedure
在一个调用的内部,参数从栈中读出并使用。注意,只在过程中需要的局部变量也储存在栈中。我不会在此深入下去,因为它可以在masm和tasm中很轻易的完称。只要记住你可以写过程,而且它们可以由参数。一个重要的地方:
eax几乎总是用来装一个过程的返回值。
对于windows函数也是如此。但然,你可以在你的过程使用其他的寄存器,但这是标准。