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