News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Newbie requesting aid

Started by kateeus, January 20, 2009, 05:59:32 AM

Previous topic - Next topic

kateeus

Hi all, hope you are doing well.

My first post btw :)

I just recently started learning assembly and ran in to a trouble. I wrote the following code:

.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

.code

start:

mov eax, sval ( input ( "First: " ) )
mov ecx, sval ( input ( "Second: " ) )

add ecx, eax

print str$ ( ecx)

exit

end start


It prompts the user for two numbers and after that spits out the sum. It is working as it should, but as soon as I try to add some text in front of the sum, for example "The sum is: ", it assembles and runs fine but the sum is way off, 2088832678 to be exact. The way I try to add the text is the following: print chr$ ("The sum is: " )

I place it right before the part where it prints out the sum. If some of the gurus here could answer this in a way that I would understand why it gives out exactly this number 2088832678 and how to do it correctly I would be very thankful.

Awaiting your answers  :U

MichaelW

Hello kateeus, welcome to the forum. The problem is that in the register-preservation convention that is used by Windows and by the procedures in the MASM32 library, EAX, ECX and EDX are not preserved. This means that the values of these registers may change across any call to the Windows API or the MASM32 library. Of the general purpose registers only ESP, EBP, EBX, ESI. and EDI can be depended on to retain their values. One possible fix would be to preserve ECX around the statement that is changing it:

    push ecx
    print chr$ ("The sum is: " )
    pop ecx

eschew obfuscation

kateeus

YEAH!

That was just the kind of answer I was looking for  :cheekygreen:

Thank you for the fast reply, that helped a lot.

kateeus

I must correct my self here.

I just noticed that the code I posted was actually never working correctly :D

It only gave correct sums when the result was even number. I came to the conclusion that it added up only the ecx with it self ( ecx + ecx ). So what is the reason for this? It woud seem that as soon as it prompted and received the second number it also overwrote the eax register with that number resulting in incorrect result(or at least that is how I figured it out, correct me if I misinterpreted it). So I fought back and came up with this bad boy: .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

.code

start:

mov eax, sval ( input ( "First: " ) )
push eax
mov ecx, sval ( input ( "Second: " ) )
push ecx

print chr$ ( "Sum: " )
pop eax
pop ecx
add eax, ecx

print str$ ( eax )

exit

end start


This one is working perfectly. Why? Well it first prompts number1 stores it to eax and then it pushes eax on top of the "stack" so it stays there unchanged, then it does the same with ecx. After that it pops both values out BUT it does that after the "Sum: " message. After all that it adds up the values that did not change thanks to being on top of the stack and then it prints out the correct result.

This is probably not the fastest/most practical way of doing this, but it helps me understand the processes better(if I understand them at all  :snooty:)

Correct me if I'm misunderstanding parts or all of the stuff that I just explained, thanks.

Mark Jones

Welcome, that looks correct. :bg

What is worth remembering is that anything which is not a single instruction (API calls, macros such as "input", "print", even "exit") generally may trash EAX, ECX, and EDX.

Alternatively, since this is a simple console application, you could also use ESI and EDI to hold the two values and not push anything onto the stack. (Do not leave ESI and EDI modified in a windowed application however, as Windows uses those values internally.)

You could also try creating a .data? section comprised of two DWORDs, and store the values in there. i.e.,


.data?
    myValue1    DD  ?    ; each DD reserves 4 bytes (a dword) beginning at its label
    myValue2    DD  ?
.code
... ;experiment with placing the input into "myValueX" instead of a register. :)
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

kateeus

Thanks for your input Mark, I tried what you suggested. I created two uninitialized DWORD variables "input1" and "input2", but was unable to get the addition part to work. Here is what I came up with: data?

input1 dd ?
input2 dd ?

.code

start:

print chr$ ( "I will sum two integers for you" )

mov input1, sval ( input ( "Number1: " ) )
mov input2, sval ( input ( "Number2: " ) )
add input1, input2

print chr$ ("The sum is: " )
print str$ ( input1 )

exit

end start


I believe that the: add input1, input2 syntax is somehow messed up, that is the part where the error is reported to be by the assembler. Perhaps someone can enlighten me on how to do any arithmetic operation, add, sub etc to two variables there must be something I'm missing here. Anyway after a little trying I came up with a solution, and it only involved one uninitialized variable. Heres how it looks: .data?

input1 dd ?

.code

start:

print chr$ ( "I will sum two integers for you", 13, 10 )

mov input1, sval ( input ( "Number1: " ) )
add input1, sval ( input ( "Number2: " ) )


print chr$ ( "The sum is: " )
print str$ ( input1 )

exit

end start


This one is by far the most practical version in my opinion, readability is good and it is also shorter then the first working version with the push and pop.

Thanks again for helping a newb

Mark Jones

Quote from: kateeus on January 20, 2009, 04:01:28 PM
...I believe that the: "add input1, input2" syntax is somehow messed up, that is the part where the error is reported to be by the assembler...

Yes this is as expected. If you take a look in \masm32\help\opcodes.chm under ADD, you'll see the supported "modes" of the ADD instruction. "r" is register, "m" is memory, and "imm" is an immediate value, so the ADD instruction can take all of these only as defined by this table.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

kateeus

Yes, this will be an interesting read, thans for the pointer :) Gonna spend some time studying those opcodes now.