News:

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

Windows Weirdness

Started by Astro, August 19, 2009, 09:01:16 PM

Previous topic - Next topic

Astro

I've likely made another beginners mistake here...

It appears to work correctly in a stand-alone .exe, but when I moved the code to a DLL loaded during Windows boot, it generates a memory access error 0x00000000 (can't remember if it was read or write).

num db "SomeString",0,0,0,0,0,0
...
pushad ; required - Windows crashes without this

; my code in here...

cld
mov ecx,1h
mov esi,offset num
mov edi,0h
cmpsb

; my code in here...

popad ; required - Windows crashes without this


What I wanted to do was check the first byte for a null value. In the code it contains an 8 byte string, null terminated, but padded with sufficient nulls to extend the total length to 16 bytes, including null terminator.

Is there anything obvious here that I'm missing that would create a memory access violation?

I do wonder if I should use 'byte ptr' instead of 'offset', but I can't see how that would prevent a memory access violation, especially as 'offset' works in a stand-alone .exe, and neither result in reading beyond the end of the string, or otherwise beyond the end of the data. Very bizarre.  :eek

Best regards,
Astro.

FORTRANS

Hi,

   You are loading ESI with the offset to your strong.
You load EDI with zero.  CMPSB will then read from
your string and the memory at zero to compare them.
That causes the memory access error.

   You probably want to put zero in AL, The offset in
EDI and use SCASB to scan for a zero.

HTH,

Steve

Astro

 :eek :eek :eek :eek

That makes sense - it is expecting a memory address in esi/edi not a value.

Thanks!

Best regards,
Astro.

dedndave

also, if you are going to cmpsb a single byte, ecx need not hold the quantity
ecx needs to be set to a length if the rep prefix is used
hang in there, Astro   :U
try this code....

        xor     eax,eax
        mov     ecx,eax
        mov     edi,offset num
        repnz   scasb
        dec     edi
        neg     ecx

afterwards, edi will point to the first 0
ecx will be the string length
hint - one of the few cases where ecx=0 means 4,294,967,296, or 100000000h
it makes the scas comparison, then decrements the ecx register, so after the first byte, ecx=FFFFFFFFh

Astro

Ahh - I thought ecx was decremented by cmpsb not rep.

Quotehang in there
Sure will!

Thanks for the code snippet!  :thumbu

I see you put the address of num in edi, not esi? Is it not addressed edi:esi ?????

EDIT:
QuoteAE SCASB Compare AL with byte at ES:(E)DI and set status flags

OK - when is it esi:edi and edi:esi? Is there a rule or is it just how the instruction is put together at the time?

mov edi,offset num
xor eax,eax
cmpsb ; compare al with dl
jz SomeLabel ; jmp if byte NULL


Best regards,
Astro.

dedndave

well - it isn't "esi:edi" or "edi:esi" - it is esi and edi - lol
when you put a ":" between registers, it implies they are paired to hold a single large value
sometimes. you may also see a segment register paired with a register - es:[di], for example
esi is the source index, edi is the destination index
some string instructions (like scas) require only one index register
lods - esi
stos - edi
scas - edi
cmps - esi and edi
movs - esi and edi

Quotecmpsb ; compare al with dl
that should read cmpsb ; compare al with [edi]

Astro

OK...

If I have:

MyString db "abcd",0

is it loaded into EDI as:

d|c|b|a
-------- edi
     ---- di
        -- dl

?

Best regards,
Astro.

dedndave

first, DL is the lower 8 bits of the EDX register - not EDI
only EAX, EBX, ECX, and EDX are split registers
but, yes, if you were to "mov edi,dword ptr MyString", the ascii "d" would be the high 8 bits of edi
notice i used "dword ptr" as a size override
that is because the data was defined as bytes and we are moving it into a dword register
the lower case letter 'a' is 97, or 61h, so edi would be 64636261h
this is not a normal use of edi, however
usually, we would put the offset of MyString into the edi register with "mov edi,offset MyString"
in that case, it is a 32-bit address that is assigned by the assembler
as assembler programmers, we are not generally too concerned with the exact value of the addresses

dedndave

#8
btw Astro - you have a great nic for avatars - lol
i found a couple you might like

Astro

hehe - thanks!  :thumbu

I see - it is either EDI or DI.

Hmm - so if I got this right:

mov edi,dword ptr var - moves the CONTENTS of var into EDI

whilst:

mov edi,offset var - moves the ADDRESS of var into EDI

?

(Off-topic slightly)...so following on from that, what is the effect of:

mov eax,dword ptr [SomePointer]

if SomePointer was a DWORD pointing to an arbitrary block of memory for example?

Would it be:

0x00000000: 0x45 = SomePointer
0x00000001: 0xF4 = SomePointer
0x00000002: 0xAC = SomePointer
0x00000003: 0x12 = SomePointer
...
0x45F4AC12: 0x00 - first byte of the dword at 0x45F4AC12 pointed to by SomePointer?

If it was mov eax,offset [SomePointer] am I correct in thinking this would move the CONTENTS of 0x45F4AC12 into eax and not the ADDRESS of SomePointer (0x00000000)?

Best regards,
Astro.

dedndave

that gets the value at the address named SomePointer
now, understand, that may be an address of some other data, stored as a dword pointer
we often pass pointers instead of data because you can send a pointer
to a structure that may contain many types and sizes of data
we often pass pointers to strings, as the string may be any length
i am working on a program now that has a circular buffer
the buffer is an array, 4 dwords per element
i use 2 pointers in the same structure to keep track of the "head" and "tail" of the buffer
in this case, as the buffer becomes full, i want to discard the oldest data
so, when i add an element to the array, i add 16 to the tail pointer
if the tail pointer is past the end of the array, i wrap it back to the beginning
if the new tail pointer is equal to the head pointer, i have to discard an element by bumping the head by 16
(that is because the condition of head=tail indicates empty buffer in this case)
that also means the updated tail pointer points to the location of the next entry
when i want to add something to the buffer, i grab the tail pointer and use it as a destination address
well - you get the idea - just trying to give you an example of uses of pointers
as you can see, this is much faster than moving all the elements in the array up by 16 bytes each time i add an element

Astro

Actually I'm confusing myself now.

Address of SomePointer = 0000

0000: 0005
0005: 2345

mov reg,SomePointer ; 0000

mov reg,[SomePointer] ; 0005

mov reg,word ptr SomePointer ; 0005

mov reg,word ptr [SomePointer] ; 2345 or 0005 ?

Best regards,
Astro.

dedndave

what may be confusing you is the brackets
in your examples, nothing will change if you remove the brackets altogether
the only time you must use brackets is to use a register as an address like: "[ebx]" is different than "ebx"
another thing that may be confusing you is the use of "ptr"
there are two times you need to use "ptr"
1) to override the declared size of defined data
2) to specify the bit-width of an immediate value

1) if i have a data item defined as a dword "DwordVal dd 12345678h" (32-bit value)
let's say i want to load only the low-order 16-bits into ax - then "mov ax,word ptr DwordVal"
basically, this just avoids the assembler error "operand sizes must match"
another example:
i have a string "ByteString db 'some dang string' "
i want to grab 4 bytes at a time - "mov eax,dword ptr ByteString"

2) this is where you actually need to use the ptr to inform the assembler how wide an immediate value is
cmp  [ebx],0
the assembler has no idea if you are refering to a byte, a word, or a dword
cmp dword ptr [ebx],0
now, the assembler knows you want to compare a dword to 0

Astro

Hmm....

If I had:

call HeapAlloc
mov SomeMemPtr,eax

and then:

mov SomeMemPtr,5h

this would trash SomeMemPtr and I'd lose the pointer to my memory.

I'd need to use:

mov byte ptr [SomeMemPtr],5h

so that 0x5 went into the first byte of where SomeMemPtr pointed, and not into SomeMemPtr itself.

Without the brackets, I'd trash the reference.

:eek :eek :eek

Actual example:

mov esi,offset [ptr_DEVICE_LIST_INFO+16]

I'll look at this tomorrow - 0300 here. I'm going to utterly confuse myself.  :eek

Best regards,
Astro.

dedndave

same same
the last example would also trash it
there are no labels to directly address allocated memory
you might do this:

        mov     ebx,SomeMemPtr
        mov dword ptr [ebx],5

Quotemov esi,offset [ptr_DEVICE_LIST_INFO+16]

        mov     esi,offset ptr_DEVICE_LIST_INFO+16

esi will contain the address of 16 bytes above ptr_DEVICE_LIST_INFO
i think what you are wanting to do isn't allowed
that is to use a stored memory location as an address to access another memory location
you have to either get the address into a register or address it directly with a label - or a combination of the two

http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_4/CH04-1.html