標籤:linux nasm 系統調用 syscall mmap
背景知識基本交代清楚了,下面我們實際寫一個小例子看一下。代碼的功能很簡單,顯示一行文本,然後退出。我們使用了syscall中的write和exit調用,查一下前面的調用號和參數,我們初步總結如下:
write(即sys_write)調用號為1,需傳遞3個參數
unsigned int fdconst char *bufsize_t count
exit(sys_exit)調用號為60,只需傳遞一個錯誤碼
int error_code
如果該值為0表示程式執行成功。
因為以上兩個調用最多的也只有3個參數,所以我們依次只會用到3個寄存器rdi,rsi和rdx。
實際代碼如下:
section .text;if use ldglobal _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.sld -o p p.o
如果是mac os x系統下命令如下:
nasm -f macho64 p.sld -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 addrunsigned long lenunsigned long protunsigned long flagsunsigned long fdunsigned long offset
第一個參數是需要映射到的地址,我們這裡傳0,表示不關心映射到哪;第二個參數是映射空間的大小;第三個參數表示映射地區的保護方式,有很多種,我們這裡只讓它可讀可寫即可,所以只用到2者的組合:
PROT_WRITE|PROT_READ
第四個參數是映射地區的一些特性,有很多組合。這裡只用MAP_SHARED|MAP_ANONYMOUS,後者表示建立匿名映射,會忽略參數fd,所以不設及檔案。
第五個參數就是fd,前面說了可以忽略,所以我們傳遞-1;最後一個參數是映射的位移量,我們也傳遞0.
該調用如果成功返回映射地區記憶體的起始地址,否則返回MAP_FAILED(-1),錯誤原因存於errno中,我們可以用strerror(errno)查看具體含義。不過該函數是C庫中的,這裡我們捎帶的用一下。
提到mmap我們不得不提到munmap,用猜大家也知道該調用的含義吧:
munmap(sys_munmap) 調用號為11,需傳遞2個參數:
unsigned long startsize_t len
linux下64位彙編的系統調用(3)