Linux x86和x64的區別

0x01:寄存器分配的不一樣

 

(1)64位有16個寄存器,32位只有8個。可是32位前8個都有不一樣的命名,分別是e _ ,而64位前8個使用了r代替e,也就是r _。e開頭的寄存器命名依然能夠直接運用於相應寄存器的低32位,而剩下的寄存器名則是從r8 - r15,其低位分別用d、w、b指定長度;
(2)32位使用棧幀來做爲傳遞的參數的保存位置,而64位使用寄存器,分別用rdi,rsi,rdx,rcx,r8,r9做爲第1-6個參數,rax做爲返回值;
(3)64位沒有棧幀的指針,32位用ebp做爲棧幀指針,64位取消了這個設定,rbp做爲通用寄存器使用;
(4)64位支持一些形式的以PC相關的尋址,而32位只有在jmp的時候纔會用到這種尋址方式;

數組

0x02:(新增)彙編指令的不一樣

 

mov、push、pop擴展了movq系列的mov和pushq以及popq用來操做quad word。函數

補充:

(1)movabsq不是32位的擴展,是純新增的指令。用來將一個64位的字面值直接存到一個64位寄存器中。由於movq只能將32位的值存入,因此新增了這樣一條指令

(2)64位的彙編代碼在ret以前可能會加一句rep,這裏的rep沒有實際意義,只是出於AMD處理器的緣由,避免jmp所到達的地方直接就是ret,這樣會使得處理器運行更快一些

0x03:函數調用的不一樣spa

(1)x_64的參數經過寄存器傳遞(見前文);
callq 在棧裏存放一個8位的返回地址;
(2)許多函數再也不有棧幀,只有沒法將全部本地變量放在寄存器裏的纔會在棧上分配空間;
(3)函數能夠獲取到棧至多128字節的空間。這樣函數就能夠在不更改棧指針的狀況下在棧上存儲信息(也就是說,能夠提早用rsp如下的128字節空間,這段空間被稱爲red zone,在x86-64裏,時刻可用);
(4)再也不有棧幀指針,如今棧的位置和棧指針相關。大多數函數在調用的一開始就分配所有所需棧空間,以後保持棧指針不改變;
(5)一些寄存器被設計成爲被調用者-存儲的寄存器,這些必須在須要改變他們值的時候存儲他們而且以後恢復他們。.net

0x04:參數傳遞的不一樣設計

(1)6個寄存器用來傳遞參數(見前文);指針

(2)剩下的寄存器按照以前的方式傳遞(不過是與rsp相關了,ebp再也不做爲棧幀指針,而且從rsp開始第7個參數,rsp+8開始第8個,以此類推);blog

(3)調用時,rsp向下移動8位(存入返回地址),寄存器參數無影響,第7個及以後的參數如今則是從rsp+8開始第7個,rsp+16開始第8個,以此類推;變量


0x05:棧幀的不一樣擴展

不少狀況下再也不須要棧幀,好比在沒有調用別的函數,且寄存器足以存儲參數,那麼就只須要存儲返回地址便可。
須要棧幀的狀況:im

(1)本地變量太多,寄存器不夠;
(2)一些本地變量是數組或結構體;
(3)函數使用了取地址操做符來計算一個本地變量的地址;
(4)函數必須用棧傳送一些參數給另一個函數;
(5)函數須要保存一些由被調用者存儲的寄存器的狀態(以便於恢復);

可是如今的棧幀常常是固定大小的,在函數調用的最開始就被設定,在整個調用期間,棧頂指針保持不變,這樣就能夠經過對其再加上偏移量來對相應的值進行操做,因而EBP就再也不須要做爲棧幀指針了。雖然不少時候咱們認爲沒有「棧幀」,可是每次函數調用都必定有一個返回地址被壓棧,咱們能夠也認爲這一個地址就是一個「棧幀」,由於它也保存了調用者的狀態。

原文連接:https://blog.csdn.net/qq_29343201/article/details/51278798

相關文章
相關標籤/搜索