I just solved a very frustrating systems problem reading volumes.
I found mbrboot.exe on your site; a very cool program to read the MasterBootRecord, tho I have problems re-directing the O/P. So I added some of that source to my own VOLUMES program, basically a stripped-down DISKPART, now running ELEVATED, but instead of dumping hex, I just copy the records to a .log file of my own (basically for compare/backup/restore) and dump hex w/my own program. But, now I can do this for every drive in GETLOGICALDRIVES/QUERYDOSDEVICE as well as the default drive, ie:
PATHSET VOLUMES.E.Sat.07202013. 8342437
MBR*
C$\HarddiskVolume2 f dNTFS 7A13ECF8
E$\HarddiskVolume3 fHP_RECOVERY dNTFS D2BF2072
F$\HarddiskVolume4 fHP_TOOLS dNTFS D45B05E7
G \CdRom0 NOT READY
H$\HarddiskVolume5 r021-IV NTFS 02480666
VOLUMES Sat 07/20/2013 8:34:24.95 All OK.
1 file(s) copied.
DUMPFILE Sat 07/20/2013 8:34:25.23 All OK.
PATHSET VOLUMES.D.Sat.07202013. 8342437
The problem:
. occasionally, after changing my MASM program in seemingly un-related areas,
this would stop working! That is, this stupid INVALID_PARAMETER/87d would
occur for EVERY eligible drive???!!!
After trying MANY things for MANY hours, I stumbled on something that would
work, at least until the next time I changed my program, which, in my case,
wasn't very long!
Googling my brains out found NOTHING that worked for me!
Being an IBM mainframe/systems programmer, there would be times when memory alignment was required in my assembler program. So I added filler before the READFILE buffer, 1 byte at a time, until/if it worked again. That's when I then
noticed the assembler listings' displacement for that buffer was QWORD-aligned;
that is, it ended in a 0 or 8h (an 8h in my working case).
That was the key; I moved my buffer IMMEDIATELY after the .DATA section, where
the displacement is 0x00000000. Now it works even if I add labels to my .DATA,
as long as they are AFTER this buffer!
Of course, all this ASSUMES that the .DATA beginning address is always, say,
page-aligned (4K). In my WinDbg testing, it was always 0x00404000, so I can
"guarantee" alignment, and, thus, a working program.
In hindsight, it would have been nice if the error RC was something like,
say, ERROR_INVALID_MEMORY_ALIGNMENT, instead of INVALID_PARAMETER. Perhaps there is a URL somewhere that discusses this very problem; I just can't find it.
In IBM-land, I have a macro to align storage:
&NAME $ALIGN &TO=4096,&BEGIN=
.* THIS MACRO WILL ALIGN THE ASM 'LOC' VALUE TO THE CLOSEST UPWARD
.* DESIRED BYTE BOUNDARY VIA A 'DS' STATEMENT.
DS ((((*-&CT-1)/&TO)*&TO)+&TO+&CT-*)X
* ZEPPSPIE, 11/2/79
This finally leads me to my MASM question; how do I align storage in the
.DATA section? I assume C++,etc doesn't have this issue; I know COBOL 01
levels align. How do I "address" the "LOCation counter" (or whatever the
PC equivalent is (ie: field1 of .LST)):
00000000 00000003 [ bsJump db 3 dup(?)
00
]
Quote from: MtheK on July 21, 2013, 01:21:47 AMhow do I align storage in the .DATA section?
Try
.data
whatever db "hi", 0
align 16myqwords dq 1000 dup(?)
If you really need 4096 byte alignment, use VirtualAlloc, or open a new segment:
include \masm32\include\masm32rt.inc
MySeg segment flat 'DATA?'
MyBuffer db 1000 dup(?)
MySeg ends
.code
AppName db "Masm32:", 0
start: MsgBox 0, hex$(offset MyBuffer), addr AppName, MB_OK
exit
end start
Hhhmmm...for some reason, 'align 16' won't work for me. However, on the plus side, I was able to make a PC equivalent of my old MainFrame macro:
00000000 .DATA
00000000 = 00000000 DATASTART EQU $
00000000 00 BYTE ?
ALIGN 2
00000002 00 BYTE ?
ALIGN 16
VOLUMES.ASM(82) : error A2189: invalid combination with segment alignment : 16
00000003 00 BYTE ?
ALIGN 2*2048
VOLUMES.ASM(84) : error A2189: invalid combination with segment alignment : 4096
00000004 00 BYTE ?
= 00001000 ALIGNSIZE EQU 4096
00000005 = 00000005 ALIGNLOC EQU $ - DATASTART
00000005 00000FFB [ BYTE ((((ALIGNLOC-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-ALIGNLOC) DUP(00h)
00
]
00001000 00000003 [ bsJump db 3 dup(?)
00
]
In my case, 'bsJump' was 4K-aligned as indicated by its' 0x00001000 LOCation counter. Thankx...
Quote from: MtheK on July 21, 2013, 06:10:40 AM
ALIGNSIZE EQU 4096
ALIGNLOC EQU $ - DATASTART
BYTE ((((ALIGNLOC-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-ALIGNLOC) DUP(00h)
Yes, that's one possibility. You could instead use the AND operator:
ALIGNSIZE EQU 4096
ALIGNLOC EQU $ - DATASTART
BYTE ALIGNSIZE - (ALIGNLOC and (ALIGNSIZE-1)) DUP(00h)
and replace the BYTE-DUP combination by the ORG directive:
ORG $ + ALIGNSIZE - (ALIGNLOC and (ALIGNSIZE-1))
ORG looks cool; seems similar to IBM. It worked fine for me, however,
there is 1 difference btx that and mine. For mine, if I'm already aligned,
I basically become a NO-OP, yet the ORG adds an extra full boundary size:
= 00001000 ALIGNSIZE EQU 4096
0000167B = 0000167B ALIGNLOC1 EQU $ - DATASTART
= 00000985 ALIGNLOC1D EQU ((((ALIGNLOC1-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-ALIGNLOC1)
0000167B 00000985 [ BYTE ALIGNLOC1D DUP(00h) ; this aligns to 4K
00
]
00002000 = 00002000 ALIGNLOC2 EQU $ - DATASTART
= 00000000 ALIGNLOC2D EQU ((((ALIGNLOC2-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-ALIGNLOC2)
BYTE ALIGNLOC2D DUP(00h) ; this is 0 since right after 1st one
00002000 = 00002000 ALIGNLOC3 EQU $ - DATASTART
ORG $ + ALIGNSIZE - (ALIGNLOC3 and (ALIGNSIZE-1))
00003000 00 BYTE ?
00003001 = 00003001 ALIGNLOC4 EQU $ - DATASTART
ORG $ + ALIGNSIZE - (ALIGNLOC4 and (ALIGNSIZE-1))
00004000 00000003 [ bsJump db 3 dup(?)
00
]
In my case, the jump from 0x2000 to 0x3000 by the ORG, where my LOC2 stayed at 0x2000. Maybe only a concern for large sizes?
Quote from: MtheK on July 22, 2013, 12:30:39 AM
there is 1 difference btx that and mine. For mine, if I'm already aligned,
I basically become a NO-OP, yet the ORG adds an extra full boundary size:
You're right. I'd say the AND has to be moved a bit:
ORG $ + ( ( ALIGNSIZE - ALIGNLOC ) and ( ALIGNSIZE-1 ) )
Perfect; thankx:
00002000 00 BYTE ?
00002001 = 00002001 ALIGNLOC3 EQU $ - DATASTART
ORG $ + ( ( ALIGNSIZE - ALIGNLOC3 ) and ( ALIGNSIZE-1 ) )
00003000 = 00003000 ALIGNLOC4 EQU $ - DATASTART
ORG $ + ( ( ALIGNSIZE - ALIGNLOC4 ) and ( ALIGNSIZE-1 ) )
00003000 00000003 [ bsJump db 3 dup(?)
00
]
As an FYI, I think the mbrboot.exe on your site only does PE1.
When I run it on another laptop, it shows 1 512-byte record, yet
my program saves 2 512-byte records (ie: DIR size). I loop thru
the 4 PARTENTRYs and, in my case, PE2 has a partition, verified
by IOCTL_STORAGE_GET_DEVICE_NUMBER.
I FINALLY found the PC equivalent of the IBM &SYSECT, which is the
beginning of the name of the currect section (ie: program segment).
Now, as in my old macro, I no longer need to add the "DATASTART" label
after .DATA, and, more importantly, I no longer need to add a unique
label before every alignment:
ORG $ + ( ( ALIGNSIZE - ($ - _DATA) ) and ( ALIGNSIZE-1 ) )
Perhaps this is obvious to you all, but it wasn't for me.
Quote from: MtheK on July 24, 2013, 01:21:57 AM
Perhaps this is obvious to you all, but it wasn't for me.
Definitely not to all (I didn't know it). Here is a snippet for testing the built-in
@CurSeg macro:
include \masm32\include\masm32rt.inc
.data?
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
.const
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
.data
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyPersonalSegment SEGMENT "whatever"
MyCount dd ?
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyPersonalSegment ENDS
.code
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
start:
.err ; force an error to stop assembly
exit
end start
I like @CurSeg:
The current segment = _BSS
The current segment = CONST
The current segment = _DATA
The current segment = MyPersonalSegment
The current segment = _TEXT
And so, hopefully, the last and only statement needed to align storage is:
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
I cheat 'cause ALIGNSIZE could just be replaced w/an actual number instead of an EQUATE.
I thought, so, too - but now I am no longer sure:
004060D0 v1
004070D0 v1a
00403010 v2
00404010 v2a
00405000 v3
00406000 v3a
00408000 v4
00409000 v4a
00401000 v5
00402000 v5a
include \masm32\include\masm32rt.inc
MySize=1000h
MyAlign MACRO ALIGNSIZE
LOCAL neworg, tmp$
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
ENDM
.data?
v1 dd ?
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyAlign MySize
v1a dd ?
.const
v2 dd 333
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyAlign MySize
v2a dd 4444
.data
v3 dd 555
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyAlign MySize
v3a dd 666
MyPersonalSegment SEGMENT "whatever"
v4 dd 777
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyAlign MySize
v4a dd 888
MyPersonalSegment ENDS
.code
v5 dd 999
tmp$ CATSTR <The current segment =>, @CurSeg
% echo tmp$
MyAlign MySize
v5a dd 888
start:
print hex$(offset v1), 9, "v1", 13, 10
print hex$(offset v1a), 9, "v1a", 13, 10
print hex$(offset v2), 9, "v2", 13, 10
print hex$(offset v2a), 9, "v2a", 13, 10
print hex$(offset v3), 9, "v3", 13, 10
print hex$(offset v3a), 9, "v3a", 13, 10
print hex$(offset v4), 9, "v4", 13, 10
print hex$(offset v4a), 9, "v4a", 13, 10
print hex$(offset v5), 9, "v5", 13, 10
print hex$(offset v5a), 9, "v5a", 13, 10
; .err ; force an error to stop assembly
exit
end start
Hhhmmm...in truth, I only know about .DATA:
00002000 00 BYTE ?
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
00003000 00000003 [ bsJump db 3 dup(?)
00
]
I tried .CODE and that failed like yours:
00000038 E8 00000FAA CALL PREP
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
00000FD1 E8 00000836 CALL PHYSICAL0 ; read MBR/drive0
I went back to naming it manually, and that also failed the same way:
00000038 E8 00000FAA CALL PREP
ORG $ + ( ( ALIGNSIZE - ($ - _TEXT) ) and ( ALIGNSIZE-1 ) )
00000FD1 E8 00000836 CALL PHYSICAL0 ; read MBR/drive0
HOWEVER, if I go back to my old IBM macro, it works fine:
00000038 E8 00000FD9 CALL PREP
0000003D 0000003D = 00000FC3 ALIGNLOC5D EQU ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg))
0000003D 00000FC3 [ BYTE ALIGNLOC5D DUP(00h) ; this aligns to 4K
00
]
00001000 E8 00000836 CALL PHYSICAL0 ; read MBR/drive0
Of course, none are runnable this way, but it does indeed align it???
Either there is something seriously wrong with ORG, or I miss the point completely ::)
Try this with ML and JWasm (with very different results):
include \masm32\include\masm32rt.inc
MySize=1000h ; try 100h - looks better...
MyAlign MACRO ALIGNSIZE
addbytes=($ - @CurSeg) ; and (ALIGNSIZE-1)
addbytes=ALIGNSIZE-addbytes
% echo @CatStr(<adding >, %addbytes, < in seg >, @CurSeg)
ORG $ + addbytes ;; same as ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
ENDM
.data?
v1 dd ?
MyAlign MySize
v1a dd ?
.const
v2 db 111
MyAlign MySize
v2a dd 222
.data
v3 RECT <12, 34, 56, 78>
MyAlign MySize
v3a dd 666
MyPersonalSegment SEGMENT "whatever"
v4 dd 777
MyAlign MySize
v4a dd 888
MyPersonalSegment ENDS
.code
v5 dd 999
MyAlign MySize
v5a dd 888
start:
print hex$(offset v1), 9, "v1 (.data?)", 13, 10
print hex$(offset v1a), 9, "v1a", 13, 10, 10
print hex$(offset v2), 9, "v2 (.const)", 13, 10
print hex$(offset v2a), 9, "v2a", 13, 10, 10
print hex$(offset v3), 9, "v3 (.data)", 13, 10
print hex$(offset v3a), 9, "v3a", 13, 10, 10
print hex$(offset v4), 9, "v4 (MyPersonalSegment)", 13, 10
print hex$(offset v4a), 9, "v4a", 13, 10, 10
print hex$(offset v5), 9, "v5 (.code)", 13, 10
print hex$(offset v5a), 9, "v5a", 13, 10, 10
exit
end start
The echoes are OK, the rest is not:
adding 4092 in seg _BSS
adding 4095 in seg CONST
adding 4080 in seg _DATA
adding 4092 in seg MyPersonalSegment
adding 4092 in seg _TEXT
:(
It looks like the 1st ORG, using the formula in my old macro, comes up w/the same value as EQU, but it doesn't ADD to the loc ctr as BYTE does. But then, the 2nd ORG comes up with F94h, but shouldn't it be the same value as the 1st ORG since both ORGs start at 3Dh?
00000038 E8 00000FAA CALL PREP
0000003D setloc1 byte 0 dup(00h)
0000003D 0000003D = 00000FC3 ALIGNLOC5D EQU ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg))
ORG ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg))
00000FC3 setloc2 byte 0 dup(00h)
org setloc1
0000003D setloc3 byte 0 dup(00h)
ORG $ + ( ( ALIGNSIZE - ($ - @CurSeg) ) and ( ALIGNSIZE-1 ) )
00000FD1 E8 00000836 CALL PHYSICAL0 ; read MBR/drive0
I made a macro for this, except using the IBM formula until/if ORG works in .CODE:
$ALIGN MACRO ALIGNSIZE
LOCAL $ALIGNS,$ALIGNZ,$ALIGNE,$ALIGNQ,$ALIGNX
IF ALIGNSIZE GT 0
IFDIFI @CurSeg,<_TEXT>
$ALIGNS BYTE 0 DUP(00h) ; show begin LOC CTR
ELSE
JMP $ALIGNQ ; branch around alignment & show LOC CTR
ENDIF
IF ($ - @CurSeg) EQ 0
$ALIGNZ EQU $ - @CurSeg ; already at start of segment, so can't do or get extra
ELSE
BYTE ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg)) DUP(00h)
ENDIF
IFDIFI @CurSeg,<_TEXT>
$ALIGNE BYTE 0 DUP(00h) ; show end LOC CTR
ELSE
$ALIGNQ: ; get past alignment & show LOC CTR
ENDIF
ELSE
$ALIGNX EQU $ - @CurSeg ; size not valid
ENDIF
ENDM
To use it, just code the following in .DATA and/or .CODE:
$ALIGN 4096
In this case, it aligns to 4K. Any number can be used. I assembled OK to 65536 (64K). For .CODE, a JMP is generated to branch around it.
How did you test your macro? For my attached example, it doesn't work properly :(
It assembles fine, but instead of aligning, it just adds 100h to the current $:
004043E0 v1 (.data?, dd)
004044E0 v1a
The only method that works for me so far is creating a new segment.
That's weird; this is what I get:
00000000 .data?
00000000 00000000 v1 dd ?
$ALIGN MySize
00000004 1 ??0019 BYTE 0 DUP(00h) ; show begin LOC CTR
00000004 000000FC [ 1 BYTE ((((($ - @CurSeg)-1)/MySize)*MySize)+MySize-($ - @CurSeg)) DUP(00h)
00
]
ALIGNX.ASM(63) : warning A4014: instructions and initialized data not supported in BSS segments
$ALIGN(12): Macro Called From
ALIGNX.ASM(63): Main Line Code
00000100 1 ??001B BYTE 0 DUP(00h) ; show end LOC CTR
00000100 00000000 v1a dd ?
It seems like 'v1a' is aligned, at least assembly-wise? Could this BSS segment not be aligned by the OS at run time? I do assume that the OS does this. For .DATA and .CODE, they are aligned by the OS for me...
I didn't spend much time examining the details, but in my test the alignment function appears to work, as it should.
;========================================================================================
$ALIGN MACRO ALIGNSIZE
LOCAL $ALIGNS,$ALIGNZ,$ALIGNE,$ALIGNQ,$ALIGNX
IF ALIGNSIZE GT 0
IFDIFI @CurSeg,<_TEXT>
$ALIGNS BYTE 0 DUP(00h) ; show begin LOC CTR
ELSE
JMP $ALIGNQ ; branch around alignment & show LOC CTR
ENDIF
IF ($ - @CurSeg) EQ 0
$ALIGNZ EQU $ - @CurSeg ; already at start of segment, so can't do or get extra
ELSE
BYTE ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg)) DUP(00h)
ENDIF
IFDIFI @CurSeg,<_TEXT>
$ALIGNE BYTE 0 DUP(00h) ; show end LOC CTR
ELSE
$ALIGNQ: ; get past alignment & show LOC CTR
ENDIF
ELSE
$ALIGNX EQU $ - @CurSeg ; size not valid
ENDIF
ENDM
;========================================================================================
;----------------------------------------
; Returns the maximum alignment of _ptr.
;----------------------------------------
alignment MACRO _ptr
push ecx
xor eax, eax
mov ecx, _ptr
bsf ecx, ecx
jz @F
mov eax, 1
shl eax, cl
@@:
pop ecx
EXITM <eax>
ENDM
;========================================================================================
include \masm32\include\masm32rt.inc
;========================================================================================
.data
db 0
FOR arg,<1,2,3,4,5,6,7,8,16,32,64,128,256>
db 0
$ALIGN arg
D&arg db 0
ENDM
.code
;========================================================================================
start:
;========================================================================================
FOR arg,<1,2,3,4,5,6,7,8,16,32,64,128,256>
printf("data %d %d\n", arg, alignment(OFFSET D&arg))
ENDM
printf("\n")
;---------------------------------------------------------
; Some arg values > 128 will trigger an error:
; error A2075: jump destination too far : by xxx byte(s)
; Where the value of xxx varies.
;---------------------------------------------------------
FOR arg,<1,2,3,4,5,6,7,8,16,32,64,128>
$ALIGN arg
C&arg:
ENDM
FOR arg,<1,2,3,4,5,6,7,8,16,32,64,128>
printf("code %d %d\n", arg, alignment(C&arg))
ENDM
inkey
exit
;========================================================================================
end start
data 1 2
data 2 4
data 3 2
data 4 8
data 5 2
data 6 4
data 7 2
data 8 16
data 16 32
data 32 64
data 64 128
data 128 256
data 256 512
code 1 4
code 2 2
code 3 2
code 4 4
code 5 2
code 6 2
code 7 1
code 8 32
code 16 16
code 32 64
code 64 128
code 128 256
MtheK,
Enclosing your code in code tags will preserve the formatting.
"code tags"...u mean that 'insert code' # button? I tried that, let's see if it works...
I changed the 3 DUP(00h) to DUP(?) to eliminate that error msg in BSS:
00000000 .data?
00000000 00000000 v1 dd ?
$ALIGN MySize
00000004 1 ??0019 BYTE 0 DUP(?) ; show begin LOC CTR
00000004 000000FC [ 1 BYTE ((((($ - @CurSeg)-1)/MySize)*MySize)+MySize-($ - @CurSeg)) DUP(?)
00
]
00000100 1 ??001B BYTE 0 DUP(?) ; show end LOC CTR
00000100 00000000 v1a dd ?
The problem is really that "$" refers to an assembly-time situation that will be changed by the linker. Run the code below with Olly, and watch what happens if you eliminate the .data section. As it stands, you can see this in Olly:
<ModuleEn /$ B8 10204000 mov eax, offset 00402010
00401005 |. B9 10304000 mov ecx, offset 00403010
... and, data dump in in the lower left corner:
00402000 78 56 34 12|00 00 00 00|00 00 00 00|00 00 00 00|
00402010 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00|
include \masm32\include\masm32rt.inc
;========================================================================================
$ALIGN MACRO ALIGNSIZE
LOCAL $ALIGNS,$ALIGNZ,$ALIGNE,$ALIGNQ,$ALIGNX
IF ALIGNSIZE GT 0
IFDIFI @CurSeg,<_TEXT>
$ALIGNS BYTE 0 DUP(00h) ; show begin LOC CTR
ELSE
JMP $ALIGNQ ; branch around alignment & show LOC CTR
ENDIF
IF ($ - @CurSeg) EQ 0
$ALIGNZ EQU $ - @CurSeg ; already at start of segment, so can't do or get extra
ELSE
BYTE ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg)) DUP(00h)
ENDIF
IFDIFI @CurSeg,<_TEXT>
$ALIGNE BYTE 0 DUP(00h) ; show end LOC CTR
ELSE
$ALIGNQ: ; get past alignment & show LOC CTR
ENDIF
ELSE
$ALIGNX EQU $ - @CurSeg ; size not valid
ENDIF
ENDM
;========================================================================================
.data?
v_uid dd ?
$ALIGN 4096
v_uidA dd ?
.data
v_id dd 12345678h
.code
start: mov eax, offset v_uid
mov ecx, offset v_uidA
ret
end start
When you click the Insert Code (#) button you get a start tag and an end tag. The code needs to be inserted between the start tag and the end tag.
http://en.wikipedia.org/wiki/BBCode
OK, got it; testing..:
$ALIGN MACRO ALIGNSIZE
LOCAL $ALIGNS,$ALIGNZ,$ALIGNE,$ALIGNQ,$ALIGNX
IF ALIGNSIZE GT 0
IFDIFI @CurSeg,<_TEXT>
$ALIGNS BYTE 0 DUP(?) ; show begin LOC CTR
ELSE
JMP $ALIGNQ ; branch around alignment & show LOC CTR
ENDIF
IF ($ - @CurSeg) EQ 0
$ALIGNZ EQU $ - @CurSeg ; already at start of segment, so can't do or get extra
ELSE
BYTE ((((($ - @CurSeg)-1)/ALIGNSIZE)*ALIGNSIZE)+ALIGNSIZE-($ - @CurSeg)) DUP(?)
ENDIF
IFDIFI @CurSeg,<_TEXT>
$ALIGNE BYTE 0 DUP(?) ; show end LOC CTR
ELSE
$ALIGNQ: ; get past alignment & show LOC CTR
ENDIF
ELSE
$ALIGNX EQU $ - @CurSeg ; size not valid
ENDIF
ENDM
-----
Ah, I see; the linker controls the alignment:
ALIGNX2
Timestamp is 51f69844 (Mon Jul 29 10:28:52 2013)
Preferred load address is 00400000
Start Length Name Class
0001:00000000 0000101bH .text CODE
0002:00000000 00000164H .rdata DATA
0002:00000164 00000000H .edata DATA
0003:00000000 00000104H .data DATA
0003:00000104 00001338H .bss DATA
WinDbg shows v_uid at 0x00404104, kinda like the linker says above for .bss,
so, yea, I only then work for segments that start with 0 per the linker,
a la .text (.CODE) and .data (all I've ever used), and, I guess, .rdata.
FYI: A file opened with the WINAPI CreateFile and FILE_FLAG_NO_BUFFERING,
and using a ReadFile and/or WriteFile, requires the buffer(s) to be aligned,
where SetEndOfFile does not; perfect for my $ALIGN macro. In my case,
I use this to ensure there is no caching, even with EXCLUSIVE. Kinda like
an IBM M/F VSAM SHAREOPTIONS(4,4), which requires ENQ/DEQ logic; this logic
is not a performance concern as it does minimum I/O (just btx calls in a .BAT),
but requires absolute control of current data w/no outside interference.
I also couldn't read/write a single byte w/o that ERROR_INVALID_PARAMETER
rc occuring; I think the minimum is a physical sector, so I used a multiple
of 512 (in my case, a 4K page) and just padded the rest w/nulls.
FYI: As I learned how to use .data?, I realized that if I prefix it with
an '$ALIGN 4096', since it follows .data which IS page-aligned, then .data?
should also be page-aligned, as, for example, shown by a .map:
0003:00000000 00004000H .data DATA
0003:00004000 00003400H .bss DATA
so that's cool.