问题描述
我一直在瞎搞一些x86汇编作为其拿出了一些我的班。特别是,我一直想揭露比较和交换(CAS)作为用户的功能。这是我能实现自己的锁的意图。
我在英特尔CPU上使用Linux 2.6.31使用GCC 4.1.1。
我有以下内容:
// INT CMPXCHG为(int * DEST,预计诠释,诠释更新)
.globl CMPXCHG
CMPXCHG:
pushl%EBP
MOVL%ESP,EBP% // EDX持有DEST
MOVL 8(EBP%),EDX%
// EAX持有预期值
MOVL 12(%EBP),EAX%
// ECX持有新价值
MOVL 16(%EBP),ECX% // CMPXCHG dest_addr,exp_value
//比较%eax中是隐含的
锁定cmpxchgl%EDX,ECX% 离开
RET
这是一个* .s文件,这是我和我的驱动程序编译内。当我包含行
锁cmpxchgl%EDX,ECX%
和执行,我收到一个非法指令错误。
当我更换行
cmpxchgl%EDX,ECX%
我的code似乎运行正常。
首先,是锁定
有必要吗?我不知道 cmpxchgl
是否自然是原子,所以我用锁定
是肯定的。作为一个用户级程序,我是不是即使允许使用锁定
?
感谢
=============================================== =================
我的最后code(对于那些谁可以漫步在这里的未来):
// INT CMPXCHG为(int * DEST,预计诠释,诠释更新)
.globl CMPXCHG
CMPXCHG:
pushl%EBP
MOVL%ESP,EBP% // EDX持有DEST,使用EDX为目标;-)
MOVL 8(EBP%),EDX%
// EAX持有隐含预期值
MOVL 12(%EBP),EAX% // CMPXCHG dest_add,src_value
锁定cmpxchgl%EDX,16(%EBP) 离开
RET
您需要 cmpxchgl%EDX,(ECX%)
这个操作没有任何意义,除非目的地是一个内存操作数,但指令允许登记的目的地。如果指令使用寄存器模式时,CPU会发生故障。
我试了一下,你的code工作与内存操作数。我不知道你是否意识到这一点,但这个序列(与寄存器目的地)有一个流行的名字:在f00fc7c8错误或的。在奔腾天,这是一个小贩管理队(停止并起火)或杀手戳指令,因为它会产生一个异常,它不会再能服务,因为公交车被锁定,它是从用户调用模式。我认为有可能是操作系统级软件解决方法。
I've been messing around with some x86 assembly as its come up in a number of my classes. In particular, I've wanted to expose compare-and-swap (CAS) as a user function. This is with the intent that I can implement my own locks.
I'm using Linux 2.6.31 with GCC 4.1.1 on an Intel CPU.
I have the following:
// int cmpxchg(int *dest, int expected, int update)
.globl cmpxchg
cmpxchg:
pushl %ebp
movl %esp, %ebp
// edx holds dest
movl 8(%ebp), %edx
// eax holds expected value
movl 12(%ebp), %eax
// ecx holds the new value
movl 16(%ebp), %ecx
// cmpxchg dest_addr, exp_value
// compare to %eax is implicit
lock cmpxchgl %edx, %ecx
leave
ret
This is within a *.s file, which I compile with my driver program. When I include the line
lock cmpxchgl %edx, %ecx
and execute, I receive an "Illegal instruction" error.When I replace the line with
cmpxchgl %edx, %ecx
my code seems to run fine.
First off, is lock
necessary? I'm not sure whether cmpxchgl
is naturally atomic, so I used lock
to be sure. As a userland program, am I even allowed to use lock
?
Thanks
================================================================
My final code (for those who may wander here in the future):
// int cmpxchg(int *dest, int expected, int update)
.globl cmpxchg
cmpxchg:
pushl %ebp
movl %esp, %ebp
// edx holds dest, use eDx for Destination ;-)
movl 8(%ebp), %edx
// eax holds expected value implicitly
movl 12(%ebp), %eax
// cmpxchg dest_add, src_value
lock cmpxchgl %edx, 16(%ebp)
leave
ret
You need cmpxchgl %edx, (%ecx)
This operation doesn't make sense unless the destination is a memory operand, however the instruction allows a register destination. The CPU will fault if the instruction uses a register mode.
I tried it, your code works with a memory operand. I don't know if you realize this, but this sequence (with a register destination) has a popular name: "the f00fc7c8 bug" or "the F00F bug". In the Pentium days this was an "HCF" (halt and catch fire) or "killer poke" instruction, as it would generate an exception which it would not then be able to service because the bus was locked, and it was callable from user mode. I think there may have been an OS-level software workaround.
这篇关于在ASM非法指令:锁CMPXCHG DEST,SRC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!