64位元變數在32位元跟64位元的不同 -- 從assemble的角度來看
OS: Ubuntu x86_64
gcc: gcc version 4.7.3
最近看了一本關於Debug的書,把好久沒看的Assembly也看了一下。對於以前寫C語言其實都不太會去看gcc會把你的code轉成什麼樣的assembly都不太關心。那也剛好最近比較有空(空了好久了 XD)就看到書上有寫有關64位元的變數在這兩個架構上的assembly會有不同,但書上也只是寫個簡單的敘述。
我也想說直接Dump Assembly直接看會更清楚。所以我做了以下的簡單的實驗。
1. Source Code
這是我要看的source code主要只是看64位元的變數在32位元跟64位元架構的assembly有什麼不同。所以只有只有簡單的兩行。所以我assemble只有專注於gcc會怎樣處理這個 變數。
首先我定義了一個unsigned long long 64位元的變數,並且給他一個64位元的值。
#include <stdio.h>
int main(int argc, const char *argv[])
{
unsigned long long val64 = 0;
val64 = 0xffffeeeeddddcccc;
return 0;
}
2. 32位元Assembly
因為我的電腦是x86_64的OS,所以要編譯32位元的assembly要在gcc的參數輸入-m32來讓gcc知道我們要編譯成32位元
$> gcc -Wall -m32 -O0 main.c -o assemble32
$> objdump -d --no-show-raw-insn assemble32
080483ec <main>:
80483ec: push %ebp
80483ed: mov %esp,%ebp
80483ef: and $0xfffffff8,%esp
80483f2: sub $0x10,%esp
80483f5: movl $0x0,0x8(%esp)
80483fd: movl $0x0,0xc(%esp)
8048405: movl $0xddddcccc,0x8(%esp)
804840d: movl $0xffffeeee,0xc(%esp)
8048415: mov $0x0,%eax
804841a: leave
804841b: ret
804841c: xchg %ax,%ax
804841e: xchg %ax,%ax
3. 64位元Assembly
$> gcc -Wall -O0 main.c -o assemble
$> objdump -d --no-show-raw-insn assemble
00000000004004ec <main>:
4004ec: push %rbp
4004ed: mov %rsp,%rbp
4004f0: mov %edi,-0x14(%rbp)
4004f3: mov %rsi,-0x20(%rbp)
4004f7: movq $0x0,-0x8(%rbp)
4004ff: movabs $0xffffeeeeddddcccc,%rax
400509: mov %rax,-0x8(%rbp)
40050d: mov $0x0,%eax
400512: pop %rbp
400513: retq
400514: nopw %cs:0x0(%rax,%rax,1)
40051e: xchg %ax,%ax
4. 討論
看得出來32跟64的差別了嗎?主要是在分配值的時候32位元要將資料拆成兩份分別存入在兩個32位元的位置上來模擬64位元的變數。
所以32位元上會花兩步movl來處理64位元的變數,所以設計上就要很注意這個問題了。
留言