【发布时间】:2017-01-30 10:27:48
【问题描述】:
有没有办法在 .code 部分创建一个变量,而不是 .data?我只是觉得很有限,因为我无法动态地创建变量。
【问题讨论】:
有没有办法在 .code 部分创建一个变量,而不是 .data?我只是觉得很有限,因为我无法动态地创建变量。
【问题讨论】:
听起来您要问的是,您能否在运行时动态分配空间。答案是肯定的,最常见的方法之一是;
int Func ()
{
int Distance;
Distance = 132;
}
在汇编中这看起来像
push rbp
mov rbp, rsp
sub rsp, 8 Now RSP points to what is essentially Distance
mov dword [rbp-8], 132
另一个值可以存储@ [rbp-4] 作为双字只需要 4 个字节。
还有其他几种分配空间的方法,也许可以修改您的问题以更具体地说明您的需求,然后我或其他人可以在此基础上给您一个示例。
【讨论】:
我不知道其他汇编程序,但在 tasm 中,我使用这个宏,就像这个一样,将某些变量的地址保存在堆栈上,
@pushsz macro msg2psh, empty
local next_instr
ifnb <empty>
%out too many arguments in macro '@pushsz'
.err
endif
call next_instr ; pushes the address of the message as the return address
db msg2psh,0
next_instr:
endm
你可以这样使用它:
push 0
@pushsz "hello world"
@pushsz "some text"
push 0
call MessageBoxA
如您所见,字符串与指令一起编码,当然您不仅可以使用字符串,还可以使用其他类型,但是请注意,这种技术会修改堆栈,(参见上面的 stdcall 示例),所以您应该在使用后将其弹出或恢复堆栈。
另外要考虑的是内存的读/写访问,如果内存不可写,你在里面存了东西,就会发生异常。给出的宏假设数据是只读的,这是另一个例子:
@pushsz "My Stringzero here"
pop eax ; eax contains the address of the string
我认为将它转换为 MASM 宏语法并不难,抱歉不是 masm 用户,我在这里得到了这个技术https://vxheaven.org/29a/29a-2/29a-2.3_3
【讨论】:
call 的可怕滥用,将字符串的地址作为返回地址。由于mismatched call/ret breaks the return-address predictor stack.,它将在现代 CPU 上表现不佳。
.rodata 部分中,并且通常只将push 其地址。您仍然可以使用一个宏来完成所有这些操作(切换到section .rodata,db 字符串,然后切换回您之前所在的任何部分)。链接器会将所有字符串收集到只读数据部分,并让代码不受数据的干扰。