嵌入式汇编实现系统调用-sysinfo

11 篇文章 1 订阅

平台为兆芯x86-64平台,原创文章,转载请标注出处~

在前一篇文章中,使用嵌入式汇编实现了time系统调用,这个系统调用没有入参,今天使用嵌入式汇编实现sysinfo,此系统调用有一个指针入参。

首先使用libc实现sysinfo的调用:

#include <sys/sysinfo.h>
#include <stdio.h>
#include <string.h>
int main()
{
   int errno = -1;
   long uptime = 0;
   struct sysinfo s_info;
   memset(&s_info,0,sizeof(struct sysinfo));
   errno = sysinfo(&s_info);
   uptime = s_info.uptime;
   printf("this is libc call sysinfo errno = %d, uptime = %ld\n",errno, uptime);
   return 0;
}

编译:

root@henry-002:/usr/test_code# gcc sysinfo_libc.c -o sysinfo_libc --static

执行结果:

root@henry-002:/usr/test_code# ./sysinfo_libc 
this is libc call sysinfo errno = 0, uptime = 6073

执行结果正常,说明libc是可以正常执行的,进行反汇编:

root@henry-002:/usr/test_code# objdump -dlt sysinfo_libc > sysinfo_libc.dis

找到主要执行的代码:

000000000040105e <main>:
main():
  40105e:	55                   	push   %rbp
  40105f:	48 89 e5             	mov    %rsp,%rbp
  401062:	48 83 c4 80          	add    $0xffffffffffffff80,%rsp
  401066:	c7 45 84 ff ff ff ff 	movl   $0xffffffff,-0x7c(%rbp)
  40106d:	48 c7 45 88 00 00 00 	movq   $0x0,-0x78(%rbp)
  401074:	00 
  401075:	48 8d 45 90          	lea    -0x70(%rbp),%rax
  401079:	ba 70 00 00 00       	mov    $0x70,%edx
  40107e:	be 00 00 00 00       	mov    $0x0,%esi
  401083:	48 89 c7             	mov    %rax,%rdi
  401086:	e8 b5 b0 01 00       	callq  41c140 <memset>
  40108b:	48 8d 45 90          	lea    -0x70(%rbp),%rax
  40108f:	48 89 c7             	mov    %rax,%rdi
  401092:	e8 89 5d 03 00       	callq  436e20 <sysinfo>
  401097:	89 45 84             	mov    %eax,-0x7c(%rbp)
  40109a:	48 8b 45 90          	mov    -0x70(%rbp),%rax
  40109e:	48 89 45 88          	mov    %rax,-0x78(%rbp)
  4010a2:	48 8b 55 88          	mov    -0x78(%rbp),%rdx
  4010a6:	8b 45 84             	mov    -0x7c(%rbp),%eax
  4010a9:	89 c6                	mov    %eax,%esi
  4010ab:	bf 28 38 49 00       	mov    $0x493828,%edi
  4010b0:	b8 00 00 00 00       	mov    $0x0,%eax
  4010b5:	e8 16 6e 00 00       	callq  407ed0 <_IO_printf>
  4010ba:	b8 00 00 00 00       	mov    $0x0,%eax
  4010bf:	c9                   	leaveq 
  4010c0:	c3                   	retq   
  4010c1:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  4010c8:	00 00 00 
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

.......................
0000000000436e20 <sysinfo>:
sysinfo():
  436e20:	b8 63 00 00 00       	mov    $0x63,%eax
  436e25:	0f 05                	syscall 
  436e27:	48 3d 01 f0 ff ff    	cmp    $0xfffffffffffff001,%rax
  436e2d:	0f 83 bd 17 00 00    	jae    4385f0 <__syscall_error>
  436e33:	c3                   	retq   
  436e34:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  436e3b:	00 00 00 
  436e3e:	66 90                	xchg   %ax,%ax

 

可以看到sysinfo的系统调用号是0x63,使用嵌入式 汇编实现代码如下:

#include <sys/sysinfo.h>
#include <stdio.h>
#include <string.h>
int main()
{
   int errno = -1;
   long uptime = 0;
   struct sysinfo s_info;
   memset(&s_info,0,sizeof(struct sysinfo));
   asm volatile(
       "lea %1,%%rdi\n\t"  //将输入参数s_info的地址赋值给rdi
       "mov $0x63,%%eax\n\t" //系统调用号为0x63
       "syscall\n\t"         //执行系统调用,此处不能用int 0x80代替
       "mov %%eax,%0\n\t"    //返回值放在eax中,将返回值赋值给errno
       :"=m"(errno)
       :"m"(s_info)
   );
   uptime = s_info.uptime;
   printf("this is syscall call sysinfo errno = %d, uptime = %ld\n",errno, uptime);
   return 0;
}

编译 :

root@henry-002:/usr/test_code# gcc sysinfo_syscall.c -o sysinfo_syscall --static 

执行结果达到预期:

root@henry-002:/usr/test_code# ./sysinfo_syscall
this is syscall call sysinfo errno = 0, uptime = 6277

 

反汇编:

root@henry-002:/usr/test_code# objdump -dlt sysinfo_syscall > sysinfo_syscall.dis

找到主要执行的代码段:

000000000040105e <main>:
main():
  40105e:	55                   	push   %rbp
  40105f:	48 89 e5             	mov    %rsp,%rbp
  401062:	48 83 c4 80          	add    $0xffffffffffffff80,%rsp
  401066:	c7 45 84 ff ff ff ff 	movl   $0xffffffff,-0x7c(%rbp)
  40106d:	48 c7 45 88 00 00 00 	movq   $0x0,-0x78(%rbp)
  401074:	00 
  401075:	48 8d 45 90          	lea    -0x70(%rbp),%rax
  401079:	ba 70 00 00 00       	mov    $0x70,%edx
  40107e:	be 00 00 00 00       	mov    $0x0,%esi
  401083:	48 89 c7             	mov    %rax,%rdi
  401086:	e8 a5 b0 01 00       	callq  41c130 <memset>
  40108b:	48 8d 7d 90          	lea    -0x70(%rbp),%rdi
  40108f:	b8 63 00 00 00       	mov    $0x63,%eax
  401094:	0f 05                	syscall 
  401096:	89 45 84             	mov    %eax,-0x7c(%rbp)
  401099:	48 8b 45 90          	mov    -0x70(%rbp),%rax
  40109d:	48 89 45 88          	mov    %rax,-0x78(%rbp)
  4010a1:	8b 45 84             	mov    -0x7c(%rbp),%eax
  4010a4:	48 8b 55 88          	mov    -0x78(%rbp),%rdx
  4010a8:	89 c6                	mov    %eax,%esi
  4010aa:	bf e8 37 49 00       	mov    $0x4937e8,%edi
  4010af:	b8 00 00 00 00       	mov    $0x0,%eax
  4010b4:	e8 07 6e 00 00       	callq  407ec0 <_IO_printf>
  4010b9:	b8 00 00 00 00       	mov    $0x0,%eax
  4010be:	c9                   	leaveq 
  4010bf:	c3                   	retq   

 

需要注意的地方:

1.给sysinfo传递参数的时候,使用的是rdi寄存器,而不是用rax寄存器。

2.编译器给edi赋值的时候,会先用lea指令将变量地址赋值给rax,然后再通过mov指令将rax的值赋值给rdi,我这里直接使用lea指令将变量地址赋值给rdi,比编译器节省一条指令。

3.lea指令不能用mov指令代替,因为lea指令为load effective address 的缩写,是取源操作数的偏移地址,并将其传送到目的操作数单元。类似于C语言的取地址符&。而mov是将变量值赋值给操作数。

4.libc还有其他的指令,如异常处理,这里没有考虑,nopw和xchg不确定具体的作用,后续可能再更新。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值