您的位置:首页 > 运维架构 > Linux

汇编语言调用Linux系统调用read和write

2014-10-09 17:25 447 查看
<span style="font-family:Microsoft YaHei;">.section .data
UserMsg:
	.ascii "Please input the message:"
LenOfUserMsg:
	.equ lenMsg,  LenOfUserMsg - UserMsg
#.section .bss
#	.lcomm resb, 200
OutputMsg:
	.ascii "This is your input:"
LenOfOutputMsg:
	.equ lenOutput, LenOfOutputMsg - OutputMsg
.section .bss
   .lcomm resb, 200

.section .text
.globl _start
_start:
	#display UserMsg
	movl $4, %eax
	movl $1, %ecx
	movl $UserMsg, %ecx 
	movl $lenMsg, %edx
	int $0x80

	#Read what input
	movl $3, %eax
	movl $0, %ebx
	movl $resb, %ecx
	movl $200, %edx
    int $0x80 	
#-------------------------------------	
	#dispaly what you input
	movl $4, %eax
	movl $1, %ebx
	movl $OutputMsg, %ecx
	movl $lenOutput, %edx
	int $0x80

	movl $4, %eax
	movl $1, %ebx
	movl $resb, %ecx
	movl $200, %edx
	int $0x80

	movl $1, %eax
	movl $0, %ebx
	int $0x80

</span>

代码就是这样的。要做什么呢?

很简单:运行后,命令行提示你输入数字或者是字符,然后回车,把你输入的现实出来。

显然,这个用C语言实现起来简直太简单了。
但是,用汇编实现起来同样很简单。
==========知识准备============
在汇编中使用系统调用,只要是将系统调用号复制到eax寄存器。
查看/usr/include/i386-linux-gnu/asm中的unistd_32.h(64bit机器是/usr/include/x86_linux_gnu/asm/unistd.h/unistd_64.h)
可以看到每个系统调用都有一个系统调用号。
然后,系统调用必然要使用终端。这里使用的是软中断。int $0x80
比如,要使用exit这个系统调用
movl $1, %eax
int $0x80
某些系统调用有参数,怎么办呢?
在C样式函数中,输入参数存放在堆栈中;系统调用与之不同,需要输入参数被存放在寄存器中。每个输入值按照特定的顺序放到寄存器中。
简而言之。
按照顺序:
ebx (第1个输入参数)
ecx (第2个输入参数)
edx (第3个输入参数)
esi (第4个输入参数)
edi (第5个输入参数)
具体的输入顺序,就取决于系统调用中参数的顺序。比如,write(fd, *buf, count)
那么,ebx就是fd,ecx就是*buf,edx就是count
=========程序代码简要说明=============
ebx:文件描述符
ecx:指向要写入的字符串的指针
edx:要写入的字符串长度
write系统调用的值是4,将它存到eax寄存器中。然后将各个参数存放到相应的寄存器中。
需要指出,Linux中,0表示标准输入一般是键盘,1表示标准输出一般是终端屏幕。
首先在终端屏幕打印字符,提示你输入。输入后,使用read存放到一个内存区域。
在使用,write将相应区域的输入值打印出来。
要指出的是,$UserMsg将标签的内存地址存放到ecx中,而不是将实际存放在内存中的值放在ecx中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: