News:

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

Tricky problem with CodeAlign macro

Started by jj2007, February 16, 2010, 11:25:14 PM

Previous topic - Next topic

qWord

don't know why, but the problem seems the 'start'-label. This works:
CodeAlign MACRO ct
LOCAL nops, diff
IFNDEF align_mark_code
_TEXT SEGMENT
align_mark_code:
org 0
algin_zero_lbl_code:
org align_mark_code
_TEXT ENDS
ENDIF

  nops = ct-(($-algin_zero_lbl_code) mod ct)

  if nops ne ct
REPEAT nops
nop
ENDM
  endif
ENDM

its generating a label in code-segment at pos 0 (org 0) - generally this is better than the start-label because not all people use a label named 'start' (or they use a proc  as entry). Also there may be code before the start-label e.g. through includes.

EDIT - error corrected - thx2 dedndave :)
FPU in a trice: SmplMath
It's that simple!

dedndave

and - it is defined before the macro that references it   :U

dedndave

shouldn't it be this ?

CodeAlign MACRO ct
LOCAL nops
    IFNDEF align_mark_code
        _TEXT SEGMENT
            align_mark_code:
            org 0
            align_zero_lbl_code:
            org align_mark_code
        _TEXT ENDS
    ENDIF

  nops = ct-(($-align_zero_lbl_code) mod ct)

  if nops ne ct
    REPEAT nops
        nop
    ENDM
  endif
ENDM

qWord

Quote from: dedndave on February 17, 2010, 02:09:17 PM
shouldn't it be this ?
yes , your right  :bg

I've also followed one of your suggestions and modified my macro: now its use masm's align except for a padding of 5
FPU in a trice: SmplMath
It's that simple!

jj2007

The problem is not the start label, it yields exactly the same offset as Lbl0 in this case. The problem is that ml.exe shoots in the dark when it comes to calculating the current offset...
Echos from JWasm:
Nops_S=7, diff_S=1
Nops_L=7, diff_L=1
Main code:  diff=95 ; correct - we need exactly one nop to arrive at 96
Nops_S=1, diff_S=95
Nops_L=1, diff_L=95

Echos from ml.exe:
Nops_S=7, diff_S=1
Nops_L=7, diff_L=1
Main code:  diff=138 ; rubbish, this is far from the true position
Nops_S=6, diff_S=138
Nops_L=6, diff_L=138

CodeAlign MACRO ct
LOCAL nops, diff
  IFNDEF Current_ORG
Current_ORG: ; save origin by creating a label
ORG 0 ; set origin to zero
Lbl0:
ORG Current_ORG ; restore origin
  ENDIF
  diff_S = $-start
  diff_L = $-Lbl0
  nops_L = ct-(($-Lbl0) mod ct) ; we take Lbl0 as reference
  nops_S = ct-($-start) mod ct ; we take start as reference
  nops = nops_L
  if nops ne ct
REPEAT nops
nop ; for testing, we just insert nops
ENDM
  endif
  tmp$ CATSTR <Nops_S=>, %nops_S, <, diff_S=>, %diff_S ; watch in output window
  % echo tmp$
  tmp$ CATSTR <Nops_L=>, %nops_L, <, diff_L=>, %diff_L
  % echo tmp$
ENDM


I am also not sure why JWasm insists that the first THIS NEAR is different from $.

qWord

Well jj, trying to fix one bug ends up finding an another one   :toothy
FPU in a trice: SmplMath
It's that simple!

qWord

Quote from: jj2007 on February 17, 2010, 03:27:21 PMThe problem is that ml.exe shoots in the dark when it comes to calculating the current offset...
the very strange is, that it works fine if you replace the loop (REPEAT nops) with 'db nops dup (090h)'. Eventually such offset expressions are not evaluated in the same pass as the rest of the macro (???).
FPU in a trice: SmplMath
It's that simple!

dedndave

well - then it isn't a problem, as we intend to use if/then constructs to place our code
the repeat nop's was for test only   :bg

EDIT - in fact - most of the masm alignment length combinations are ok
we only need to replace the ones that use add eax,0
that could simplify the macro logic considerably

qWord

Quote from: dedndave on February 17, 2010, 05:44:17 PMin fact - most of the masm alignment length combinations are ok
we only need to replace the ones that use add eax,0
that could simplify the macro logic considerably
that what the macro does I've upload in the post above. Here an simplified version without .data/.data? support:
code_align macro nAlign:req
IFNDEF algin_zero_lbl_code
align_mark_code:
org 0
algin_zero_lbl_code:
org align_mark_code
ENDIF

;; check if power of two
align_msk  = 2
align_flag = 0
REPEAT 31
IF align_msk EQ nAlign
align_flag = 1
EXITM
ENDIF
align_msk = align_msk SHL 1
ENDM
IF align_flag EQ 0
.err <code_align: ALIGN only to power of 2: 2,4,8,16,32,64...>
EXITM
ENDIF

;; generate the bit mask
align_msk = nAlign-1
align_fill = 090h
IFIDNI @CurSeg,<_TEXT>
IF nAlign LE 16
IF (nAlign-(align_msk AND ($-OFFSET algin_zero_lbl_code))) EQ 5 ; correct masm's align bug
nop
db 08Dh,74h,26h,0 ; lea esi,[esi+imm8(0)]
ELSE
align nAlign
ENDIF
ELSE ;; align > 16
db (nAlign-(align_msk AND ($-OFFSET algin_zero_lbl_code)))*(1 AND ((align_msk AND ($-OFFSET algin_zero_lbl_code)) NE 0)) dup (align_fill)
ENDIF
ELSE
.err <current segemnt not supported by code_align-macro>
ENDIF
endm

FPU in a trice: SmplMath
It's that simple!

dedndave

i created a code segment with PAGE align-type
it seems ALIGN 256 will use 7-byte NOP's (lea esp,[esp+00000000]) to fill in most of the space
they could have used Michael's SS: override to make them 8-byte NOP's - but oh well - it works without modifying flags
i guess it wouldn't make much difference in terms of speed
so - if the (align distance MOD 7) = 5, you need to take over alignment
otherwise, the ALIGN directive works ok

you could just add the 5-byte NOP, then use ALIGN   :bg  (oops - that logic doesn't fly)
ok - i see you just added a NOP instruction
i guess if you use executed alignment to 256, you aren't too concerned about speed or dependancies - lol

dedndave

i glued your macro into Jochen's test program...

0: should be zero
5: should be zero

same result - not sure how to fix it

qWord

Quote from: dedndave on February 17, 2010, 09:17:48 PM
i glued your macro into Jochen's test program...
for me it works (ml 10.x) - I'm using my friend Olly for checking. Are you building it as release?
FPU in a trice: SmplMath
It's that simple!

dedndave

yes - i have no debugger installed on this hard drive
i am about to rebuild, so haven't taken the time to set it up
let me attach...

MichaelW

If the alignment will require more than a small number of nop instructions it would be faster to jump around them than to execute them. GAS does this starting with a 15-byte nop.  
eschew obfuscation

qWord

dedndave, with your example it doesn't work for me too. Currently it seems for me, that  it is not possible to fix this align bug :'( - may jj get it.
However, my original macro (using simply db x dup()) seems to work proper.

qWord
FPU in a trice: SmplMath
It's that simple!