我一直在讨论一些x86程序集,因为它出现在我的许多课程中.特别是,我想将比较和交换(CAS)作为用户函数公开.这是为了我可以实现自己的锁.
我在Intel CPU上使用Linux 2.6.31和GCC 4.1.1.
我有以下内容:
// 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
这是在*.s文件中,我用我的驱动程序编译.当我包括该行
lock cmpxchgl %edx, %ecx
并执行,我收到"非法指令"错误.当我用线替换
cmpxchgl %edx, %ecx
我的代码似乎运行正常.
首先,有lock
必要吗?我不确定是否cmpxchgl
是天然的原子,所以我曾经lock
确定过.作为用户地计划,我甚至被允许使用lock
?
谢谢
================================================== ==============
我的最终代码(对于那些可能在将来徘徊的人):
// 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
DigitalRoss.. 7
cmpxchgl %edx, (%ecx)
除非目标是内存操作数,否则此操作没有意义,但该指令允许寄存器目标.如果指令使用寄存器模式,CPU将发生故障.
我尝试过,你的代码使用内存操作数.我不知道你是否意识到这一点,但这个序列(带寄存器目的地)有一个流行的名字:"f00fc7c8 bug"或" F00F bug ".在Pentium时代,这是一个"HCF"(停止和着火)或"杀手捅"指令,因为它会产生一个例外,由于总线被锁定而无法服务,并且它可以从用户调用模式.我认为可能存在操作系统级别的软件解决方法.
cmpxchgl %edx, (%ecx)
除非目标是内存操作数,否则此操作没有意义,但该指令允许寄存器目标.如果指令使用寄存器模式,CPU将发生故障.
我尝试过,你的代码使用内存操作数.我不知道你是否意识到这一点,但这个序列(带寄存器目的地)有一个流行的名字:"f00fc7c8 bug"或" F00F bug ".在Pentium时代,这是一个"HCF"(停止和着火)或"杀手捅"指令,因为它会产生一个例外,由于总线被锁定而无法服务,并且它可以从用户调用模式.我认为可能存在操作系统级别的软件解决方法.