所以使用組合語言可以使code size做的更小 (當然一般來說,一個有經驗的programmer使用組合語言編寫程式會比使用C語言編寫程式所產生的code size還小的原因,這裡所描述的理由只是眾多原因之一)
1 /*
2 * hello2.c
3 */
4 unsigned char *str= "Hello World\n";
5
6 int _start(void)
7 {
8 /* write(STDOUT_FILENO, str, sizeof(str)); */
9 asm("movl $14, %%edx;\
10 movl %0, %%ecx;\
11 movl $1, %%ebx;\
12 movl $4, %%eax;\
13 int $0x80;"
14 : :"m"(str));
15
16 /* exit(0); */
17 asm("xorl %ebx, %ebx;\
18 movl $1, %eax;\
19 int $0x80;");
20 }
第4行字串的安排及第6行_start() function,轉或成組合語言結果...
1 /* as helloworld.s -o helloworld.o; ld helloworld.o -o helloworld */
2 /* gcc helloworld.s -nostartfiles -nostdlib -static -o hellworld */
3
4 .text
5 .globl _start
6
7 _start:
8 mov $13, %edx
9 mov $msg, %ecx
10 mov $1, %ebx
11 mov $4, %eax
12 int $0x80
13
14 movl $0, %ebx /* exit code */
15 movl $1, %eax /* exit function */
16 int $0x80
17
18 .data
19 msg:
20 .string "Hello world\n"
其編譯方式有兩種(於1、2行註解中),此程式中的進入點直接執行第8行程式,且只有安排一個data section(.data)。
其編譯、執行結果...
$ gcc helloworld.s -nostartfiles -nostdlib -static -o hellworld
$ strip hellworld
$ objdump -h hellworld
hellworld: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000022 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 0000000d 08049098 08049098 00000098 2**2
CONTENTS, ALLOC, LOAD, DATA
$
$ ls -l hellworld
-rwxr-xr-x 1 lungswu lungswu 348 2010-03-01 11:40 hellworld
$
$ ./hellworld
Hello world
$
$
所以產生348 bytes 大小的執行檔,組合語言中因為沒有定義.rodata section,所以編譯連結出來的執行檔也無.rodata section。
本文開頭第2點有說到....組合語言可以"可以精確的處理section的內容"...
先來將hellworld執行檔反組譯...
$ objdump -S helloworld
helloworld: file format elf32-i386
Disassembly of section .text:
08048074 <.text>:
8048074: ba 0d 00 00 00 mov $0xd,%edx
8048079: b9 98 90 04 08 mov $0x8049098,%ecx
804807e: bb 01 00 00 00 mov $0x1,%ebx
8048083: b8 04 00 00 00 mov $0x4,%eax
8048088: cd 80 int $0x80
804808a: bb 00 00 00 00 mov $0x0,%ebx
804808f: b8 01 00 00 00 mov $0x1,%eax
8048094: cd 80 int $0x80
在上述反組譯的內容中,其執行碼剛好跟helloworld.s的組合語言做一對一的對應。
1. 其中程式進入點為0x8048074。
2. 於0x8048079位址,是將0x8049098的十六進制值填入站存器ECX中。值0x8049098剛好是symbol msg的位址。
3. 程式執行到0x8048094便結束。
所以...於位址 0x8048094 + 2 = 0x8048096 可以自行加入所需要額外的資料也不會對整個執行造成不良的影響 ....
1 /* as helloworld2.s -o helloworld2.o; ld helloworld.o -o helloworld2 */
2 /* gcc helloworld2.s -nostartfiles -nostdlib -static -o helloworld2 */
3
4 .text
5 .globl _start
6
7 _start:
8 mov $13, %edx
9 mov $msg, %ecx
10 mov $1, %ebx
11 mov $4, %eax
12 int $0x80
13
14 movl $0, %ebx /* exit code */
15 movl $1, %eax /* exit function */
16 int $0x80
17
18 msg:
19 .string "Hello world\n"
所以...這樣可以將"Hello World\n"的字串內容接到int 0x80之後,也將.data的section移除...
這樣的結果...
$ gcc helloworld2.s -nostartfiles -nostdlib -static -o hellworld2
$ strip helloworld2
$ objdump -h helloworld2
helloworld2: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000002f 08048054 08048054 00000054 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
$ ./helloworld2
Hello world
$
$ ls -l helloworld2
-rwxr-xr-x 1 lungswu lungswu 268 2010-03-01 13:33 hellworld2
$
.data section已經移除,整個執行檔剩下.text section,大小變為 268 bytes。
附註...組合語言中加入"機械語言"...
因為組合語言中可以自行將入不同二進制的資料,如以下反組譯的結果...
$ objdump -S helloworld2
helloworld2: file format elf32-i386
Disassembly of section .text:
08048054 <.text>:
8048054: ba 0d 00 00 00 mov $0xd,%edx
8048059: b9 76 80 04 08 mov $0x8048076,%ecx
804805e: bb 01 00 00 00 mov $0x1,%ebx
8048063: b8 04 00 00 00 mov $0x4,%eax
8048068: cd 80 int $0x80
804806a: bb 00 00 00 00 mov $0x0,%ebx
804806f: b8 01 00 00 00 mov $0x1,%eax
8048074: cd 80 int $0x80
8048076: 48 dec %eax
8048077: 65 gs
8048078: 6c insb (%dx),%es:(%edi)
8048079: 6c insb (%dx),%es:(%edi)
804807a: 6f outsl %ds:(%esi),(%dx)
804807b: 20 77 6f and %dh,0x6f(%edi)
804807e: 72 6c jb 0x80480ec
8048080: 64 0a 00 or %fs:(%eax),%al
$
其實上面反組譯後位址 0x8048076 到 0x8048080 + 3 的地方是symbol msg的資料內容,因為放置於.text中,objdump或者program loader會將這新資料當作程式碼放置。
所以,helloworld中要插入機械語言(比方說int 0x80的機械碼為0xCD 0x80,則可以這樣編寫(注意下面程式16行)...
1 /* as helloworld3.s -o helloworld3.o; ld helloworld3.o -o helloworld3 */
2 /* gcc helloworld3.s -nostartfiles -nostdlib -static -o helloworld3 */
3
4 .text
5 .globl _start
6
7 _start:
8 mov $13, %edx
9 mov $msg, %ecx
10 mov $1, %ebx
11 mov $4, %eax
12 int $0x80
13
14 movl $0, %ebx /* exit code */
15 movl $1, %eax /* exit function */
16 .byte 0xCD, 0x80 /* Machine code int 0x80 */
17
18 .data
19 msg:
20 .string "Hello world\n"
結果如下...
$ gcc helloworld3.s -nostartfiles -nostdlib -static -o helloworld3
$ objdump -S helloworld3
helloworld3: file format elf32-i386
Disassembly of section .text:
08048074 <_start>:
8048074: ba 0d 00 00 00 mov $0xd,%edx
8048079: b9 98 90 04 08 mov $0x8049098,%ecx
804807e: bb 01 00 00 00 mov $0x1,%ebx
8048083: b8 04 00 00 00 mov $0x4,%eax
8048088: cd 80 int $0x80
804808a: bb 00 00 00 00 mov $0x0,%ebx
804808f: b8 01 00 00 00 mov $0x1,%eax
8048094: cd 80 int $0x80
$ ./helloworld3
$
Hello world
$
$
No comments:
Post a Comment