Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我的程序有什么问题?_C_Assembly_X86 - Fatal编程技术网

C 我的程序有什么问题?

C 我的程序有什么问题?,c,assembly,x86,C,Assembly,X86,我想不出是怎么回事。我花了几个小时试着调试这个。我是用gcc-m32 source.c-o源代码编译的 调试时,我还可以如何处理此问题?现在,我正在以许多不同的方式隔离代码,一切都按照我期望的方式工作,但当我把它们都放在一起时,它的工作方式是错误的 该程序接受一个输入,然后用1位查找最高位置 我现在删除了我的代码。我的汇编知识有点生疏,但在我看来,bitsearch过于复杂。将数字向右旋转,然后计算需要执行的次数,直到它为零,怎么样?是否需要在汇编中执行位搜索?一个简单的for循环可以完成相同的

我想不出是怎么回事。我花了几个小时试着调试这个。我是用gcc-m32 source.c-o源代码编译的

调试时,我还可以如何处理此问题?现在,我正在以许多不同的方式隔离代码,一切都按照我期望的方式工作,但当我把它们都放在一起时,它的工作方式是错误的

该程序接受一个输入,然后用1位查找最高位置


我现在删除了我的代码。

我的汇编知识有点生疏,但在我看来,
bitsearch
过于复杂。将数字向右旋转,然后计算需要执行的次数,直到它为零,怎么样?

是否需要在汇编中执行位搜索?一个简单的
for
循环可以完成相同的任务,并且可读性更高:

int num = 10;
int maxFound = -1;
for (int numShifts = 0; numShifts < 32 && num != 0; numShifts++) {
    if ((num & 1) == 1) {
        maxFound = numShifts;
    }
    num = num >> 1;
}
//the last position that had a 1 will be in maxFound
int num=10;
int maxFound=-1;
对于(int numShifts=0;numShifts<32&&num!=0;numShifts++){
如果((num&1)==1){
maxFound=numShift;
}
num=num>>1;
}
//最后一个有1的位置将在maxFound中

在bitsearch中,您将
num
存储在
eax
中,您将一个特殊值存储在
edx
中以执行
检查<代码>检查
正在测试是否设置了最高位(表示负数),如果是这种情况,则退出

check
中的
andl
指令将运算结果存储在第二个操作数(
eax
)内,因此结果覆盖
num

然后在
zero
中使用
edx
执行计算
edx
包含函数开始的特殊值,因此结果总是错误的


现在在
zero
的末尾,您将返回到
check
,但是这里不需要检查,您应该返回到
zero

有一个巧妙的位摆弄技巧:x&-x隔离最后的1位。以下C程序使用基于de Bruijn序列的查找表来计算常量(!)时间内某个数字的尾随(!)零的数量:

用汇编语言(我在16岁时就停止学习汇编语言)做这件事应该没有问题。现在,您所要做的就是反转num中的位并应用上述技术


我写了一篇关于上述技巧的论文,但不幸的是,这篇文章没有在网上发布。如果您感兴趣,我可以通过电子邮件将其发送给您(或其他感兴趣的人)。

尝试单步查看gdb下的代码,查看寄存器中发生的情况等。您能告诉我们有什么问题吗:您输入了什么号码?程序输出什么?您对输出的期望是什么?此代码不使用
gcc-m32
编译:
未定义对_num
\u position
的引用。请在发布前进行清理。解决此问题时,请确保测试是否可以检测到1的输入。我认为可能还有另一个bug…虽然可能不是这个家庭作业式问题的重点,但这可以通过使用BSR指令在没有循环的情况下完成。我假设有一个很好的理由在汇编中而不是C中完成:)我相信有更好的方法,但我仍然想克服这个问题。你描述的算法正是OP在代码中使用的算法。。。(虽然可能会优化一点)哦,呸。比我想象的更粗糙。只需将
andl
指令更改为
testl
,以避免破坏
eax
。这更复杂。。。我在问自己:为什么要检查,为什么要检查2147483648
check
只是删除符号,所以忽略我关于
和l
覆盖
num
的评论。剩下的就是
edx
应该是
eax
zero
的开头…我不知道
和1
垃圾
eax
。我认为这只是一个无害的比较。我现在要测试一下,我已经完成了关于循环的回答。不要忘记在
zero
的第一行中使用
eax
而不是
edx
…我只是想告诉你谢谢!我知道
addl
会覆盖寄存器。非常感谢。而且,
position=(int)(log(num)/log(2))
要短得多,但这根本不是OP要求的。如果OP真的想要组装怎么办?(想象一下周围的C代码只是提供测试用例的样板)是的,它必须在汇编中,但是感谢您的帮助@Adrien你使用日志的方式很有趣。我从未在编程中使用过日志,这对我来说非常陌生,但我还是一名本科生。简言之,对数(
log()
)函数是指数的倒数(
pow()
)。所以(大约),如果
pow(x,y)==n
,那么
log(n,x)==y
。不幸的是,C运行时库没有提供2个参数的日志,它只提供了一个“自然对数”。但是数学说,
log(x,y)==log(x)/log(y)
,因此上面的公式。。。现在为什么要用
2
表示
y
的值:二进制数是由“位”组成的,位是二的幂。。。
unsigned int x;  // find the number of trailing zeros in 32-bit x
int r;           // result goes here
int table[32] = 
{
  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 
  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};
r = table[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];