【问题标题】:Assembly define variable in .code (MASM)汇编在 .code (MASM) 中定义变量
【发布时间】:2017-01-30 10:27:48
【问题描述】:

有没有办法在 .code 部分创建一个变量,而不是 .data?我只是觉得很有限,因为我无法动态地创建变量。

【问题讨论】:

    标签: variables assembly masm


    【解决方案1】:

    听起来您要问的是,您能否在运行时动态分配空间。答案是肯定的,最常见的方法之一是;

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

    还有其他几种分配空间的方法,也许可以修改您的问题以更具体地说明您的需求,然后我或其他人可以在此基础上给您一个示例。

    【讨论】:

    • 如果我想用文本来做这个,会有什么改变吗?还是我只需要做 13, 10, "Message$" ?
    • 我要做的几乎就是为我所有的 MASM 程序制作一个“骨架”。所以,我正在为打印、加法、减法等创建一大堆宏。我想做另一个宏来创建变量(就像高级语言一样,所以我可以输入“int [name]”然后使用那个变量)
    • 您所指的通常称为模板。虽然可行,但它确实远远超出了 SO 的范围,后者更面向特定问题。
    【解决方案2】:

    我不知道其他汇编程序,但在 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 字符串,然后切换回您之前所在的任何部分)。链接器会将所有字符串收集到只读数据部分,并让代码不受数据的干扰。
    • 我看到你从一个 DOS 示例中得到了这个技巧。如果代码大小是唯一重要的事情,这是一个有趣的想法。但是,即使在旧 CPU 上,性能也是有问题的,因为任何具有拆分 L1 I 和 D 缓存的东西都需要在 D 缓存中保存字符串的行,以及在读取字符串时需要缓存的行。它也只对坏的旧 ABI 有用,其中 args 在堆栈而不是寄存器上传递。对于 286 或 386 时代的 CPU,这是一个很酷的主意,但现在不是一个好主意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多