经过上一篇的铺垫貌似可以很轻松的用汇编写出mmap的代码来,可仔细一看,还是有不少问题需要解决:

1.系统调用mmap如果出错并不直接返回MAP_FAILED(-1),而是一个“类似”值;C库中的mmap函数对其做了包装,使其最终返回-1;如果我们直接调用mmap syscall,则这些事必须自己来做。

2.C库函数如果出错会设置errno的值,而在汇编中没法直接用:

  1. extern errno

的方法使用外部的值,连接时会报错:

  1. /usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in p.o
  2. /lib/x86_64-linux-gnu/libc.so.6: error adding symbols: 错误的值

C语言的解决办法很简单,直接把:

  1. extern int errno;
  2. //替换为
  3. #include <errno.h>

但nasm下这招没法使;我们先看一下errno对应的C代码:

  1. #define errno() *errnofunc()
  2. int *errnofunc()
  3. {
  4. int *errnoptr = get_thread_data(ERRNOPTR);
  5. return errnoptr;
  6. }

可以看到其调用另一个函数,在nasm中我们可以大致这么写:

  1. extern __errno_location
  2. call __errno_location
  3. mov rax,qword [rax]

不过貌似也不太对 :( ,不过我们可以在mmap系统调用后自己操作errno的值,以下代码将填充变量errno的值并且如果出错将修正mmap的返回值为-1:

  1. section .data
  2. errno dq 0
  3. ;mmap syscall 之后
  4. cmp rax,0xfffffffffffff001
  5. jb next
  6. push rax
  7. neg rax
  8. mov [errno],rax
  9. pop rax
  10. or rax,-1
  11. next:
  12. ;处理mmap返回后的逻辑

3 可以看到C代码中调用mmap参数压栈,是将第4个参数放到rcx里,但是在C库mmap函数里又将rcx赋值给r10;这正应了前面调用规则里的内核系统调用第4个参数是放在r10里,而不是rcx里的哦;所以汇编中我们直接放在r10里即可,不用先转到rcx里了。

最后的代码如下:

  1. section .data
  2. errno dq 0
  3. addr dq 0
  4. MAP_FAILED equ -1
  5. ;MAP_LEN equ 40960
  6. MAP_LEN equ 0xffffffffffffffff
  7. PROT_READ_WRITE equ 3
  8. MAP_SHARED_ANON equ 33
  9. ;MAP_SHARED_ANON equ 0x20
  10. section .text
  11. ;extern errno
  12. extern __errno_location
  13. extern strerror
  14. extern printf
  15. ;if use ld
  16. ;global _start
  17. ;if use gcc
  18. global main
  19. ;_start:
  20. main:
  21. and rsp,~0xffff ;堆栈对齐 equ 0xffffffffffff0000
  22. mov rax,9 ;mmap NO
  23. mov rdi,0 ;map address
  24. mov rsi,MAP_LEN ;map size
  25. mov rdx,PROT_READ_WRITE
  26. mov r10,MAP_SHARED_ANON
  27. mov r8,-1 ;忽略fd
  28. mov r9,0 ;offset
  29. syscall
  30. cmp rax,0xfffffffffffff001
  31. jb next
  32. push rax
  33. neg rax
  34. mov [errno],rax
  35. pop rax
  36. or rax,-1
  37. next:
  38. cmp rax,MAP_FAILED
  39. ;cmp rax,0
  40. ;js map_failed
  41. je map_failed
  42. mov [addr],rax
  43. mov rsi,[addr]
  44. mov rdi,msg_success
  45. call printf
  46. mov rax,11
  47. mov rdi,addr
  48. mov rsi,MAP_LEN
  49. syscall
  50. jmp exit
  51. map_failed:
  52. ;mov rdi,0xb
  53. ;call __errno_location
  54. ;mov rax,qword [rax]
  55. ;mov rsi,[errno]
  56. mov rdi,[errno]
  57. call strerror
  58. mov rsi,rax
  59. mov rdi,msg_failed
  60. call printf
  61. exit:
  62. mov rax,60 ;exit NO
  63. mov rdi,0 ;error_code
  64. syscall
  65. msg_success: db "map successed , addr at %p",0ax,0
  66. msg_failed: db "map failed ,due to %s",0ax,0

编译连接:

  1. nasm -f elf64 p.s
  2. gcc -o p p.o

如果mmap成功结果如下:

  1. wisy@wisy-pad:~/src/asm_src/nasm_src/linux$ ./p
  2. map successed , addr at 0x7fbe5c94e000

可以用strace查看其返回的syscall:

  1. mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fc6b2397000

如果mmap出错则会显示出错原因:

  1. //将MAP_LEN 设为超大的值
  2. ./p
  3. map failed ,due to Cannot allocate memory
  4. //传递给flags错误的参数
  5. ./p
  6. map failed ,due to Invalid argument

linux下64位汇编的系统调用(4)的更多相关文章

  1. linux下64位汇编的系统调用(2)

    知道了syscall调用号之后还不算完,还要搞清楚2件事: 1 每种调用号需要传递哪些参数: 2 调用如何传递参数以及结果如何返回: 第一个问题的答案是: 在linux系统中某个程序执行时进行的系统调 ...

  2. linux下64位汇编的系统调用(3)

    背景知识基本交代清楚了,下面我们实际写一个小例子看一下.代码的功能很简单,显示一行文本,然后退出.我们使用了syscall中的write和exit调用,查一下前面的调用号和参数,我们初步总结如下: w ...

  3. linux下64位汇编的系统调用(1)

    现在基本上系统都是64位了,而64位系统下的汇编和32位有了较大的变化,无论是系统调用的接口还是C标准库的接口都和32位汇编有所不同:下面简单谈一下在64位linux下如何利用汇编直接调用系统调用. ...

  4. linux下64位汇编的系统调用(5)

    看到这里大家都基本知道了如何进行linux下的汇编系统调用:不过有些童鞋可能会问:那些C库中函数里为我们解决的额外汇编代码你是怎么知道的? 好吧,我承认:我是通过逆向知道的,这貌似有点犯规的嫌疑- 比 ...

  5. linux下64位汇编的系统调用系列

    http://blog.csdn.net/mydo/article/category/3084893

  6. Mac OS X下64位汇编与Linux下64位汇编的一些不同

    1 首先系统调用号大大的不同:mac64和linux32的系统调用号也不同(虽然局部可能有相同) 2 mac64的系统调用号在: /usr/include/sys/syscall.h 可以查到,但是调 ...

  7. linux下32位汇编调用规则

    传递给系统调用的参数必须安装参数顺序一次放到寄存器中,当系统调用完成后,返回值放在eax中: 当系统调用参数<=5个时: eax中存放系统调用的功能号,传递给系统调用的参数顺序依次放到寄存器:e ...

  8. win7win8 64位汇编开发环境合集安装与设置

    win7win8 64位汇编开发环境合集安装与设置 下载 win7 win8  64位汇编开发环境.rar 下载地址(免积分下载) http://download.csdn.net/detail/li ...

  9. Win7下64位机安装SQL2000

    win7下64位机安装SQLSERVER20001.右击计算机属性,查看操作系统 2.打开安装文件夹,按图点击 3.开始安装 4. 下一步选择 安装SQL Server2000 组件 5. 下一步 选 ...

随机推荐

  1. 2.6、Android Studio创建可伸缩的图片(9-patch文件)

    Draw 9-patch工具是一个所见即所得编辑器,允许你创建可以自动改变大小来适应视图的内容和屏幕的大小. 以下是使用Draw 9-path工具快速创建一个NinePatch图片. 1. 在命令行中 ...

  2. 因 URL 意外地以“/HelloWorld”结束,请求格式无法识别

    http://www.cnblogs.com/AngelLee2009/p/3540527.html

  3. java操作XML文件--读取内容

          先把问题贴出来:编写一个可以解析xml及修改xml内容的工具类       由于我以前做过Android应用程序开发,之前也解析过xml文件,所以,这道题不是很难,这篇文章我先解决第一个问 ...

  4. Cocos2D添加精灵纹理滤镜实现图像复古效果的转换

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 大家知道Cocos2d本身是一个非常强悍的2d游戏引擎,其中自 ...

  5. 学习TensorFlow,生成tensorflow输入输出的图像格式

    TensorFLow能够识别的图像文件,可以通过numpy,使用tf.Variable或者tf.placeholder加载进tensorflow:也可以通过自带函数(tf.read)读取,当图像文件过 ...

  6. linux qcom LCD framwork

    点击打开链接 0.关键字 MDSS : Multimedia Display sub system DSI: Display Serial Interface 1.涉及文件 (1) drivers\v ...

  7. Android的搜索框SearchView的用法-android学习之旅(三十九)

    SearchView简介 SearchView是搜索框组件,他可以让用户搜索文字,然后显示.' 代码示例 这个示例加了衣蛾ListView用于为SearchView增加自动补全的功能. package ...

  8. 小文本——Cookies

    http协议的无状态性导致在需要会话的场景下寸步难行,例如一个网站为了方便用户,在一段时间内登录过改网站的浏览器客户端实现自动登录,为实现这种客户端与服务器之间的会话机制需要额外的一些标识,http头 ...

  9. 初次见面 你好EF

    EF(yif),第一次听到这个名字的时候,以为是一个帅帅的魔术师,在小编的傻傻的梦想里,就是有一天,有一个魔术师站在小编面前,变出一大捧的玫瑰花,然后,然后不要钱`(*∩_∩*)′,然而在我们的编程世 ...

  10. SpringMVC项目中启动自加载Listener

    package com.kuman.cartoon.listener; import java.util.List; import org.springframework.beans.factory. ...