有没有什么办法可以在.code部分创建一个变量,而不是.data?我只是觉得有限,因为我无法在飞行中变化变量。程序集在.code(MASM)中定义变量
回答
这听起来像你问的是,你可以在运行时动态分配空间。答案是肯定的,最常用的方法之一是;
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,使用im这个宏,这样一说,保存在栈上的某些变量的地址,
@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'来推送字符串地址作为返回地址的糟糕透顶。它将在现代CPU上执行得不好,因为[不匹配的调用/ ret会中断返回地址预测器堆栈。](http://stackoverflow.com/questions/22442766/return-address-prediction-stack-buffer-vs-stack-存储返回地址)。 –
更好的办法是将消息放在'.rodata'部分,并正常地“推”它的地址。你仍然可以用一个宏切换(切换到'section .rodata',db字符串,然后切换回你之前的任何部分)。链接器将收集所有字符串在只读数据部分,并保持代码不被数据中断。 –
我看到你从DOS例子中得到了这个技巧。如果代码大小是唯一重要的东西,这是一个有趣的想法。然而,即使在旧的CPU上,性能也值得怀疑,因为任何具有L1 I和D高速缓存分割的东西都需要在D高速缓存中保存该字符串的行,以及当某些内容读取字符串时我缓存。它也仅适用于旧的ABI,其中args通过栈而不是寄存器。对于286或386时代的CPU来说这是一个很酷的主意,但现在不是一个好主意。 –
了这种技术如果我想用文本来做到这一点,会有什么改变?或者我只需要做13,10,“消息$”? –
我想要做的就是为我的所有MASM程序制作一个“骨架”。所以,我为诸如打印,添加,减少等等创建了一大堆宏。我想创建另一个宏用于创建变量(就像高级语言一样,所以我可以键入“int [name]”然后使用该变量) –
大多数情况下,您所指的称为_template_。虽然可行,但确实远远超出了* SO *的范围,它更加面向特定的问题。 –