C++ 使用汇编访问数组元素时的SIGSEGV 背景:
我不熟悉集会。当我学习编程时,我做了一个程序,实现了1000*1000的乘法表。表格的格式是这样的,每个答案都在C++ 使用汇编访问数组元素时的SIGSEGV 背景:,c++,arrays,segmentation-fault,inline-assembly,gnu-assembler,C++,Arrays,Segmentation Fault,Inline Assembly,Gnu Assembler,我不熟悉集会。当我学习编程时,我做了一个程序,实现了1000*1000的乘法表。表格的格式是这样的,每个答案都在factor1行上,我打赌表格是指向数组的指针,而不是数组本身 因此,您需要: asm volatile ( "shll $10, %1;" movl _tables,%%eax "orl %1, %2;" "movl (%%eax,%2,4)", : "=r" (answer) : "r" (factor1), "r" (
factor1行上,我打赌表格
是指向数组的指针,而不是数组本身
因此,您需要:
asm volatile ( "shll $10, %1;"
movl _tables,%%eax
"orl %1, %2;"
"movl (%%eax,%2,4)",
: "=r" (answer) : "r" (factor1), "r" (factor2) : "eax" )
(别忘了最后一行的额外打击)
当然也有一些变化,如果代码在循环中,这可能更有效:
asm volatile ( "shll $10, %1;"
"orl %1, %2;"
"movl (%3,%2,4)",
: "=r" (answer) : "r" (factor1), "r" (factor2), "r"(tables) )
(从反汇编中)我打赌表
是指向数组的指针,而不是数组本身
因此,您需要:
asm volatile ( "shll $10, %1;"
movl _tables,%%eax
"orl %1, %2;"
"movl (%%eax,%2,4)",
: "=r" (answer) : "r" (factor1), "r" (factor2) : "eax" )
(别忘了最后一行的额外打击)
当然也有一些变化,如果代码在循环中,这可能更有效:
asm volatile ( "shll $10, %1;"
"orl %1, %2;"
"movl (%3,%2,4)",
: "=r" (answer) : "r" (factor1), "r" (factor2), "r"(tables) )
这是对Mats Peterson答案的补充——我写这篇文章的原因很简单,因为我不清楚OP对反汇编的分析(他的汇编和编译器生成的汇编是等效的)为什么不正确
正如Mats Peterson所解释的,问题在于表
实际上是指向数组的指针,因此要访问元素,必须取消引用两次。现在对我来说,这在编译器生成的代码中发生在哪里还不清楚。罪魁祸首是这条看起来无辜的线:
a1 18 e0 47 00 mov 0x47e018,%eax
对于未经培训的人(包括我的),这可能看起来像值0x47e018
被移动到eax
,但实际上不是。相同操作码的英特尔语法表示为我们提供了一个线索:
a1 18 e0 47 00 mov eax,ds:0x47e018
啊-ds:
-所以它实际上不是一个值,而是一个地址
对于现在想知道的人,下面是将值0x47e018
移动到eax
的操作码和ATT语法汇编:
b8 18 e0 47 00 mov $0x47e018,%eax
这是对Mats Peterson答案的补充——我写这篇文章的原因很简单,因为我不清楚OP对反汇编的分析(他的汇编和编译器生成的汇编是等效的)为什么不正确
正如Mats Peterson所解释的,问题在于表
实际上是指向数组的指针,因此要访问元素,必须取消引用两次。现在对我来说,这在编译器生成的代码中发生在哪里还不清楚。罪魁祸首是这条看起来无辜的线:
a1 18 e0 47 00 mov 0x47e018,%eax
对于未经培训的人(包括我的),这可能看起来像值0x47e018
被移动到eax
,但实际上不是。相同操作码的英特尔语法表示为我们提供了一个线索:
a1 18 e0 47 00 mov eax,ds:0x47e018
啊-ds:
-所以它实际上不是一个值,而是一个地址
对于现在想知道的人,下面是将值0x47e018
移动到eax
的操作码和ATT语法汇编:
b8 18 e0 47 00 mov $0x47e018,%eax
你为什么要做编译器的工作?@TonyTheLion刚刚读到了一个问题:“我知道使用汇编不会加快很多速度,但我只是想做这件事是为了好玩(还有一点练习)。”“有人想做编译器”听起来更有趣,@Tony.asm volatile的volatile
部分告诉编译器它根本不能移动程序集的一部分,也不能在程序集周围移动代码的其他部分。这会阻止编译器内置的优化器执行其工作。您不应该将程序集指定为volatile
,除非您确定需要这样做,并且您了解原因。需要它的一个很好的例子是rdtsc
,因为您不希望编译器移动该代码,否则它会计时错误。@SoapBox感谢您指出这一点,我将删除它。您为什么要尝试做编译器的工作?@TonyTheLion请阅读以下问题:“我知道使用汇编不会加快很多速度,但我只是想做它的乐趣(和一点练习)。”“有人试图成为一名编译器“听起来很有趣,@Tony.asm volatile
的volatile
部分告诉编译器它根本不能移动程序集的一部分,也不能在程序集周围移动代码的其他部分。这会阻止编译器内置的优化器执行其工作。您不应该将程序集指定为volatile
,除非您确定需要这样做,并且您了解原因。需要它的一个很好的例子是rdtsc
,因为您不希望编译器移动该代码,否则它会计时错误。@SoapBox感谢您指出这一点,我将删除它。非常感谢!在movl
的末尾有一个逗号,使编译器感到困惑。除此之外,它工作得非常好!非常感谢你!在movl
的末尾有一个逗号,使编译器感到困惑。除此之外,它工作得非常好!
a1 18 e0 47 00 mov eax,ds:0x47e018
b8 18 e0 47 00 mov $0x47e018,%eax