Main adresinde ne var?

Sep 09 2020

Bunun gibi basit bir kod parçası

#include<stdio.h>
int main()
{

    return 0;
}

gdb ile "& main" içindeki değeri kontrol edin , 0xe5894855 aldım, bunun ne olduğunu merak ediyorum?

(gdb) x/x &main
0x401550 <main>:        0xe5894855
(gdb)

Yanıtlar

4 ShaneReilly Sep 09 2020 at 21:17
(gdb) x/x &main
0x401550 <main>:        0xe5894855
(gdb)

0xe5894855esas olarak ilk komutların onaltılık işlem kodlarıdır, ancak x/xşimdi kullandığınızdan beri gdbonu yalnızca bir onaltılık sayı olarak görüntülüyor ve x86-64 küçük endian olduğu için geriye doğru. 55işlem kodu push rbpve ilk talimatıdır main. x/i &mainTalimatları görüntülemek için kullanın .

3 JohnBollinger Sep 09 2020 at 21:16

gdb ile "& main" içindeki değeri kontrol edin , 0xe5894855 aldım, bunun ne olduğunu merak ediyorum?

C ifadesi &main, bir (işlev) işaretçisi olarak değerlendirilir main.

Gdb komutu

x/x &main

ile ifade edilen adreste saklanan değeri &mainonaltılık biçimde ( /x) yazdırır (eXaminler ). Sizin durumunuzdaki sonuç şu 0xe5894855, ancak C dili bu değerin önemini belirtmiyor. Aslında C, onu programın içinden okumak için bile kesinlikle uygun bir yol tanımlamaz.

Uygulamada , bu değer muhtemelen işlevin makine kodunun ilk dört baytını temsil eder ve yerel bayt sırasına göre dört baytlık işaretsiz tamsayı olarak yorumlanır. Ancak bu, ilgili C uygulamasının hem GDB'sinin uygulama ayrıntılarına bağlıdır.

2 Lundin Sep 09 2020 at 21:21

Tamam, yani 0x401550main () 'in adresi ve sağdaki hex goo, bu adresin "içeriği" dir, bu da kodun veri değil, orada depolandığı için pek bir anlam ifade etmiyor.

Bu altıgen yapışkanın nereden geldiğini açıklamak için bazı yapay örneklerle oynayabiliriz:

#include <stdio.h>

int main (void)
{
  printf("%llx\n", (unsigned long long)&main);
}

Bu kodu gcc x86_64 üzerinde çalıştırdığımda, 401040sistemimdeki main () adresinin hangisi olduğunu anladım (bu sefer). Sonra örneği çirkin bir kodlama haline getirdikten sonra:

#include <stdio.h>

int main (void)
{
  printf("%llx\n", (unsigned long long)&main);
  printf("%.8x\n", *(unsigned int*)0x401040);
}

(Lütfen bunun gibi program kod belleğinin mutlak adreslerine erişmenin kirli bir bilgisayar korsanlığı olduğunu unutmayın. Bu çok şüpheli bir uygulamadır ve bunu denerseniz bazı sistemler bir donanım istisnası atabilir.)

alırım

401040
08ec8348

Anlamsız ikinci satır, gdb'nin vereceğine benzer bir şeydir: orada depolanan talimatlar için ham işlem kodları.

(Yani, aslında makine kodunu yazdırmak için kullanılan makine kodunu yazdıran bir program ... ve şimdi başım ağrıyor ...)

Sökme ve çalıştırılabilir dosyanın bir ikilisini oluşturduktan sonra, açıklamalı derleme ile sayısal işlem kodlarını görüntüledikten sonra şunu elde ederim:

        main:
         48 83 ec 08
401040   sub    rsp,0x8

Nerede 48 83 ec 08talimat içeren ham makine kodu vardır subonun parametreleri ile (x86 montajcı tam olarak benim işim değil, ama ben 48 olduğuna inanıyoruz "REX öneki" için op kod ve 83 olan sub). Oldukça makina koduna göre verilerin tamsayı sanki bu yazdırmaya çalışırken üzerine, gelen x86 little endian sıralamaya göre etrafında attı var 48 83 ec 08etmek 08 ec 83 48. Ve bu, önceki büyülü saçmalık 08ec8348.