背景知識基本交代清楚了,下面我們實際寫乙個小例子看一下。**的功能很簡單,顯示一行文字,然後退出。我們使用了syscall中的write和exit呼叫,查一下前面的呼叫號和引數,我們初步總結如下:
write(即sys_write)呼叫號為1,需傳遞3個引數
unsigned
int fd
const
char *buf
size_t count
exit(sys_exit)呼叫號為60,只需傳遞乙個錯誤碼
int error_code
如果該值為0表示程式執行成功。
因為以上兩個呼叫最多的也只有3個引數,所以我們依次只會用到3個暫存器rdi,rsi和rdx。
實際**如下:
;if use ld
global _start
;if use gcc
;global main
_start:
;main
mov rax,1 ;write no
mov rdx,1 ;fd
mov rsi,msg ;addr of msg string
mov rdx,msg_len ;lenght of msg string
syscall
mov rax,60 ;exit no
mov rdi,0 ;error_code
syscall
msg: db "hello world!",0xa
msg_len:equ $-msg
編譯連線命令如下:
nasm -f elf64 p.s
ld -o p p.o
如果是mac os x系統下命令如下:
nasm -f macho64 p.s
ld -o p p.o
因為本博的標題是linux下的彙編,所以mac os x下請參考本貓另一篇博文[mac os x64位以及32位彙編系統呼叫]。
如果你要生成32位的**,在編譯時把elf64改為elf32就可以了,不過我前面說過:32位和64位彙編結構變化較大,光改這個是沒辦法執行成功的。
不出所料**執行輸出一行:hello world!並且程式返回後用echo $?看,應該為0.
這個例子很簡單,下面看一下稍微複雜點的呼叫:mmap,該呼叫共有6個引數,我們再一次總結如下:
mmap(sys_mmap) 系統呼叫號為9,引數分別為:
unsigned
long addr
unsigned
long len
unsigned
long prot
unsigned
long flags
unsigned
long fd
unsigned
long offset
第乙個引數是需要對映到的位址,我們這裡傳0,表示不關心對映到哪;第二個引數是對映空間的大小;第三個引數表示對映區域的保護方式,有很多種,我們這裡只讓它可讀可寫即可,所以只用到2者的組合:
prot_write|prot_read
第四個引數是對映區域的一些特性,有很多組合。這裡只用map_shared|map_anonymous,後者表示建立匿名對映,會忽略引數fd,所以不設及檔案。
第五個引數就是fd,前面說了可以忽略,所以我們傳遞-1;最後乙個引數是對映的偏移量,我們也傳遞0.
該呼叫如果成功返回對映區域記憶體的起始位址,否則返回map_failed(-1),錯誤原因存於errno中,我們可以用strerror(errno)檢視具體含義。不過該函式是c庫中的,這裡我們捎帶的用一下。
unsigned long start
size_t len
linux下64位彙編的系統呼叫 1
現在基本上系統都是64位了,而64位系統下的彙編和32位有了較大的變化,無論是系統呼叫的介面還是c標準庫的介面都和32位彙編有所不同 下面簡單談一下在64位linux下如何利用彙編直接呼叫系統呼叫。需要準備的有 1.一台linux機器 我的系統是ubuntu 14.10 x64版 2.還要乙個彙編器...
linux下64位彙編的系統呼叫 1
現在基本上系統都是64位了,而64位系統下的彙編和32位有了較大的變化,無論是系統呼叫的介面還是c標準庫的介面都和32位彙編有所不同 下面簡單談一下在64位linux下如何利用彙編直接呼叫系統呼叫。需要準備的有 1.一台linux機器 我的系統是ubuntu 14.10 x64版 2.還要乙個彙編器...
linux下64位彙編的系統呼叫 5
include include include include include include include include include include int main void return 0 前面介紹過幾個linux下的整合除錯環境,這裡我們還是用codelite而不用codebloc...