C指針原理教程之AT&T匯編
匯編在LINUX系統(tǒng)下的意義遠遠大于WINDOWS系統(tǒng),LINUX內核部分代碼就是匯編編寫的。然后,絕大多數(shù) Linux 程序員以前只接觸過DOS/Windows 下的匯編語言,這些匯編代碼都是 Intel 風格的。但在 Unix 和 Linux 系統(tǒng)中,更多采用的還是 AT&T 格式,兩者在語法格式上有著很大的不同,因此應對AT&T匯編應有一個基本的了解和熟悉。
我們在LINUX下用C編寫一段最簡單的helloworld程序,命令為hello.c
#include <stdio.h> int main() { printf("hello,world\n"); exit(0); }
然后,使用GCC編譯,同時使用-s參數(shù)生成中間匯編代碼,看看AT&T匯編的真實面目
.section .data#初始化的變量
output:
.ascii "hello,world\n"
#要打印的字符串,.data為初始化值的變量。output是標簽,指示字符串開始的位置,ascii為數(shù)據(jù)類型
.section .bss#未初始化的變量,由0填充的緩沖區(qū)
.lcomm num,20
#lcomm為本地內存區(qū)域,即本地匯編外的不能進行訪問。.comm是通用內存區(qū)域。
.section .text#匯編語言指令碼
.globl _start#啟動入口
_start:
movl $4,%eax#調用的系統(tǒng)功能,4為write
movl $output,%ecx#要打印的字符串
movl $1,%ebx#文件描述符,屏幕為1
movl $12,%edx#字符串長度
int $0x80#顯示字符串hello,world
movl $0,%eax
movl $num,%edi
movl $65,1(%edi)#A 的ascii
movl $66,2(%edi)#B 的ascii
movl $67,3(%edi)#C 的ascii
movl $68,4(%edi)#D 的ascii
movl $10,5(%edi)#\n的ascii
movl $4,%eax#調用的系統(tǒng)功能,4為write
movl $num,%ecx#要打印的字符串
movl $1,%ebx#文件描述符,屏幕為1
movl $6,%edx#字符串長度
int $0x80#顯示字符串ABCD
movl $1,%eax#1為退出
movl $0,%ebx#返回給shell的退出代碼值
int $0x80#內核軟中斷,退出系統(tǒng)
gcc -S hello.c .file "hello.c" .section .rodata .LC0: .string "hello,world" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $16, %esp movl $.LC0, (%esp) call puts movl $0, (%esp) call exit .size main, .-main .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" .section .note.GNU-stack,"",@progbits
匯編器(assembler)的作用是將用匯編語言編寫的源程序轉換成二進制形式的目標代碼。Linux 平臺的標準匯編器是 GAS,它是 GCC 所依賴的后臺匯編工具,通常包含在 binutils 軟件包中。
AT&T匯編主要有以下特點:
1、在 AT&T 匯編格式中,寄存器名要加上 '%' 作為前綴。
如:
把eax寄存器的內容復制到ebx中
movl %eax,%ebx
2、用 '$' 前綴表示一個立即操作數(shù)。
如:將1復制到eax中
movl $1, %eax
3、目標操作數(shù)在源操作數(shù)的右邊
movl %eax,%ebx
eax是源操作數(shù),ebx是目標操作數(shù)
4、在 AT&T 匯編格式中,操作數(shù)的字長由操作符的最后一個字母決定,后綴'b'、'w'、'l'分別表示操作數(shù)為字節(jié)(byte,8 比特)、字(word,16 比特)和長字(long,32比特)
比如:
movl對32位進行操作,將eax寄存器32位的內容復制到ebx中
movl %eax, %ebx
movw對16位進行操作,將ax寄存器的內容復制到bx中
movw %ax, %bx
movb對8位進行操作,將al寄存器的內容復制到bl中
movb %al, %bl
我們再以入棧為例:
pushl %ecx # 32位ecx的內容入棧
pushw %cx # 16位ecx的內容入棧
pushl $180 # 80做為一個32位整數(shù)入棧
pushl data # data變量內容入棧,長度為32位
pushl $data # 這一個操作很特別,在變量前面加上$表示取變量的地址,這是將data變量的地址入棧
5、在 AT&T 匯編格式中,絕對轉移和調用指(jump/call)的操作數(shù)前要加上'*'作為前綴
6、遠程轉移指令和遠程子調用指令的操作碼,在 AT&T 匯編格式中為 ljump和lcall
我們從生成的中間代碼可以看出這幾個特點。
我們再來看一段用AT&T匯編編寫的helloworld程序。
.section .data#初始化的變量 output: .ascii "hello,world\n" #要打印的字符串,.data為初始化值的變量。output是標簽,指示字符串開始的位置,ascii為數(shù)據(jù)類型 .section .bss#未初始化的變量,由0填充的緩沖區(qū) .lcomm num,20 #lcomm為本地內存區(qū)域,即本地匯編外的不能進行訪問。.comm是通用內存區(qū)域。 .section .text#匯編語言指令碼 .globl _start#啟動入口 _start: movl $4,%eax#調用的系統(tǒng)功能,4為write movl $output,%ecx#要打印的字符串 movl $1,%ebx#文件描述符,屏幕為1 movl $12,%edx#字符串長度 int $0x80#顯示字符串hello,world movl $0,%eax movl $num,%edi movl $65,1(%edi)#A 的ascii movl $66,2(%edi)#B 的ascii movl $67,3(%edi)#C 的ascii movl $68,4(%edi)#D 的ascii movl $10,5(%edi)#\n的ascii movl $4,%eax#調用的系統(tǒng)功能,4為write movl $num,%ecx#要打印的字符串 movl $1,%ebx#文件描述符,屏幕為1 movl $6,%edx#字符串長度 int $0x80#顯示字符串ABCD movl $1,%eax#1為退出 movl $0,%ebx#返回給shell的退出代碼值 int $0x80#內核軟中斷,退出系統(tǒng)
我們對上面這段匯編代碼的結構和內容進行解說:
1、.section .data段存放著初始化的變量, .section .bss段存放著未初始化的變量
2、變量的定義采用以下格式:
變量名:
變量類型 變量值
上面代碼中的output變量就是這么定義的
output:
.ascii "hello,world\n"
下面例子定義了多個變量
.section .data
msg:
.ascii “This is a text”
x:
.double 109.45, 2.33, 19.16
y:
.int 89
z:
.int 21, 85, 27
.equ a 8
其中,msg為字符符,x為雙精度符點數(shù),y和z為整數(shù),a是一個特別的定義,它的是一個靜態(tài)變量的定義,使用.equ 變量名 變量值來實現(xiàn)
3、.section .bss段中變量訪問區(qū)域的定義規(guī)則為:
lcomm為本地內存區(qū)域,即本地匯編外的不能進行訪問,而.comm是通用內存區(qū)域
比如上面的定義
.lcomm num,20
num為本地內存區(qū)域。
4、section .text段為匯編語言指令碼,使用.globl _start指示_start標記后的代碼為程序啟動入口。
5、#表示注釋,上面代碼的其它部分均有注釋,有匯編基礎的程序員應很容易理解
變量的類型有以下幾種:
.ascii 文本字符串
.asciz 以NULL結束的文本字符串
.byte 字節(jié)值
.double 雙精度符點數(shù)
.float 單精度符點數(shù)
.int 32位整數(shù)
.long 32位整數(shù)
.octa 16位整數(shù)
.quad 8位整數(shù)
.short 16位整數(shù)
.single 單精度符點數(shù)
此外,AT&T匯編經(jīng)常會涉及字節(jié)順序反轉,比較加載,交換,壓入彈出所有寄存器等操作,以下例子涉及了這些操作,
每行代碼都有詳細的注釋。
.bss段定義的數(shù)據(jù)元素為未初始化的變量,在運行時對其進行初始化。
可分為數(shù)據(jù)通用內存區(qū)域和本地通用內存區(qū)域
本地通用內存區(qū)域不能從本地匯編代碼之外進行訪問。
.text段存放代碼
您可能感興趣的文章
- 01-10深入理解數(shù)組指針與指針數(shù)組的區(qū)別
- 01-10基于C++輸出指針自增(++)運算的示例分析
- 01-10解析sizeof, strlen, 指針以及數(shù)組作為函數(shù)參數(shù)的應用
- 01-10探討C++中數(shù)組名與指針的用法比較分析
- 01-10深入理解雙指針的兩種用法
- 01-10libxml教程(圖文詳解)
- 01-10C語言數(shù)組指針的小例子
- 01-10基于SVN源碼服務器搭建(詳細教程分析)
- 01-10解析如何用指針實現(xiàn)整型數(shù)據(jù)的加法
- 01-10深入const int *p與int * const p的區(qū)別詳解(常量指針與指向常量的指


閱讀排行
本欄相關
- 04-02c語言函數(shù)調用后清空內存 c語言調用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調用函數(shù)求fibo C語言調用函數(shù)求
隨機閱讀
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實例總結
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載