在堆栈中创建命名变量
Creating named variables in the stack
有没有办法在堆栈中创建命名变量而不是通过偏移量引用它们:
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
FASM
FASM 通过 ad-hoc FASM 自带的特制宏来支持局部变量。
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
也就是编译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
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
The %$localsize
variable is used internally by the %local
directive and must be defined within the current context before the %local directive may be used.
其他草率的方法
可以
%define SUPER_VAR ebp-4
%define MEGA_VAR ebp-8
mov DWORD [SUPER_VAR], 0xf
mov DWORD [MEGA_VAR], 0xff
然而,这隐藏了变量在堆栈中并假定正确设置帧指针的事实。
稍微好一点的方法:
%define SUPER_VAR 4
%define MEGA_VAR 8
mov DWORD [ebp-SUPER_VAR], 0xf
mov DWORD [ebp-MEGA_VAR], 0xff
汇编程序员之道
真正的汇编程序员使用注释[citation needed]来陈述他们代码的意图。
并且只在vi
写代码。或者是 emacs
?
mov DWORD [ebp-4], 0xf ;SUPER_VAR
mov DWORD [ebp-8], 0xff ;MEGA_VAR
汇编语言的主要优势在于其简单的语法和完整的信息方法(没有任何隐藏,程序员控制一切)。
虽然使用 high-level 宏 2 没有任何问题,但混合高级和低级方法会导致源文件更难被专家解析。
此外,从本体论的角度来看,它没有什么意义:如果你想使用 high-level 特性,那么像 C 这样的语言更适合,必须重新考虑使用汇编。相反,如果您想学习如何进行 low-level 编程,那么此类宏会阻碍学习过程。
最后,宏不是魔法。虽然非常灵活,但程序员迟早会遇到他们的限制。
例如,我没有深入研究 FASM 和 NASM 对 aligned 局部变量的支持。
1 此时这不再是汇编了...
2 High-level 宏让你轻松重构代码,这一点非常重要。不过,人们应该暂停片刻,质疑自己在重要重构 expected/needed.
时使用汇编的选择
FASM 执行此类操作的本机方法是通过 virtual
指令:
参数:
virtual at ebp + 8
.arg1 dd ?
.arg2 dq ?
end virtual
对于局部变量:
virtual at ebp - 10h ; the offset is the size of the local variables area.
.var1 dd ?
.local_array rb 12
end virtual
不同种类的 proc
宏在内部使用 virtual
。
有没有办法在堆栈中创建命名变量而不是通过偏移量引用它们:
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
FASM
FASM 通过 ad-hoc FASM 自带的特制宏来支持局部变量。
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
也就是编译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
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
The
%$localsize
variable is used internally by the%local
directive and must be defined within the current context before the %local directive may be used.
其他草率的方法
可以
%define SUPER_VAR ebp-4
%define MEGA_VAR ebp-8
mov DWORD [SUPER_VAR], 0xf
mov DWORD [MEGA_VAR], 0xff
然而,这隐藏了变量在堆栈中并假定正确设置帧指针的事实。
稍微好一点的方法:
%define SUPER_VAR 4
%define MEGA_VAR 8
mov DWORD [ebp-SUPER_VAR], 0xf
mov DWORD [ebp-MEGA_VAR], 0xff
汇编程序员之道
真正的汇编程序员使用注释[citation needed]来陈述他们代码的意图。
并且只在vi
写代码。或者是 emacs
?
mov DWORD [ebp-4], 0xf ;SUPER_VAR
mov DWORD [ebp-8], 0xff ;MEGA_VAR
汇编语言的主要优势在于其简单的语法和完整的信息方法(没有任何隐藏,程序员控制一切)。
虽然使用 high-level 宏 2 没有任何问题,但混合高级和低级方法会导致源文件更难被专家解析。
此外,从本体论的角度来看,它没有什么意义:如果你想使用 high-level 特性,那么像 C 这样的语言更适合,必须重新考虑使用汇编。相反,如果您想学习如何进行 low-level 编程,那么此类宏会阻碍学习过程。
最后,宏不是魔法。虽然非常灵活,但程序员迟早会遇到他们的限制。
例如,我没有深入研究 FASM 和 NASM 对 aligned 局部变量的支持。
1 此时这不再是汇编了...
2 High-level 宏让你轻松重构代码,这一点非常重要。不过,人们应该暂停片刻,质疑自己在重要重构 expected/needed.
FASM 执行此类操作的本机方法是通过 virtual
指令:
参数:
virtual at ebp + 8
.arg1 dd ?
.arg2 dq ?
end virtual
对于局部变量:
virtual at ebp - 10h ; the offset is the size of the local variables area.
.var1 dd ?
.local_array rb 12
end virtual
不同种类的 proc
宏在内部使用 virtual
。