Is there any way to create named variables in the stack rather refer to them by 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
Is there any way to create named variables in the stack rather refer to them by 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
FASM supports local variables through ad-hoc crafted macros that are shipped with FASM itself.
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
That is compiled1 into
: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 support local variables too with the use of the %local directive.
Quoting from the manual:
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.
One could
%define SUPER_VAR ebp-4
%define MEGA_VAR ebp-8
mov DWORD [SUPER_VAR], 0xf
mov DWORD [MEGA_VAR], 0xff
However this hides the fact that the variables are in the stack and assume a correctly set frame pointer.
A slightly better approach:
%define SUPER_VAR 4
%define MEGA_VAR 8
mov DWORD [ebp-SUPER_VAR], 0xf
mov DWORD [ebp-MEGA_VAR], 0xff
Real assembler programmers use comments[citation needed] to state the intentions of their code.
And write code only in vi
. Or it was emacs
?
mov DWORD [ebp-4], 0xf ;SUPER_VAR
mov DWORD [ebp-8], 0xff ;MEGA_VAR
The key strengths of the assembly language are its simple syntax and the full information approach (nothing is hidden, the programmer controls everything).
While there is nothing wrong with using high-level macros2, mixing high and low level approaches result in a source file that is harder to parse for an expert.
Furthermore it makes little sense from an ontological point of view: if you want to use high-level features then a language like C is better suited and the use of assembly must be reconsidered. Au contraire, if you want to learn how to do low-level programming then such macros are an hindrance to the learning process.
Finally, macros are not magic. While very flexible soon or later a programmer will encounter their limit.
For example, I haven't dug into the FASM and NASM support for aligned local variables.
1 At this point this is not assembly anymore...
2 High-level macros let you refactor the code easily, which is very important. One should pause a moment though, questioning itself about the choice made of using assembly when important refactoring is expected/needed.
vi
or emacs
, just joe
) –
Clishmaclaver %local
link changed to nasm.us/doc/nasmdoc4.html#section-4.10.3 –
Durward The FASM native way of doing such things is through virtual
directive:
For arguments:
virtual at ebp + 8
.arg1 dd ?
.arg2 dq ?
end virtual
For local variables:
virtual at ebp - 10h ; the offset is the size of the local variables area.
.var1 dd ?
.local_array rb 12
end virtual
The different kind of proc
macros use virtual
internally.
© 2022 - 2024 — McMap. All rights reserved.
r32 + equ_offsets
to mimic OOP, that part worked OK-ish. If you group several variables into "objects", create functions to manipulate them, likelea ebx,[ebp-30] ; object "X" instance
call Xsomething
... Then I finally learned C++. – Clishmaclaver