细说linux系统调用--使用c和汇编进行系统调用
来源:互联网 发布:电脑屏幕视频录制软件 编辑:程序博客网 时间:2024/06/05 05:01
linux系统如何打印”Hello World”
1. fprintf
使用fprintf输出到stdout
#include <stdio.h>int main(int argc, char *argv[]) { fprintf(stdout, "Hello World!\n"); return 0;}
2. write
使用write将字符串输出到STDOUT_FILENO
#include <unistd.h>int main(int argc, char *argv) { const char msg[] = "Hello World!\n"; write(STDOUT_FILENO, msg, sizeof(msg)-1); return 0;}
3. syscall
使用glibc提供的syscall进行系统调用SYS_write将字符串输出到STDOUT_FILENO
#define _GNU_SOURCE /* See feature_test_macros(7) */#include <unistd.h>#include <sys/syscall.h> /* For SYS_xxx definitions */int main(int argc, char *argv[]) { const char msg[] = "Hello World!\n"; syscall(SYS_write, STDOUT_FILENO, msg, sizeof(msg)-1); return 0;}
汇编格式对比
4. nasm格式汇编
使用nasm格式汇编进行int 80h系统调用,nasm_write.s内容如下
; nasm -f elf64 nasm_write.s && ld -s -o nasm_write nasm_write.osection .data hello db 'Hello world!', 10 ; ‘Hello world!’加一个换行符(10) len equ $-hello ; 字符串长度section .text global _start_start: mov eax, 4 ; 系统调用sys_write mov ebx, 1 ; 文件描述符,标准输出 mov ecx, hello ; 设置字符串偏移地址到ecx mov edx, len ; 设置字符串长度 int 80h ; 中断0x80, kernel系统调用syscall mov eax, 1 ; exit的系统调用(sys_exit) mov ebx, 0 ; 退出值我为0 int 80h
编译
nasm -f elf64 nasm_write.s && ld -s -o nasm_write nasm_write.o
5. int 80h
在Linux x86和Linux x86_64系统上可以使用int $0x80制造中断0x80进行系统调用。调用参数:
在arch/x86/include/asm/unistd_32.h中,exit和write的syscall number为
#define __NR_exit 1#define __NR_write 4
AT&T格式汇编通过int $0x80进行系统调用
# as -o gas_int.o gas_int.s && ld -s -o gas_int gas_int.o.data # section声明 msg: .ascii "Hello World!\n" len = . - msg # 字符串长度.text .global _start_start: movl $4, %eax movl $1, %ebx movl $msg, %ecx movl $len, %edx int $0x80 movl $1, %eax movl $0, %ebx int $0x80
编译:
as -o gas_int.o gas_int.s && ld -s -o gas_int gas_int.o
6. syscall
在x86_64上有专用指令进行系统调用
在arch/x86/include/asm/unistd_64.h中相应的syscall number
#define __NR_write 1#define __NR_exit 60
文件gas_syscall.s
# as -o gas_syscall.o gas_syscall.s && ld -s -o gas_syscall gas_syscall.o.data msg: .ascii "Hello World!\n" len = . - msg # 字符串长度.text .global _start_start: movq $1, %rax movq $1, %rdi movq $msg, %rsi movq $len, %rdx syscall movq $60, %rax movq $0, %rdi syscall
编译
as -o gas_syscall.o gas_syscall.s && ld -s -o gas_syscall gas_syscall.o
7. 内联方式调用syscall
gcc -nostdlib不连接glibc库
/** * 在c语言中内联汇编,使用AT&T风格 * 编译: gcc -nostdlib inline.c -o inline *//** * @brief 通过系统调用打印字符串 */void my_printf(char *s, int len) { long ret; __asm__ volatile( "int $0x80" /* 系统调用 */ : "=a" (ret) /* 返回值eax("a") */ : "0"(4), /* 系统调用号sys_write */ "b"(1), /* 参数ebx,文件句柄1=标准输出 */ "c"(s), /* 参数ecx, 字符串 */ "d"(len) /* 参数edx, 字符长度 */ );}/** * @brief 程序入口 */void _start() { /* main body of program: call main(), etc */ char *s = "Hello world!\n"; my_printf(s, 13); /* exit system call */ asm("movl $1,%eax;" "xorl %ebx,%ebx;" "int $0x80" );}
参考
+ Hello, world!
+ Linux System Call Table
+ Linux Assembly HOWTO 6.2. Hello, world!
+ X86 Assembly/Interfacing with Linux
+ X86 Assembly/NASM Syntax
+ What is better “int 0x80” or “syscall”?
+ Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)
0 0
- 细说linux系统调用--使用c和汇编进行系统调用
- linux使用系统调用和C库函数调用
- Linux内核分析:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
- 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用(Linux)
- 使用嵌入汇编调用open系统调用
- Linux系统调用(C内嵌汇编)
- 使用库函数API和C代码中嵌入汇编代码两种方式使用系统调用
- Linux内核分析:实验四--使用嵌入汇编系统调用
- 库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
- 库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
- 第四周 使用API和C编码中的嵌入式汇编 来应用同一个系统调用
- 汇编系统功能调用
- Linux AT&T汇编 系统调用
- 64位汇编之linux系统调用
- linux下C通过系统调用进行基本IO操作
- 细说linux IPC(三):mmap系统调用共享内存
- 细说linux IPC(三):mmap系统调用共享内存
- 细说linux IPC(三):mmap系统调用共享内存
- C预处理指令
- C++的const操作符
- Linux常用命令笔记
- iOS后台模式以及后台持续运行
- UploadiFive基本用法和配置
- 细说linux系统调用--使用c和汇编进行系统调用
- IOS app上交提交包时出现ERROR ITMS-90535 ITMS-90542 ITMS-90207
- hdu 4997 状压dp
- DataGridView表头颜色c#
- Android之 震动(Vibrator)如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- 超深度网络前沿:Going Deeper
- 轮播图--ConvenientBanner
- Linux Shell脚本编程--netstat命令
- 黑马程序员_Java基础_Day15我的学习笔记