0

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

6
  • mov [dewit], 0 or maybe mov word ptr [dewit], 0`? Also define "didn't work". Commented Jan 15, 2016 at 21:43
  • Didnt work - i.e. It ran into error, i think.. The program 'stopped working' at that point Commented Jan 15, 2016 at 21:47
  • That's not enough information, provide a minimal reproducible example. You might want to look at generated assembly code as well. Also, consider not using helper features until you can do it by hand too, and understand what the assembler is doing. Commented Jan 15, 2016 at 21:52
  • I tried what u said, it didnt work.. Now why all the downvotes?.. Commented Jan 15, 2016 at 22:08
  • 1
    Because your code can't compile as is. @Jester asked for a minimal code that reproduces your problem: where minimal means: a code that we can compile on our side. For ex. Your code doesn't have the usual header statement, Print and Exit aren't defined anywhere and are not statements that MASM can understand. Commented Jan 16, 2016 at 18:15

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! It will take me a while to check out all u said.. But it has been helpful
Btw, which debugger u use?.. @neitsa
0

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

6 Comments

Cool! Now what if i want to print out a word?.. Cause i see, as u said, that it prints the value of the number stored in the variable..
@daniel You could move the word from memory to a 32-bit register using something like the movsz instruction which would sign extend a 16 bit register or memory operand into a 32-bit register. That 32-bit register could then be used with str$
@daniel : I may have misunderstood. Do you mean WORD as in a 16-bit value, or text like "hello there"?
To print out a string you can do something like this.Define a string in your DATA section like msg1 db "Hello There",0 and then use print to print the string. You'd have to do it like print offset msg1 . You need the offset keyword so that you want print to use the address of msg1, not what msg1 points at. You can also print a string with an instruction like print "hello world"
You can allocate an array of bytes on the stack, copy a string to it, and then print it out with something like LOCAL locMsg[128]:byte to define a buffer of 128 bytes, fn lstrcpy, addr locMsg, "Hello World" to place a string in it, and then to print it from a LOCAL variable you'd use print addr locMsg (you need ADDR in this case because locMsg is stack based inside the function)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.