程式的機器級表示

2021-06-23 06:35:57 字數 3356 閱讀 9653

三種:

立即數:常數值,  在att格式的彙編**中, 書寫格式是  $ + 整數, 如:$-123   $0x12

暫存器:如:32位的%eax   16位的%ax  8位的%al

儲存器引用:

mov  同等傳送, 即倆者的大小一致 (如:movb byte,  movew   word, movel  longword(dw))

movs/ movz   不同等傳送, 即倆者的大小可以不一致, 如:movsbl 表示將源byte傳送到目的longword, 用1 或0補充剩餘位(取決於源byte的最高位是否為1), movzbl 與movsbl相似, 用0補充剩餘位

push & pop

lea:  直接上例:

lea  4(%eax) %ebx   //表示 %ebx 裡面的值為%eax + 4 。       

而 mov 4(%eax) %ebx //表示 %ebx裡面的值為【eax+4】這個位址的值

其實, 複雜的來說, lea 表示獲取源位址的偏移位址, 對於上例來說, 偏移位址當然是%eax + 4 咯。

int fun (unsigned x) 

return val & 0x1;

}

這個函式是測試x二進位制裡面1的個數的奇偶, 奇返回1, 偶返回0;

理解, 第一著重於移位操作, 每次移位  都使前一位移動至後一位(即使得n位與n-1位之間的運算成為可能), 第二 著重於異或操作,對於1bit ^ 1bit來說, 恰好是檢視這倆者的1的總個數是否為偶,    第三著重於第一位,  每次移位操作  都使得前一位都能跟當前第一位進行異或操作, 而這一位的結果是這一位上的1的個數是否為偶。loop, 測試前前一位。。。。。 again and again  until it ends.

int fun (unsigned x) 

return val;

}

這是獲取x的位反轉製造出來的映象

條件跳轉, 在asm中, 是以類似cmp   +   jne    等指令實現的。 對於n種情況來說, 就意味著要n對cmp-jne這些指令。

switch對於條件轉換來說, 是利用了跳轉表來進行的(其實就是位址偏移),例如情況為100-106, 即只需要計算當前值-100 的大小(k), 跳轉到jt【k】所指的位置即可。

其實這個也說明了某種問題, 也就是對於疏散的情況集合, 對於跳轉表的使用會不會新增空白無用的區域浪費呢?

to be continued.......

類似struct可以存放資料, 不同在於, union所有資料共用記憶體, 即union的大小為資料中大小最大的, 而不是大小之和。

用處: 型別轉換。。。注意小端法讀取資料

條件:1,平台獲取資料都是以固定位元組數獲取的。 2,有些資料不規則,如:structa;   其標準大小是5bytes

導致的情況: 比如固定位元組數為8, 不對齊資料就意味著第一次讀取, 獲得  a1 以及a2的部分資料, 為了讀取a2的值, 必須讀取兩次,以及需要進行高低位的修補。。。。

所以資料對齊, 是一種以空間換時間的策略。

這也是為什麼   sizeof(a)!= 5  而是8(test in vs2013)。

測試:

struct a;

void testsizeof()

; printf("a:\na: %d\nc: %c\nb: %d\n\n", k.a, k.c, k.b);

printf("a:\na: %x\nc: %x\nb: %x\n\n", k, k, k); //其中%x表示十六進製制整數。 科普:\x 表示其後面兩位為十六進製制數,常用於printf cout等。

}結果為:

size of a is 12

a:a: 1

c: c

b: 2

a:a: 1

c: cccccc63 // 63是 'c'的十六進製制ascii字元表示形式

b: 2

表明:1, 對於結構體k來說, 執行printf多次輸出,其過程類似於檔案流讀取(讀即前進)。

2, 結構體a中, c占用的位元組為4, 其中多餘3位元組作為補充。

這也表明了資料位置排列的重要性。一般來說  應按照從大到小排列。 因為這樣可以縮小對齊要求的位元組數,如4->>2。(???若是從小到大, 會怎樣?   會呵呵。。。)

int func(int a, int *b)

typedef int (*fp) (int a, int *b);

fp = func;

int result = fp(a, &b);

其實函式呼叫call也是移動到某一指令, 跟指標有差別嗎?

int a[n],      *(a+1) = a [1];

char *cp;

(int*)cp + 7 => (cp, 4, 7)的位置

(int*)(cp+7) => (cp, 1, 7)的位置

常見的做法是 類似於char chs[8], strcpy(chs, "1234...........");導致緩衝區溢位, 覆蓋其他位址的值(被儲存的暫存器的值, 以及返回位址)

1, 棧隨機化:  即同乙個程式, 執行時的棧的位置不固定。

2, 棧破壞檢測: 即在儲存暫存器附近放置哨兵值, 程式執行後檢查哨兵值是否發生改變, 若有, 立即終止程式。當然  這意味著哨兵值必須儲存倆處, 而另一處唯一的保障是,唯讀,不能被修改, 似乎有點薄弱。。。。

3, 設定不能執行區域機制, 限制可執行區域。

總結(自我感覺):

1, 每次呼叫其他函式是, 會將引數列表反序壓棧 + 返回位址。   接著是%ebp  %ebx(或許這個跟引數有關, 因為每次push ebx之後在函式結尾都需要pop ebx 意味著ebx是乙個需要儲存的值, 不能改變, 這個豈不是傳值引數傳遞不影響引數的值的依據?)     如果此時有申請緩衝區(char buffer)則在此後面開闢乙個*8(8byte)的空間,(其序號排列順序是從自棧頂到棧底公升序) 如果對這個緩衝區進行strcpy等操作, 就有可能修改到ebp ebx等  甚至是返回位址。

2, 在有保護的**中, 常常是區域性變數比buffer更靠近棧頂, 這樣buffer溢位,不會破壞區域性變數的值。

注: sizeof(「1234」)is 5; because of 『\0』(0x00);   但是strlen返回的是4, 故在malloc的呼叫時, 應該malloc ( strlen(buf)+1 ).  記得要對返回值進行null判斷。

特殊數字:0x101010101010101        72340172838076673

程式的機器級表示

32位和64位 instruction system architecture 程式計數器pc eip 整數暫存器 8個每個32位 有的用來記錄狀態,有的用來儲存臨時資料,區域性變數,返回值 3.條件碼暫存器 指標都是雙字 char short long 其他4位元組 movb movw movl ...

程式的機器級表示

本文對 深入理解計算機系統 第三版 中第三章 程式的機器級表示 中的部分內容進行了整理,以方便日後查閱。目錄 1.整數暫存器 2.運算元 3.資料傳送指令 mov類。4.壓入和彈出棧資料 push操作和pop操作 5.算術和邏輯操作 6.條件碼 7.比較和測試指令 cmp和test 8.set指令 ...

程式的機器級表示(二)

以上操作,我們只考慮了直線 的行為,即指令按順序執行。但是還有一些 比如條件語句 迴圈語句和分支語句,要求有條件的執行,這時需要根據資料測試的結果來改變條件碼,結合跳轉指令決定操作執行的順序。條件傳送指令 實現條件操作的傳統方法是利用控制的條件轉移。當條件滿足時,程式沿著一條執行路徑進行,而當條件不...