1. 程式人生 > >C指標原理(44)-彙編基礎

C指標原理(44)-彙編基礎

AT&T彙編語語言中的資料段與資料型別

.data段定義的資料元素保留在記憶體中能夠被指令讀取和寫入;
.rodata段定義的資料元素只讀;

.data與.rodata段的資料型別:
1) .ascii 代表文字字串型別
2) .asciz 代表以空字元結尾的文字字串,在C中以空代表串的結尾
3) .byte 代表一個位元組值
4) .double 雙精度浮點數
5) .float 單精度浮點數
6) .int 代表32位整數
7) .long 代表32位整數IA-32
8) .octa 代表16位元組整數
9) .quad 代表8位元組整數
10) .short 代表16位整數
11) .single 單精度浮點數 32位

   同時可以使用.fill自動建立10000個數據元素,預設為每個欄位建立一個字長,並使用零填充它。

在.data與.rodata段中定義的資料將從記憶體地址由低到高排列。編寫一段簡單的彙編程式碼

[email protected]:~ % cat test.s

.section .data

mybuffer:

   .fill 100

.section .rodata

mytext:

   .ascii "abcde"

val1:

    .byte 'a'

val2:

    .byte 'b'

    .byte 'c'

.section .text

.globl _start 

_start:

   movl mytext,%eax

   movl val1,%ebx 

 

[email protected]
:~ %  從對上面程式的反彙編可看出,記憶體地址從低到高放置了mytext(0804807f )、val1(08048084 )、val2(08048085)、mybuffer。 [email protected]:~ % objdump -D test   test:     file format elf32-i386-freebsd   Disassembly of section .text:   08048074 <_start>:  8048074:a1 7f 80 04 08       mov    0x804807f,%eax  8048079:8b 1d 84 80 04 08    mov    0x8048084,%ebx Disassembly of section .rodata:   0804807f <mytext>:  804807f:61                   popa     8048080:62 63 64             bound  %esp,0x64(%ebx)  8048083:65                   gs   08048084 <val1>:  8048084:61                   popa      08048085 <val2>:  8048085:62                   .byte 0x62  8048086:63                   .byte 0x63 Disassembly of section .data:   08049088 <mybuffer>: ...

.bss段定義的資料元素為未初始化的變數,在執行時對其進行初始化。

可分為資料通用記憶體區域和本地通用記憶體區域 

本地通用記憶體區域不能從本地彙編程式碼之外進行訪問。

.text段存放程式碼

在程式碼段中用“;”表示註釋

彙編程式碼如下:

[email protected]:~ % cat test1.s

.section .rodata

  output:

    .asciz "the number is %d\n"

.section .data

  value:

    .int 0,0,0,0,0,0,0,0,0,0

.section .text

.globl main

main:

   movl $0,%ecx

   loopset:

;基地址(存在暫存器中的偏移地址,存在暫存器中的資料元素索引,存在暫存器中的資料元素大小)

       movl %ecx,value(,%ecx,4)

       inc %ecx

       cmpl $10,%ecx

       jne loopset

   movl $0,%ecx

   loopprint:

       movl value(,%ecx,4),%eax

       pushl %ecx

       pushl %eax

       pushl $output

       call printf

       add $8,%esp

       popl %ecx

       inc %ecx

       cmpl $10,%ecx

       jne loopprint

編譯並執行

[email protected]:~ % gcc -o test1 test1.s

[email protected]:~ % ./test1

the number is 0

the number is 1

the number is 2

the number is 3

the number is 4

the number is 5

the number is 6

the number is 7

the number is 8

the number is 9

    上述程式碼 ,先在.data可讀寫區域放置10個初始值為0的int值,然後在程式中通過loopset標記和jne語句完成一個迴圈,將它們的值依次賦值為0到9,最後通過loopprint標記和jne語句完成迴圈,呼叫c庫的print語句將這些數輸出。

inc表示自增1,而dec表示自減1 。

棧是由高地址向低地址增長的,當棧增加內容,將導致棧頂指標減少,否則,導致棧頂指標增加

在print語句執行返回後,清空執行print在堆疊中的生成垃圾,add $8,%esp,拋棄為呼叫printf函式準備的引數 ,棧頂有ESP暫存器來定位,壓棧的操作使得棧頂的地址減小,彈出的操作使得棧頂的地址增大,因此這裡相當於直接彈出壓入的2個%eax(指向需要輸出的資料)和$output引數,前面有呼叫:

 pushl %eax

 pushl $output

在上面這2個壓棧之前,還呼叫了

 pushl %ecx

其作用在於,儲存%ecx的值,因為c庫的printf函式會破壞%ecx暫存器的值,一般使用堆疊來儲存可能被破壞的值,執行完printf完畢後,再還原:popl %ecx