By the time I get to coding, I am tired after a long day so the answer is not coming to me...
How would I create a buffer that is divisible by 4? Or would this be unnecessary? I am thinking for alignment that buffers should be divisible by 4 right?
I have variable length strings that I get the lengths of and add em together and create a buffer with HeapAlloc, lets say at one time the length might be 49, is there an equation or some math I could use to figure out it should be made 52? if it is say 56, then we are good to go... etc...
mov edx,StringLength
add edx,4 ;add 1 for terminator and 3 for mod function
and edx,-4 ;=0FFFFFFFCh
;edx = buffer length
i prefer not to use EAX for these because you get shorter code with any other register
EAX does not have the shortened forms for signed byte add, sub, etc
of course, you can do it with an EQU if the length is known in advance
Nice, just what I was looking for... Thanks!
The lengths aren't known before hand...
if you don't count the terminator...
X = (N + M - 1) and (- M)
X = result size
N = minimum size
M = alignment size
The memory returned by HeapAlloc() and GlobalAlloc() is allways 8 byte aligned.
Quote from: dedndave on April 27, 2011, 12:42:24 AM
i prefer not to use EAX for these because you get shorter code with any other register
EAX does not have the shortened forms for signed byte add, sub, etc
AFAIK, ML produces short opcode form for the short immediates, i.e., for ADD EAX,4 this would be db 83h,0C0h,04h, and 83h, 0E0h, 0FCh for the AND EAX,-4
as usual, you're right, Alex :P
another bad habit i have to break from the 8086 days
Hi,
It works the same for the 8086. Abstracted from a TASM
reference.
83 /0 ib ADD r/m16,imm8 Add a sign-extended immediate
byte to r/m word
Regards,
Steve N.
huh ?
what the hell am i thinking - lol
i was pretty sure that
ADD AX,8
was 3 bytes long
and that
ADD DX,8
was 2
now you guys are just picking on me because i am getting old - lol
mov edx,StringLength
and edx,03h
jz align_4
not dl
inc dl
and dl,03h
add edx,StringLenght
align_4:
;edx = buffer length
Hi,
Minor question. Or brainfart?
not dl
inc dl
; Is that not the same result as...
NEG DL ; except for carry flag?
Regards,
Steve
Me I am so used to the memalign opcode :bg
include \masm32\include\masm32rt.inc
.code
Dummy db 123
txDave db "Hi, Dave!", 0
AppName db "Masm32:", 0
start: mov esi, offset txDave
memalign esi, 4
MsgBox 0, esi, addr AppName, MB_OK
exit
end start
mov edx,StringLength
and edx,03h
jz align_4
not dl
inc dl
and dl,03h
add edx,StringLenght
align_4:
;edx = buffer length
not dl
inc dl
; Is that not the same result as...
NEG DL ; except for carry flag?
even so - that is a lot of code - ouch !
i like...
add edx,3
and edx,-4
a lot better
memalign macro from masm32 :bg
memalign MACRO reg, number
add reg, number - 1
and reg, -number
ENDM
at least i got one thing right, today
i feel like my mind is slipping farther and farther every day around you guys
well, i used to be pretty sharp :lol
i was also good lookin, but i don't remember what that was like, either
Yes, neg works, maybe I need sleep a bit hehehe.
align2 proc len:dword,multiple_of_2:dword
;to do: need check if multiple of 2 is so high to fit in this dword
push ecx
mov edx,len
mov ecx,multiple_of_2
dec ecx
and edx,ecx
neg edx
and edx,ecx
add edx,len
pop ecx
ret
align2 endp
:dazzled:
align2 proc len:dword,multiple_of_2:dword
;to do: need check if multiple of 2 is so high to fit in this dword
mov edx,multiple_of_2
mov eax,len
add eax,edx
dec eax
neg edx
and eax,edx
ret
align2 endp
Fatality, Sr Dedndave wins, flawers victory hehehe. :thumbu
or
mov eax,Value
mov edx,Alignment
dec eax
dec edx
or eax,edx
inc eax
and aligned memory alloc
if @WordSize ne 8
rax equ <eax>
rdx equ <edx>
size_t typedef dword
else
size_t typedef qword
endif
_alloc:
mov rax,_ALLOC_BYTES
add rax,_MEMORY_ALIGN
invoke HeapAlloc,_HHEAP,HEAP_GENERATE_EXCEPTIONS+HEAP_ZERO_MEMORY,rax
mov rdx,rax
add rax,_MEMORY_ALIGN
and rax,-_MEMORY_ALIGN
mov [rax-size_t],rdx
ret
_free:
mov rax,[rax-size_t]
invoke HeapFree,_HHEAP,HEAP_GENERATE_EXCEPTIONS+HEAP_ZERO_MEMORY,rax
ret
sorry, drizz, i don't speak "rax" :lol
Rob,
To address your original question, there is no overriding reason to make a buffer divisible by 4. As Erol mentioned allocated memory is already 8 byte aligned and the solution is to simply make your buffer large enough to fit the data you want to put into it. Memory is rarely ever allocated in very small amounts at an OS level so there is no reason why you should have to trim its size down to an arbitrary byte count. Now this means that if you need 15k there is no loss at allocating 16k.
If you need to have memory aligned by greater than 8 bytes, add the extra onto the buffer length then align a location near the beginning of the start address and pass back a pointer to that location. When you deallocate the memory later make sure you deallocate the original memory pointer, not the aligned location. This matters if you want to use later SSE opcodes where they require 16 byte alignment.
dec eax ; make sure # is either aligned to lower value or not aligned
and eax, -2 ; align down, has no effect if aligned to lower
add eax, 2 ; += 2
number 0, 2byte aligned will result in 0
number 1, 2byte aligned will result in 2
number 2, 2byte aligned will result in 2
number 3, 2byte aligned will result in 4
number 4 2byte aligned will result in 4
why not...
inc eax
and eax,-2
INC/DEC only works for 2-alignment
larger than that, and you are back to...
add eax,M-1
and eax,-M