linux下64位汇编的系统调用(4)
经过上一篇的铺垫貌似可以很轻松的用汇编写出mmap的代码来,可仔细一看,还是有不少问题需要解决:
1.系统调用mmap如果出错并不直接返回MAP_FAILED(-1),而是一个“类似”值;C库中的mmap函数对其做了包装,使其最终返回-1;如果我们直接调用mmap syscall,则这些事必须自己来做。
2.C库函数如果出错会设置errno的值,而在汇编中没法直接用:
extern errno
的方法使用外部的值,连接时会报错:
/usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in p.o
/lib/x86_64-linux-gnu/libc.so.6: error adding symbols: 错误的值
C语言的解决办法很简单,直接把:
extern int errno;
//替换为
#include <errno.h>
但nasm下这招没法使;我们先看一下errno对应的C代码:
#define errno() *errnofunc()
int *errnofunc()
{
int *errnoptr = get_thread_data(ERRNOPTR);
return errnoptr;
}
可以看到其调用另一个函数,在nasm中我们可以大致这么写:
extern __errno_location
call __errno_location
mov rax,qword [rax]
不过貌似也不太对 :( ,不过我们可以在mmap系统调用后自己操作errno的值,以下代码将填充变量errno的值并且如果出错将修正mmap的返回值为-1:
section .data
errno dq 0
;mmap syscall 之后
cmp rax,0xfffffffffffff001
jb next
push rax
neg rax
mov [errno],rax
pop rax
or rax,-1
next:
;处理mmap返回后的逻辑
3 可以看到C代码中调用mmap参数压栈,是将第4个参数放到rcx里,但是在C库mmap函数里又将rcx赋值给r10;这正应了前面调用规则里的内核系统调用第4个参数是放在r10里,而不是rcx里的哦;所以汇编中我们直接放在r10里即可,不用先转到rcx里了。
最后的代码如下:
section .data
errno dq 0
addr dq 0
MAP_FAILED equ -1
;MAP_LEN equ 40960
MAP_LEN equ 0xffffffffffffffff
PROT_READ_WRITE equ 3
MAP_SHARED_ANON equ 33
;MAP_SHARED_ANON equ 0x20
section .text
;extern errno
extern __errno_location
extern strerror
extern printf
;if use ld
;global _start
;if use gcc
global main
;_start:
main:
and rsp,~0xffff ;堆栈对齐 equ 0xffffffffffff0000
mov rax,9 ;mmap NO
mov rdi,0 ;map address
mov rsi,MAP_LEN ;map size
mov rdx,PROT_READ_WRITE
mov r10,MAP_SHARED_ANON
mov r8,-1 ;忽略fd
mov r9,0 ;offset
syscall
cmp rax,0xfffffffffffff001
jb next
push rax
neg rax
mov [errno],rax
pop rax
or rax,-1
next:
cmp rax,MAP_FAILED
;cmp rax,0
;js map_failed
je map_failed
mov [addr],rax
mov rsi,[addr]
mov rdi,msg_success
call printf
mov rax,11
mov rdi,addr
mov rsi,MAP_LEN
syscall
jmp exit
map_failed:
;mov rdi,0xb
;call __errno_location
;mov rax,qword [rax]
;mov rsi,[errno]
mov rdi,[errno]
call strerror
mov rsi,rax
mov rdi,msg_failed
call printf
exit:
mov rax,60 ;exit NO
mov rdi,0 ;error_code
syscall
msg_success: db "map successed , addr at %p",0ax,0
msg_failed: db "map failed ,due to %s",0ax,0
编译连接:
nasm -f elf64 p.s
gcc -o p p.o
如果mmap成功结果如下:
wisy@wisy-pad:~/src/asm_src/nasm_src/linux$ ./p
map successed , addr at 0x7fbe5c94e000
可以用strace查看其返回的syscall:
mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fc6b2397000
如果mmap出错则会显示出错原因:
//将MAP_LEN 设为超大的值
./p
map failed ,due to Cannot allocate memory
//传递给flags错误的参数
./p
map failed ,due to Invalid argument
linux下64位汇编的系统调用(4)的更多相关文章
- linux下64位汇编的系统调用(2)
知道了syscall调用号之后还不算完,还要搞清楚2件事: 1 每种调用号需要传递哪些参数: 2 调用如何传递参数以及结果如何返回: 第一个问题的答案是: 在linux系统中某个程序执行时进行的系统调 ...
- linux下64位汇编的系统调用(3)
背景知识基本交代清楚了,下面我们实际写一个小例子看一下.代码的功能很简单,显示一行文本,然后退出.我们使用了syscall中的write和exit调用,查一下前面的调用号和参数,我们初步总结如下: w ...
- linux下64位汇编的系统调用(1)
现在基本上系统都是64位了,而64位系统下的汇编和32位有了较大的变化,无论是系统调用的接口还是C标准库的接口都和32位汇编有所不同:下面简单谈一下在64位linux下如何利用汇编直接调用系统调用. ...
- linux下64位汇编的系统调用(5)
看到这里大家都基本知道了如何进行linux下的汇编系统调用:不过有些童鞋可能会问:那些C库中函数里为我们解决的额外汇编代码你是怎么知道的? 好吧,我承认:我是通过逆向知道的,这貌似有点犯规的嫌疑- 比 ...
- linux下64位汇编的系统调用系列
http://blog.csdn.net/mydo/article/category/3084893
- Mac OS X下64位汇编与Linux下64位汇编的一些不同
1 首先系统调用号大大的不同:mac64和linux32的系统调用号也不同(虽然局部可能有相同) 2 mac64的系统调用号在: /usr/include/sys/syscall.h 可以查到,但是调 ...
- linux下32位汇编调用规则
传递给系统调用的参数必须安装参数顺序一次放到寄存器中,当系统调用完成后,返回值放在eax中: 当系统调用参数<=5个时: eax中存放系统调用的功能号,传递给系统调用的参数顺序依次放到寄存器:e ...
- win7win8 64位汇编开发环境合集安装与设置
win7win8 64位汇编开发环境合集安装与设置 下载 win7 win8 64位汇编开发环境.rar 下载地址(免积分下载) http://download.csdn.net/detail/li ...
- Win7下64位机安装SQL2000
win7下64位机安装SQLSERVER20001.右击计算机属性,查看操作系统 2.打开安装文件夹,按图点击 3.开始安装 4. 下一步选择 安装SQL Server2000 组件 5. 下一步 选 ...
随机推荐
- Linux日志管理高级进阶:实例详解syslog
syslog已被许多日志函数采纳,它用在许多保护措施中,任何程序都可以通过syslog记录事件.syslog可以记录系统事件,可以写到一个文件或设备中,或给用户发送一个信息.它能记录本地事件或通过网络 ...
- Python模块探秘之EasyGui
在Windows想用Python开发一些简单的界面,所以找到了很容易上手的EasyGui库.下面就分享一下简单的使用吧. 参考的链接:官网Tutorial 接下来,我将从简单,到复杂一点点的演示如何使 ...
- DBoW2应用
图像对应的bag-of-words向量\(v_t\) 假设词典总共有\(W\)个单词,那么每一幅图像能够用一个\(W\)维的向量表示 \((t_1, t_2, t_3, ..., t_W)\)其中 \ ...
- Nhibernate系列学习之(一) ORM and Nhibernate入门实例解析
最近框架项目需要,数据层想使用Nhibernate,代替传统的sql语句的写法,更加使用面向对象的思维来维护实体与数据库的这层关系映射(ORM),好在之前接触过Java时学习使用了Hibernate, ...
- Qt中事件分发源代码剖析
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的. 下面举例说明: 1)首先看看下面一段示例代码: i ...
- JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码
JAVA之旅(三十)--打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码 三十篇了,又是一个 ...
- Activity与Fragment的生命周期详解
在安卓中Activity与Fragment是非常相似的两个类,它们各自都拥有自己的生命周期,且都可以用来显示布局文件中的视图.其中Activity是通过setContenView()显示视图,而Fra ...
- (七十六)CoreLocation(二)获取经纬度、速度、方向,进行区域监听
上节说明了如何在iOS7和iOS8上完成授权,并且开始获取位置,这一节介绍获取位置信息的方法. [定位精度] 定位精度有多种选择:根据字面意思即可理解 extern const CLLocationA ...
- Android版本更新时对SQLite数据库升级或者降级遇到的问题
SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定 ...
- OC语言编写:为视图添加丝滑的水波纹
先看一下最终效果图: 首先我们可以把如此丝滑的水波纹拆分一下下: 一条规律的曲线. 曲线匀速向右移动. 曲线下方的位置用颜色填充. 于是先来一条曲线吧. 对于需要产生波动如此规律的曲线,我们首先想到的 ...