"option zerolocals : 1" should (at least to my understanding) initialize all locals of a procedure to zero, but it doesn´t
32 bit code for UASM:
...
include windows.inc
includelib kernel32.lib
includelib user32.lib
option ZEROLOCALS : 1
.data
MsgCaption db "Test",0
MsgBoxText db "works",0
.code
start proc
;***************************************************************************
;
;***************************************************************************
local n :dword
LOCAL rct :RECT ;is created on the stack
int 3
mov eax, rct.left
mov rct.left, 1
;int 3 ;at this point i would expect EAX to be zero
mov eax, rct.left
mov ebx, n ;at this point EAX = 1, which is expected
invoke MessageBox, NULL, addr MsgBoxText, addr MsgCaption, MB_OK
invoke ExitProcess, NULL
ret
start endp
end start
;*************************************************************************************
; code generated
;*************************************************************************************
;00081000 <Mod> 55 PUSH EBP
;00081001 8BEC MOV EBP, ESP
;00081003 83C4 EC ADD ESP, -14
;00081006 CC INT3
;00081007 8B45 EC MOV EAX, DWORD PTR SS:[EBP-14]
;0008100A C745 EC 01000000 MOV DWORD PTR SS:[EBP-14], 1
;00081011 8B45 EC MOV EAX, DWORD PTR SS:[EBP-14]
;00081014 8B5D FC MOV EBX, DWORD PTR SS:[EBP-4]
;00081017 6A 00 PUSH 0
;00081019 68 00300800 PUSH Sample2.00083000 ; ASCII "Test"
;0008101E 68 05300800 PUSH Sample2.00083005 ; ASCII "works"
;00081023 6A 00 PUSH 0
;00081025 FF15 08200800 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA
;0008102B 6A 00 PUSH 0
;0008102D FF15 00200800 CALL DWORD PTR DS:[<&KERNEL32.ExitProcess>] ; kernel32.ExitProcess
;00081033 8BE5 MOV ESP, EBP
;00081035 5D POP EBP
;00081036 C3 RETN
The generated code doesn´t change regardless of the actual setting of "option zerolocals" (0 or 1), stepping through the code shows, that (in my case) rect.left is 0x48 (not zero). The reserved stack space for locals isn´t cleared (set to zero).
What am i doing wrong?
Thanks
JK
Hi JK,
Another test :
.386
.model flat,stdcall
option casemap:none
option ZEROLOCALS:1
ExitProcess PROTO :DWORD
printf PROTO C :VARARG
.data
string1 db '%u %u',0
.code
start:
call main
invoke ExitProcess,0
main PROC
LOCAL x:DWORD
LOCAL y:DWORD
invoke printf,ADDR string1,\
x,y
ret
main ENDP
END start
Disassembling the object module :
_start PROC NEAR
call _main@0
push 0
call _ExitProcess@4
_main@0 LABEL NEAR
push ebp
mov ebp, esp
add esp, -8
push dword ptr [ebp-8H]
push dword ptr [ebp-4H]
push offset _string1
call _printf
add esp, 12
leave
ret
_start ENDP
The two locals x and y are not set to 0.
Tested with UASM v2.49, Jun 21 2019
Can the option be switched on and off repeatedly? For performance reasons, I don't think it's a good idea to clear all local variables throughout a whole program. For example, in my editor's source I use ClearLocals only in 45 of 200 procedures.
MyTest proc uses edi esi ebx arg1:DWORD, arg2:RECT, TheString
LOCAL v1, v2, rc:RECT, buffer[100]:BYTE ; ordinary locals first
_Local v3=123, v4:REAL4=123.456 ; see SetFloat for allowed syntax
_Local x$="Hello World", y$=TheString ; strings can be initialised, too
ClearLocals ; first line after the LOCALs
MsgBox 0, Str$("The value of v1: %i", v1), "Test clv:", MB_OK
ret
MyTest endp
The option can be switched on/off at will. I will investigate why it doesn't work anymore.
In case you don't find the bug: there are handy macros around :tongue:
MyTest proc uses edi esi ebx arg1:DWORD, arg2:RECT, TheString
LOCAL v1, v2, rc:RECT, buffer[100]:BYTE ; ordinary locals first
_Local v3=123, v4:REAL4=123.456
_Local x$="Hello World", y$=TheString ; strings can be initialised, too
ClearLocals ; first line after the LOCALs
MsgBox 0, Str$("The value of v1: %i", v1), "Test clv:", MB_OK
ret
MyTest endp
QuoteI will investigate why it doesn't work anymore.
Thanks !
The option is only available in 64bit code. 32bit doesn't warn that it will have no affect. For 32bit code I'd use the macros. I will update UASM to warn that it has no effect in 32bit mode.