News:

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

masm problem?

Started by RedXVII, June 19, 2006, 09:06:13 PM

Previous topic - Next topic

RedXVII

here it is, names in capslock are in .const

.repeat
mov al, [edi]
.if al
mov temp1, edi
invoke myfunc, edi
mov edi, temp1
.endif
add edi, ARRAY_UNIT_LENGTH
.until edi>=OFFSET Array+(ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS)


the problem lies here;

OFFSET Array+(ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS)

its not calculating the correct value on building. i calculated what it was meant to be and checked it in the debugger MASM's calculated address was much smaller then it should have been!!!

Problem with MASM maths or my bad?

Cheers  :U

Casper

You might want to use brackets to control the order of operations else MASM will add first and then multiply which is why it is wrong.  Either that or move the add part to the end.  MASM does operations left to right so, this will work...

(ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS)+OFFSET Array

Try that.  We are used to the parenthesis doing the job but MASM likes brackets instead.

Casper

RedXVII

Didnt work!

i looked again, its too small. I just checked my constants, and im sure nothing is wrong with those either!!

Casper

Darn, I was hoping.  Show me what you tried, please.  Working blind here.  I think I need to see more or all of the program so I can test it. Also need to see that data section...

Casper

RedXVII

FOUND IT!!! HURRAY!! :dance:

Ok, this is most curious little problem, but compile this program below and step through it in the debugger. Notice that it doesnt complete the process as we might expect it should. The cmp statement is wrong. This was the problem occuring in my program, but i can explain it now.

It seems that masm passes over the file replacing the constants (.const) with the exact text specified, then problably repeats these passes until everything has settled out. This could mean erroneous calculations.

eg. take this statement, from below:
Array db (ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS) dup (?)
To us its a simple 8*4 = 32
To the compiler
First pass: ACONSTANT+1*4 = ACONSTANT+4
Second pass: 7+4 = 11

   :dazzled:

Solution:
Array db ((ARRAY_UNIT_LENGTH)*NUMBER_OF_UNITS) dup (?)
-or correct the constants BEFORE it isss applied to the program-
ACONSTANT equ 7
ARRAY_UNIT_LENGTH equ ACONSTANT+1        ;masm changes to ARRAY_UNIT_LENGTH equ 8, so no problems will occur on first pass


The same happend with my program, all i needed to do was either put the constant in brackets or make sure the constants are corrected before masm tries to adjust my program!

Its a bit bizarre, but anyhow,
Sorted  :U  :U  :U


NOTICE: i have already correct the Array problem, but take a look at the cmp command in the debugger, and do the maths  :bg
.386
.model flat,stdcall
option casemap:none

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

myfunc proto :DWORD

.const
ARRAY_UNIT_LENGTH equ ACONSTANT+1
ACONSTANT equ 7
NUMBER_OF_UNITS equ 4

.data
garbage db "garbage", 0

.data?
Array db ((ARRAY_UNIT_LENGTH)*NUMBER_OF_UNITS) dup (?)
temp1 DWORD ?

.code
start:
lea edi, Array
.repeat
mov al, [edi]
.if !al
mov temp1, edi
invoke myfunc, edi
mov edi, temp1
.endif
add edi, ARRAY_UNIT_LENGTH
.until edi>=OFFSET Array+(ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS)
invoke ExitProcess, 1

myfunc proc string:DWORD
mov edi, string
mov esi, OFFSET garbage
mov ecx, ARRAY_UNIT_LENGTH
rep movs byte ptr [edi], byte ptr [esi]
ret
myfunc endp

end start

Casper

IIRC, Brackets was 'my' solution for you.  It is hard to work blind.  In the future you should give us an even chance by poting more code or attaching the project.

Casper

RedXVII

well, i didnt realise it would be a problem this far back in my programs - hence why i asked if it was a masm problem. It only occured to me the other night that it might read it wrong on compiling. Your brackets soulution wouldnt and doesnt work, like i was explaining above. Needs to be more like this;

((ARRAY_UNIT_LENGTH)*NUMBER_OF_UNITS)+OFFSET Array

Cheers anyway
:U

Casper

Actually,

Thank you very much.  I see your point and am adding that to my database.  Very nice work.

Casper

Ossa

A guy who was interviewing me for a summer job a few years back gave me this piece of advice ragarding macros (it was for C macros, but it applies to MASM macros too):

"Always bracket macros: both the arguments and the complete macros. Do this because the arguments are always inserted and then evaluated"

In other words, in MASM (in MASM it applies to almost anything):

Blah TEXTEQU ((arg1) and (arg2))

or in C:

#define Blah ((arg1) & (arg2))

This removes any ambiguity and always leaves you safe both from sloppy definitions of the arguments and sloppy use of the result. As a result, I have become a huge over-user of brackets, but I never run into any problems like you have found here.

Ossa
Website (very old): ossa.the-wot.co.uk

Ratch

Casper,
QuoteYou might want to use brackets to control the order of operations else MASM will add first and then multiply which is why it is wrong.  Either that or move the add part to the end.

     Nope, in MASM, multiplication/division have a higher precedence than addition/substraction, and will be performed first.  Leaving addition to the last will not change anything either, because A+B=B+A.  In this case, MASM is doing exactly what RedXVII is telling it to do, only he does not realize what he is coding.

RedXVII,
     I see problems like yours a lot.  You are using EQU instead of = for numeric constants.  EQU does a symbolic substitution of a symbol if the operand is unknown at the time.  For instance, you used ACONSTANT before you defined it in the next line, so EQU simply assigned ARRAY_UNIT_LENGTH a value of ACONSTANT+1.   In your last example, the compare assembles "cmp    edi, offset Array + ( ACONSTANT + 001h * NUMBER_OF_UNITS )" which evaluates to 0Bh instead of 020H, because multiplication is done before addition.  What you really wanted was "cmp    edi, OFFSET Array+(ARRAY_UNIT_LENGTH*NUMBER_OF_UNITS), but since ARRAY_UNIT_LENGTH was EQU'd to ACONSTANT+1, the substitition was made before the evaluation and a different result than you expected was obtained.  Ok, here is what you should do. (1) Use the '=' directive instead of EQU for numeric constants.  You can still use EQU for numeric constants, but if you goof and don't have them the correct order so no operand is undefined, you will get a substitution instead of an evaluation.  A '=' will squawk and alert you if that happens.  (2) Arrange the CONST statements so that the operands are known before they are evaluated.  So the "ACONSTANT = 7" statement should come before 'ARRAY_UNIT_LENGTH=ACONSTANT+1' Parenthesis will correct the problem, but are unnecessary, because the expression is unambiguous if you use '=' instead of EQU for numeric constants, and order them correctly.  Try it without the parenthesis and see.  Ratch

RedXVII

Yes ratch. As i was saying in my last post - i figured the problem out, and i was trying to explain that.  :green2

Although i didnt know about the the "=" and some other bits. Thanks for confirming it.

:U