簡體   English   中英

匯編 - x86調用指令和內存地址?

[英]Assembly - x86 call instruction and memory address?

我一直在閱讀一些匯編代碼,我開始看到調用指令實際上是程序計數器相對的。

但是,每當我使用visual studio或windbg進行調試時,它總是會調用0xFFFFFF ...這對我來說意味着它會說我要跳轉到那個地址。

誰是對的? Visual Studio是否隱藏了指令編碼的復雜性,只是說這就是程序的意思,那就是調試器知道它是一個與pc相關的指令,而且因為它知道pc,它只是為你做數學運算?

高度困惑。

如果您正在反匯編尚未鏈接的.o目標文件,則調用地址將只是一個由鏈接器填充的占位符。

您可以使用objdump -drwc -Mintel顯示 .o的重定位類型+符號名稱-r選項是鍵。或-R用於已鏈接的共享庫。)


用戶顯示跳轉目標的實際地址更有用,而不是將其反匯編為jcc eip-1234H或其他東西。 目標文件具有默認的加載地址,因此反匯編程序在每條指令處都有一個eip值,這通常出現在反匯編輸出中。

例如,在我編寫的一些asm代碼中(我使用符號名稱將其放入目標文件中,因此循環分支目標實際上對反匯編程序可見):

objdump -M intel  -d rs-asmbench:
...
00000000004020a0 <.loop>:
  4020a0:       0f b6 c2                movzx  eax,dl
  4020a3:       0f b6 de                movzx  ebx,dh
   ...
  402166:       49 83 c3 10             add    r11,0x10
  40216a:       0f 85 30 ff ff ff       jne    4020a0 <.loop>

0000000000402170 <.last8>:
  402170:       0f b6 c2                movzx  eax,dl

請注意, jne指令的編碼是帶符號的小端32位移,為-0xD0字節。 (跳轉后,它們的位移加到e/rip的值。跳轉指令本身長6個字節,所以位移必須是-0xD0 ,而不僅僅是-0xCA 。) 0x100 - 0xD0 = 0x30 ,這是值2的補碼位移的最低有效字節。

在你的問題中,你所說的是調用地址為0xFFFF... ,除非那只是占位符,否則你認為位移中的非0xFF字節是操作碼的一部分。

在鏈接之前,對外部符號的引用如下所示:

objdump -M intel -d main.o
  ...
  a5:   31 f6                   xor    esi,esi
  a7:   e8 00 00 00 00          call   ac <main+0xac>
  ac:   4c 63 e0                movsxd r12,eax
  af:   ba 00 00 00 00          mov    edx,0x0
  b4:   48 89 de                mov    rsi,rbx
  b7:   44 89 f7                mov    edi,r14d
  ba:   e8 00 00 00 00          call   bf <main+0xbf>
  bf:   83 f8 ff                cmp    eax,0xffffffff
  c2:   75 cc                   jne    90 <main+0x90>
  ...

注意call指令的相對位移= 0。因此,在鏈接器插入實際相對值之前,它們會在call編碼一個帶有指令目標的調用。 (即RIP = RIP+0 )。 call bf之后緊跟一條指令,該指令從該節的開始處開始於0xbf 另一個call具有不同的目標地址,因為它位於文件中的不同位置。 (gcc將main放在它自己的部分: .text.startup )。

因此,如果您想了解實際調用的內容,請查看鏈接的可執行文件,或者獲取一個反匯編程序,該反匯編程序查看目標文件符號以插入調用目標的符號名稱,而不是將它們顯示為零位移的調用。

在鏈接之前,已經解析了對本地符號的相對跳轉:

objdump -Mintel  -d asm-pinsrw.o:
0000000000000040 <.loop>:
  40:   0f b6 c2                movzx  eax,dl
  43:   0f b6 de                movzx  ebx,dh
  ...
 106:   49 83 c3 10             add    r11,0x10
 10a:   0f 85 30 ff ff ff       jne    40 <.loop>
0000000000000110 <.last8>:
 110:   0f b6 c2                movzx  eax,dl

注意,完全相同的指令編碼相對跳轉到同一文件中的符號,即使文件沒有基址,因此反匯編程序只是將其視為零。

有關指令編碼,請參閱英特爾參考手冊。 鏈接https://stackoverflow.com/tags/x86/info 即使在64位模式下, call僅支持32位符號擴展相對偏移。 支持64位地址作為絕對地址。 (在32位模式下,支持16位相對地址,帶有操作數大小前綴,我想保存一個指令字節。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM