在堆栈中创建命名变量

Kev*_*vin 4 assembly nasm fasm

有没有办法在堆栈中创建命名变量,而是通过offset来引用它们:

sub esp, 0x10 ; 4 variables of 4 bytes

mov DWORD [ebp-4], 0xf ; 1st var
mov DWORD [ebp-8], 0xff  ; 2nd var
; and so on
Run Code Online (Sandbox Code Playgroud)

Mar*_*oom 8

FASM

FASM通过FASM自身附带的ad-hoc制作宏支持局部变量.

include 'win32ax.inc' 

.code

  start:
        mov ax, 1

        call foo


  proc foo

      ;Local variables

      locals
        var1 dd ?
        var2 dw ?
      endl


      ;Use them as expected
      mov eax, [var1]
      lea ebx, [var2]

   ret
  endp 
Run Code Online (Sandbox Code Playgroud)

也就是说编译1

:00401000 66B80100                mov ax, 0001
:00401004 E800000000              call 00401009
:00401009 55                      push ebp
:0040100A 89E5                    mov ebp, esp
:0040100C 83EC08                  sub esp, 00000008
:0040100F 8B45F8                  mov eax, dword ptr [ebp-08]
:00401012 8D5DFC                  lea ebx, dword ptr [ebp-04]
:00401015 C9                      leave
:00401016 C3                      ret
Run Code Online (Sandbox Code Playgroud)

NASM

NASM也使用%local指令支持局部变量.

引自手册:

silly_swap: 
    %push mycontext             ; save the current context 
    %stacksize small            ; tell NASM to use bp 
    %assign %$localsize 0       ; see text for explanation 
    %local old_ax:word, old_dx:word 

    enter   %$localsize,0   ; see text for explanation 
    mov     [old_ax],ax     ; swap ax & bx 
    mov     [old_dx],dx     ; and swap dx & cx 
    mov     ax,bx 
    mov     dx,cx 
    mov     bx,[old_ax] 
    mov     cx,[old_dx] 
    leave                   ; restore old bp 
    ret                     ; 

    %pop                        ; restore original context
Run Code Online (Sandbox Code Playgroud)

%$localsize变量在%local指令内部使用,必须在当前上下文中定义,然后才能使用%local指令.

其他草率的方法

有人可以

%define SUPER_VAR ebp-4
%define MEGA_VAR ebp-8

mov DWORD [SUPER_VAR], 0xf
mov DWORD [MEGA_VAR], 0xff
Run Code Online (Sandbox Code Playgroud)

然而,这隐藏了变量在堆栈中并假设正确设置的帧指针的事实.

一个稍好的方法:

%define SUPER_VAR 4
%define MEGA_VAR 8

mov DWORD [ebp-SUPER_VAR], 0xf
mov DWORD [ebp-MEGA_VAR], 0xff
Run Code Online (Sandbox Code Playgroud)

汇编程序员的方式

真正的汇编程序员使用注释[citation needed]来陈述其代码的意图.
并且仅在代码中编写代码vi.或者是emacs

mov DWORD [ebp-4], 0xf           ;SUPER_VAR
mov DWORD [ebp-8], 0xff          ;MEGA_VAR
Run Code Online (Sandbox Code Playgroud)

汇编语言的关键优势在于其简单的语法和完整的信息方法(没有任何东西是隐藏的,程序员控制着一切).

虽然使用高级宏2没有任何问题,但混合高级和低级方法会导致源文件难以为专家解析.

此外,从本体论的角度来看,它没有多大意义:如果你想使用高级功能,那么像C这样的语言更适合,必须重新考虑使用汇编.相反,如果你想学习如何进行低级编程,那么这些宏是学习过程的障碍.

最后,宏不是魔术.虽然很快就会非常灵活,程序员会遇到他们的限制.
例如,我没有挖掘FASM和NASM支持对齐的局部变量.


1此时这不再是汇编...
2高级宏允许您轻松地重构代码,这非常重要.人们应该暂停一下,质疑自己在预期/需要进行重要重构时使用汇编的选择.

  • "真正的汇编程序员使用注释"......在阅读其他人的代码时,我有时会认为它"很难对我进行编码,所以你应该很难阅读它";-) (2认同)