簡體   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