Page 1 of 1

Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 1:47 am
by Cjreek
Hi,

Just a little question:

As far as I understand LOCK it essentially does "nothing" on a single core CPU.
Is this right?

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 2:13 am
by Combuster
Even with a single CPU core, there can be several other devices trying to access memory.

LOCK initially blocked the entire system bus. Now it only does that for uncached memory, but it still tries to enforce full read-modify-write atomicity against all non-CPU devices that way.

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 2:34 am
by Cjreek
Okay thanks.

I saw someone in this forum who made an (x86-) emulator and I'm trying to do it myself because that sounds really interesting.

So my new question is: every operation in my current code is atomic at the moment. Is it okay to just ignore LOCK or do I really have to emulate how the processor may take several ticks for some instructions and how this can lead to other devices interfering with the current write operation of the cpu (if the cpu didn't lock the bus)?

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 5:23 am
by Brendan
Hi,
Cjreek wrote:So my new question is: every operation in my current code is atomic at the moment. Is it okay to just ignore LOCK or do I really have to emulate how the processor may take several ticks for some instructions and how this can lead to other devices interfering with the current write operation of the cpu (if the cpu didn't lock the bus)?
If there is never more than 1 "thing" accessing (emulated) memory at a time, then you can ignore LOCK. This includes emulators that emulate multi-CPU; if the emulator executes one instruction from one CPU, then executes the next instruction from the next CPU, etc. It doesn't include (e.g.) a multi-threaded emulator that use one thread to emulate a single CPU plus another thread to emulate DMA/bus mastering devices.

Note: You would also need to emulate the "invalid LOCK prefix" case correctly. For example, if someone does "lock add eax,ebx" then you're supposed to invoke the invalid opcode exception and can't just execute it as if it was "add eax, ebx".


Cheers,

Brendan

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 5:36 am
by Cjreek
Okay that's nice. This saves me a lot of work :)

Throwing some invalid opcode exceptions is fine and not a big deal.

But wait:
LOCK add cl, dl
This compiles into
F0 00 D1
which represents
ADD r/m8, r8
http://ref.x86asm.net/coder32.html

Is this a valid opcode altough the destination operand is a register and no memory location?

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 6:05 am
by Combuster
r/m
That's a shorthand of register/memory

The D1 is actually 11 010 001 binary. There are 8 registers, which means you need three bits to define one. That leaves you two extra bits you will want to use instead of letting them go to waste. 00 is a simple memory operand, 01 and 10 are memory operands with offsets, and 11 means a register instead.

(and please don't use colours, they make reading a pain)

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 6:12 am
by Brendan
Hi,
Cjreek wrote:Is this a valid opcode altough the destination operand is a register and no memory location?
No.

For the bytes "0xF0, 0x00, 0x??" the third byte is a ModRM byte that determines if the instruction has a memory location or not. If the ModRM byte says there's a memory location then the instruction is valid. If the ModRM byte says there's no memory location then the instruction is illegal.


Cheers,

Brendan

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 6:28 am
by Cjreek
Combuster wrote:
r/m
That's a shorthand of register/memory

The D1 is actually 11 010 001 binary. There are 8 registers, which means you need three bits to define one. That leaves you two extra bits you will want to use instead of letting them go to waste. 00 is a simple memory operand, 01 and 10 are memory operands with offsets, and 11 means a register instead.

(and please don't use colours, they make reading a pain)
Yes I know those things (otherwise I couldn't have done anything with my emulator :mrgreen: )
It's just that the destination operand of this opcode 0x00 can either be a register (11) or a memory location (00-10).

And I thought LOCK is only valid if the destination operand is actually a memory location.

@Brendan:

Okay that's what I wanted to know :)

It just found it to be strange that NASM did compile this without an error altough this opcode will always end in an invalid opcode exception :-k

EDIT:

WAIT again! I just compiled this with nasm and loaded it with qemu:

Code: Select all

[BITS 16]
mov ax, 0xAABB
LOCK add cl, dl
mov ax, 0xCCDD
jmp $

times 510-($-$$) db 0
db 0x55
db 0xAA
after booting my image I printed eax and it's 0xCCDD. So LOCK add cl, dl seems to be valid!

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 1:42 pm
by Octocontrabass
Cjreek wrote:So LOCK add cl, dl seems to be valid!
Currently, qemu does not catch invalid locks (other than "lock nop"). On a more accurate emulator or a real CPU, your test will fail.

Re: Assembly instruction prefix: LOCK

Posted: Wed Oct 01, 2014 2:04 pm
by Cjreek
Okay than my emulator may be more accurate than qemu :mrgreen:
And I think there's no more confusion about LOCK so thanks to everyone who helped me with this issue :)

Re: Assembly instruction prefix: LOCK

Posted: Wed Nov 05, 2014 11:41 am
by Czernobyl
Fwiw, and for the record, use of the LOCK prefix was unrestricted on x86 prior to 80386, so : " lock add cl,dl " is valid on these early intel processors. Also for the record, it appears the opcode position 0xF1
on these processors was an undocumented alias for LOCK (0xF0).