汇编语言非双字局部变量
在声明不同大小的局部变量时,LOCAL 伪指令的操作会变得很有趣。每个变量都按照其大小来分配空间:8 位的变量分配给下一个可用的字节,16 位的变量分配给下一个偶地址(字对齐),32 位变量分配给下一个双字对齐的地址。
现在来看几个例子。首先,Example 过程含有一个局部变量 var1,类型为 BYTE:
过程 Example2 含一个双字局部变量和一个字节局部变量:
如果要创建超过几百字节的数组作为局部变量,那么一定要确保为运行时堆栈预留足够的空间。此时可以使用 STACK 伪指令。比如,在 Irvine32 链接库中,要预留 4096 个字节的堆栈空间:
现在来看几个例子。首先,Example 过程含有一个局部变量 var1,类型为 BYTE:
Example1 PROC LOCAL var1:byte mov al,var1 ;[EBP-1] ret Example1 ENDP由于 32 位模式中,堆栈偏移量默认为 32 位,因此,var1 可能被认为会存放于 EBP-4 的位置。实际上,如下图所示,MASM 将 EBP 减去 4,但是却把 var1 存放在 EBP-1,其下面的三个字节并未使用(用 nu 标记,表示没有使用)。图中,每个方块表示一个字节。
过程 Example2 含一个双字局部变量和一个字节局部变量:
Example2 PROC
local temp:dword, SwapFlag:BYTE
...
ret
Example2 ENDP
push ebp mov ebp, esp add esp,0FFFFFFF8h ; ESP+(-8) mov eax,[ebp-4] ; temp mov bl,[ebp-5] ; SwapFlag leave ret虽然 SwapFlag 只是一个字节变量,但是 ESP 还是会下移到堆栈中下一个双字的位置。下图以字节为单位详细展示了堆栈的情况:SwapFlag 确切的位置以及位于其下方的三个没有使用的空间(用 nu 标记)。图中,每个方块表示一个字节。
如果要创建超过几百字节的数组作为局部变量,那么一定要确保为运行时堆栈预留足够的空间。此时可以使用 STACK 伪指令。比如,在 Irvine32 链接库中,要预留 4096 个字节的堆栈空间:
.stack 4096
对嵌套调用来说,不论程序执行到哪一步,运行时堆栈都必须大到能够容纳下全部的活跃局部变量。比如在下面的代码中,Sub1 调用 Sub2,Sub2 调用 Sub3,每个过程都有一个局部数组变量:
Sub1 PROC
local array1 [50]:dword ; 200 字节
callSub2
...
ret
Sub1 ENDP
Sub2 PROC
local array2 [80]:word ; 160 字节
callSub3
...
ret
Sub2 ENDP
Sub3 PROC
local array3 [300]:dword ; 1200 字节
...
ret
Sub3 ENDP