2012年2月20日 星期一

gcc 產生的 16/32 bit 組合語言程式碼 (x86)

注意: 本篇的說法可能是錯的。

參考 20120912 補充那段。

first edit: 2012/2/20
gcc asm(".code16gcc\n"); 產生的 16 bit 程式碼。

這行的位址在 16/32 bit 下, 被翻譯成不同的組合語言程式碼。
21 volatile u8 *video_addr = (u8*)0xB8000;

objdump -dS b.o L22
22 11: c7 45 f8 00 80 0b 00 movl $0xb8000,-0x8(%ebp)

objdump -dS b.o(16 bit version) L22
22 16: 67 66 c7 45 f8 00 80 movw $0x8000,-0x8(%di)

由於 16 bit 版本的 pointer 是 16 bit, 所以 b8000 被截成 8000 並使用 movw, 而在 32 bit 的版本, 則完整使用 b8000 且是用 movl 指令。

b.c
 1
 2 typedef unsigned char u8;
 3
 4 int i;
 5
 6 #if 1
 7 int p()
 8 {
 9   int c=i+1;
10   volatile u8 *video_addr = (u8*)0xB8000;
11   return c;
12 }
13 #endif



objdump -dS b.o
 1
 2 b.o:     file format elf32-i386
 3
 4
 5 Disassembly of section .text:
 6
 7 00000000 <p>:
 8
 9 int i;
10
11 #if 1
12 int p()
13 {
14    0: 55                    push   %ebp
15    1: 89 e5                 mov    %esp,%ebp
16    3: 83 ec 10              sub    $0x10,%esp
17   int c=i+1;
18    6: a1 00 00 00 00        mov    0x0,%eax
19    b: 83 c0 01              add    $0x1,%eax
20    e: 89 45 fc              mov    %eax,-0x4(%ebp)
21   volatile u8 *video_addr = (u8*)0xB8000;
22   11: c7 45 f8 00 80 0b 00  movl   $0xb8000,-0x8(%ebp)
23   return c;
24   18: 8b 45 fc              mov    -0x4(%ebp),%eax
25 }
26   1b: c9                    leave 
27   1c: c3                    ret   




b.c (asm(".code16gcc\n");)
 1 asm(".code16gcc\n");
 2
 3 typedef unsigned char u8;
 4
 5 int i;
 6
 7 #if 1
 8 int p()
 9 {
10   int c=i+1;
11   volatile u8 *video_addr = (u8*)0xB8000;
12   return c;
13 }
14 #endif



objdump -dS b.o(16 bit version)
 1
 2 b.o:     file format elf32-i386
 3
 4
 5 Disassembly of section .text:
 6
 7 00000000 <p>:
 8
 9 int i;
10
11 #if 1
12 int p()
13 {
14    0: 66 55                 push   %bp
15    2: 66 89 e5              mov    %sp,%bp
16    5: 66 83 ec 10           sub    $0x10,%sp
17   int c=i+1;
18    9: 66 a1 00 00 66 83     mov    0x83660000,%ax
19    f: c0 01 67              rolb   $0x67,(%ecx)
20   12: 66 89 45 fc           mov    %ax,-0x4(%ebp)
21   volatile u8 *video_addr = (u8*)0xB8000;
22   16: 67 66 c7 45 f8 00 80  movw   $0x8000,-0x8(%di)
23   1d: 0b 00                 or     (%eax),%eax
24   return c;
25   1f: 67 66 8b 45 fc        mov    -0x4(%di),%ax
26 }
27   24: 66 c9                 leavew
28   26: 66 c3                 retw  


20120912 補充:
在真實機器驗證 (eeepc 901) 之後, 以下的反組譯可能比較精確。雖然是 16 bit code, 但是可以使用 32 bit address。不需要像 turbo c 使用特殊的 far keyword, 是因為 386 的關係嗎?不知道耶, 現在也找不到 8086 真實機器來測試了。

objdump -m i8086 -d b.o
 2 
 3 b.o:     file format elf32-i386
 4 
 5 
 6 Disassembly of section .text:
 7 
 8 00000000 <p>:
 9    0:   66 55                   push   %ebp
10    2:   66 89 e5                mov    %esp,%ebp
11    5:   66 83 ec 10             sub    $0x10,%esp
12    9:   66 a1 00 00             mov    0x0,%eax
13    d:   66 83 c0 01             add    $0x1,%eax
14   11:   67 66 89 45 f8          mov    %eax,-0x8(%ebp)
15   16:   67 66 c7 45 fc 00 80    movl   $0xb8000,-0x4(%ebp)
16   1d:   0b 00 
17   1f:   67 66 8b 45 f8          mov    -0x8(%ebp),%eax
18   24:   66 c9                   leavel 
19   26:   66 c3                   retl  

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。