Reputation: 318
In assembly coding, working with masm32.
How can i put a value into a variable, that is not defiened at the .data segment, but by the LOCAL decleration?
thous:
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print dewit
ret
main endp
end start
I tried something like this:
Mov dewit, 0
It didnt work. However, this code:
Mov dewit, input("enter a number")
Did put a value into it.
Anybody?
** the LOCAL decleration can only be in a procedure
Upvotes: 0
Views: 1834
Reputation: 47603
Since you are using MASM32 If you are trying to print out a 32-bit value try doing it this way with str$
:
print str$(dewit)
This converts the 32-bit value at the memory location dewit
into a string, and that string is printed on the console. This also work for an immediate value as well:
print str$(100)
And a register:
print str$(eax)
You can use $ustr
as well if you wish to print the unsigned value.
These macros are described in the High Level Macro help that comes with MASM32 SDK
Upvotes: 0
Reputation: 8176
You could have found this with a debugger. Here is the beginning of the code viewed from a debugger:
CPU Disasm
Address Command Comments
00401000 CALL 0040100C ; call main
00401005 PUSH 0 ; /ExitCode = 0
00401007 CALL <JMP.&kernel32.ExitProcess> ; \KERNEL32.ExitProcess
0040100C PUSH EBP ; main
0040100D MOV EBP,ESP
0040100F ADD ESP,-4
00401012 MOV DWORD PTR SS:[LOCAL.1],0 ; dewit = 0
00401019 PUSH DWORD PTR SS:[LOCAL.1] ; /Arg1 => 0
0040101C CALL 00401024 ; print
00401021 LEAVE
00401022 RETN
So print
is called (remember, print
is a macro, so its expanded once compiled). Remeber you pushed 0 to print
:
CPU Disasm
Address Command Comments
00401024 PUSH EBP ; print (guessed Arg1)
00401025 MOV EBP,ESP
00401027 ADD ESP,-0C
0040102A PUSH -0B ; /StdHandle = STD_OUTPUT_HANDLE
0040102C CALL <JMP.&kernel32.GetStdHandle> ; \KERNEL32.GetStdHandle
00401031 MOV DWORD PTR SS:[LOCAL.1],EAX
00401034 PUSH DWORD PTR SS:[Arg1] ; /Arg1 => [Arg1] *** push 0 ***
00401037 CALL 00401060 ; \so.00401060
See at line 0x00401034
, 0 is pushed as an argument for a call.
Let's see the code:
CPU Disasm
Address Command Comments
00401060 MOV EAX,DWORD PTR SS:[Arg1] ; eax = 0
00401064 LEA EDX,[EAX+3]
00401067 PUSH EBP
00401068 PUSH EDI
00401069 MOV EBP,80808080
0040106E /MOV EDI,DWORD PTR DS:[EAX] ; trying to dereference [0]...
The code is trying to read at address 0 (aka NULL pointer bug), which is a big no no.
Looking at print
macro in macros.asm
, it seems that this macro doesn't do any formatting, you should then use printf
.
Your code fixed (you need msvcrt.inc
and msvcrt.lib
for printf
macro, which is still defined in macros.asm
):
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\msvcrt.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
.data
format_string db "value: %d", 0
.code
start:
call main
exit
main proc
LOCAL dewit:DWORD
mov dewit, 0
print "printing value: "
printf ("value: %d", dewit)
ret
main endp
end start
Roughly the same code without any include:
; compile and link with:
; ml test.asm /link /subsystem:console /defaultlib:kernel32.lib /defaultlib:msvcrt.lib
.686
.model flat, stdcall
option casemap: none
ExitProcess PROTO STDCALL :DWORD
externdef _imp__printf:PTR c_msvcrt
crt_printf equ <_imp__printf>
.data
fmt db "value: %d", 0
.code
start:
call MyFunc
invoke ExitProcess, 0
ret
MyFunc proc
LOCAL foo:DWORD
mov foo, 42
push foo
push offset fmt
call crt_printf
ret
MyFunc endp
end start
I also completely agree with @Jester:
Also, consider not using helper features until you can do it by hand too, and understand what the assembler is doing
Macros are great but unless you can understand what they do and achieve the same by hand, you should refrain from using them. They hide way too much things from beginners' eyes.
Upvotes: 2