2016-09-22 53 views

回答

2

这听起来像你问的是,你可以在运行时动态分配空间。答案是肯定的,最常用的方法之一是;

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个字节。

还有其他几种分配空间的方式,也许可以修改您的问题以更具体地了解您需要的内容,然后我或其他人可以基于此给出示例。

+0

了这种技术如果我想用文本来做到这一点,会有什么改变?或者我只需要做13,10,“消息$”? –

+0

我想要做的就是为我的所有MASM程序制作一个“骨架”。所以,我为诸如打印,添加,减少等等创建了一大堆宏。我想创建另一个宏用于创建变量(就像高级语言一样,所以我可以键入“int [name]”然后使用该变量) –

+0

大多数情况下,您所指的称为_template_。虽然可行,但确实远远超出了* SO *的范围,它更加面向特定的问题。 –

2

我不知道其他的汇编,但在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

+0

这是一个糟糕的滥用'call'来推送字符串地址作为返回地址的糟糕透顶。它将在现代CPU上执行得不好,因为[不匹配的调用/ ret会中断返回地址预测器堆栈。](http://stackoverflow.com/questions/22442766/return-address-prediction-stack-buffer-vs-stack-存储返回地址)。 –

+0

更好的办法是将消息放在'.rodata'部分,并正常地“推”它的地址。你仍然可以用一个宏切换(切换到'section .rodata',db字符串,然后切换回你之前的任何部分)。链接器将收集所有字符串在只读数据部分,并保持代码不被数据中断。 –

+0

我看到你从DOS例子中得到了这个技巧。如果代码大小是唯一重要的东西,这是一个有趣的想法。然而,即使在旧的CPU上,性能也值得怀疑,因为任何具有L1 I和D高速缓存分割的东西都需要在D高速缓存中保存该字符串的行,以及当某些内容读取字符串时我缓存。它也仅适用于旧的ABI,其中args通过栈而不是寄存器。对于286或386时代的CPU来说这是一个很酷的主意,但现在不是一个好主意。 –