汇编语言中的内存访问、常量、变量与数据类型
1. 栈操作与数据访问
1.1 栈数据弹出优化
在栈操作中,有一种代码可以将数据从栈中弹出而不移动其位置。例如,通过向 ESP 寄存器添加一个常量来移除栈中的数据,这种方式比使用两条虚拟的 pop 指令更快,因为它可以用一条 add 指令移除任意数量的字节。不过要注意,必须保持栈在双字边界上对齐,所以在从栈中移除数据时,应始终向 ESP 添加一个 4 的倍数的常量。
1.2 不弹出栈数据的访问
有时候,我们将数据压入栈后,可能想获取该数据的值副本,或者改变其值而不实际将其从栈中弹出。80x86 的 [reg32 + offset] 寻址模式为此提供了机制。
例如,执行以下两条指令后:
push( eax );
push( ebx );
若要访问原始的 EBX 值而不将其从栈中移除,可使用 [ESP + offset] 寻址模式。如 mov( [esp+4], eax );
会将从内存地址 ESP + 4 开始的 4 个字节复制到 EAX 寄存器,此值恰好是之前压入栈的 EAX 的值。
但要注意,每次压入或弹出数据时,ESP 到栈中值的偏移量都会改变。滥用此特性会使代码难以修改。
下面是一个更安全的代码示例:
push( eax );
push( ebx );
<< Some code that wi