繁体   English   中英

SIGSEGV使用装配访问数组元素时

[英]SIGSEGV When accessing array element using assembly

背景:

我是新来的。 在学习编程时,我制作了一个程序,实现了高达1000 * 1000的乘法表。这些表经过格式化,因此每个答案都位于行factor1 << 10 | factor2 factor1 << 10 | factor2 (我知道,我知道这不是很漂亮)。 然后将这些表加载到一个数组中: int* tables 空行用0填充。 是到表文件的链接(7.3 MB)。 我知道使用汇编不会大大加快此过程,但是我只是想做些有趣的事情(还有一些练习)。

题:

我正在尝试将此代码转换为内联汇编( tables是全局的):

int answer;
// ...
answer = tables [factor1 << 10 | factor2];

这是我想出的:

asm volatile ( "shll $10, %1;"
           "orl %1, %2;"
           "movl _tables(,%2,4), %0;" : "=r" (answer) : "r" (factor1), "r" (factor2) );

我的C ++代码可以正常运行,但是我的汇编失败。 与我的C ++相比,我的程序集有什么问题(特别是movl _tables(,%2,4), %0;部分)

我为解决该问题所做的工作:

我使用了一些随机数:89 796作为factor1factor2 知道89 << 10 | 786 89 << 10 | 786 (即91922 )–使用C ++进行了验证。 当我使用gdb运行它时,我得到一个SIGSEGV:

程序收到信号SIGSEGV,分段故障。

在这一行:

"movl _tables(,%2,4), %0;" : "=r" (answer) : "r" (factor1), "r" (factor2) );

我在asm周围添加了两种方法,这就是我如何知道asm块在反汇编中的位置的方法。

拆卸我的asm块:

objdump -M att -d反汇编看起来很好(尽管我不确定,我是新来的汇编程序,正如我所说):

402096: 8b 45 08                mov    0x8(%ebp),%eax
402099: 8b 55 0c                mov    0xc(%ebp),%edx
40209c: c1 e0 0a                shl    $0xa,%eax
40209f: 09 c2                   or     %eax,%edx
4020a1: 8b 04 95 18 e0 47 00    mov    0x47e018(,%edx,4),%eax
4020a8: 89 45 ec                mov    %eax,-0x14(%ebp)

objdump -M intel -d反汇编:

402096: 8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
402099: 8b 55 0c                mov    edx,DWORD PTR [ebp+0xc]
40209c: c1 e0 0a                shl    eax,0xa
40209f: 09 c2                   or     edx,eax
4020a1: 8b 04 95 18 e0 47 00    mov    eax,DWORD PTR [edx*4+0x47e018]
4020a8: 89 45 ec                mov    DWORD PTR [ebp-0x14],eax

据我了解,这是将我的void calc ( int factor1, int factor2 )函数的第一个参数移到eax 然后将第二个参数移到edx 然后,它将eax向左移动10 oredx 32位整数是4个字节,因此[edx*4+base_address] 将结果移动到eax ,然后将eax放入int answer (我想它在堆栈的-0x14上)。 我真的没什么大问题。

反汇编编译器的.exe

当我用纯C ++替换asm块( answer = tables [factor1 << 10 | factor2]; )并将其反汇编时,这就是我在Intel语法中得到的:

402096: a1 18 e0 47 00          mov    eax,ds:0x47e018
40209b: 8b 55 08                mov    edx,DWORD PTR [ebp+0x8]
40209e: c1 e2 0a                shl    edx,0xa
4020a1: 0b 55 0c                or     edx,DWORD PTR [ebp+0xc]
4020a4: c1 e2 02                shl    edx,0x2
4020a7: 01 d0                   add    eax,edx
4020a9: 8b 00                   mov    eax,DWORD PTR [eax]
4020ab: 89 45 ec                mov    DWORD PTR [ebp-0x14],eax

AT&T语法:

402096: a1 18 e0 47 00          mov    0x47e018,%eax
40209b: 8b 55 08                mov    0x8(%ebp),%edx
40209e: c1 e2 0a                shl    $0xa,%edx
4020a1: 0b 55 0c                or     0xc(%ebp),%edx
4020a4: c1 e2 02                shl    $0x2,%edx
4020a7: 01 d0                   add    %edx,%eax
4020a9: 8b 00                   mov    (%eax),%eax
4020ab: 89 45 ec                mov    %eax,-0x14(%ebp)

我对Intel语法不是很熟悉,因此我将尝试理解AT&T语法:

它首先将tables数组的基地址移到%eax 然后,将第一个参数移到%edx 它移位%edx 10向左然后or与该第二参数这样。 然后,通过将%edx左移2,实际上将%edx乘以4。然后,将其添加到%eax (数组的基地址)。 因此,基本上它就是这样做的: [edx*4+0x47e018] (Intel语法)或0x47e018(,%edx,4) AT&T。 它将移入%eax的元素的值并将其放入int answer 此方法更“扩展”,但它与我的手写汇编具有相同的功能! 那么为什么在编译器工作正常的情况下我给出SIGSEGV

我打赌(从反汇编中) 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 Petersson的回答的补充-我之所以写它,只是因为我现在还不清楚,为什么OP的反汇编分析(他的汇编和编译器生成的汇编是等效的)是不正确的。

正如Mats Petersson解释的那样,问题在于tables实际上是指向数组的指针,因此要访问元素,您必须取消引用两次。 现在对我来说,尚不清楚编译器生成的代码这发生在哪里 罪魁祸首是这种无辜的表情:

a1 18 e0 47 00          mov    0x47e018,%eax

对于未经训练的眼睛(包括我的眼睛),这看起来像是将 0x47e018移到了eax ,但实际上不是。 相同操作码的Intel语法表示法为我们提供了一个线索:

a1 18 e0 47 00          mov    eax,ds:0x47e018

ds: -所以它实际上不是值,而是地址!

对于现在想知道的人,以下是将 0x47e018移至eax的操作码和ATT语法汇编:

b8 18 e0 47 00          mov    $0x47e018,%eax

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM