【asm基础】在mac下使用nasm进行汇编

nasm安装

首先需要安装nasm,不同版本的OS X可能没有装nasm,或者版本比较老。

安装的方法有几个:

可以在官网http://www.nasm.us/找到下载:

下载到的nasm可以直接运行。

也可以通过brew来安装nasm,它上面的版本也是比较新的。至于如何安装brew就不在这里介绍了。

示例代码

以下的示例代码来自wiki

global _start   ; 定义入口函数

section .data
  query_string        :  db    "Enter a character:  "
  query_string_len    :  equ   $ - query_string
  out_string          :  db    "You have input:  "
  out_string_len      :  equ   $ - out_string

section .bss
  in_char:			resw 4

section .text

_start:
  mov rax, 0x2000004         ; syscall需要用到的参数,表示write
  mov rdi, 1                 ; 表示stdout
  mov rsi, query_string      ; syscall调用回到rsi来获取字符
  mov rdx, query_string_len  ; 并到rdx获取长度
  syscall

  ; 读取字符
  mov rax, 0x2000003         ; syscall需要用到的参数,表示read
  mov rdi, 0                 ; 表示stdin
  mov rsi, in_char           ; 字符存储位置,在.bbs段
  mov rdx, 2                 ; 从内核缓存获取两个字节,一个给字符一个给回车
  syscall

  ; 打印输入的值
  mov rax, 0x2000004
  mov rdi, 1
  mov rsi, out_string
  mov rdx, out_string_len
  syscall

  mov rax, 0x2000004
  mov rdi, 1
  mov rsi, in_char
  mov rdx, 2                 ; 这里两个字节,因为第二个是回车
  syscall

  ; 退出syscall
  mov rax, 0x2000001         ; syscall需要用到的参数,表示退出syscall
  mov rdi, 0
  syscall

需要说明的几点:

1. global对外公开了函数的名称,这样ld时就可以指定它为入口函数;

2. syscall是内核调用函数,前面的mov指令都是用来提供参数的,在"syscall.h"中可以找到调用的具体作用(根据rax来确定);具体所有参数要怎么写,我也没有找到具体的说明...

关于syscall,在这里补充一些内容:

syscall指令使CPU从用户态跳转到了内核态,并执行内核态的代码(本例中就是控制台的读写操作)。

上述代码中的寄存器使用也是有规定的:首先rax用来确定内核态中需要执行的具体函数,这一部分在《深入理解Linux内核》一书的“系统调用”这一节中有讲到;其次,rdi、rsi、rdx等寄存器是用来传递内核态所执行的函数的参数的,在《nasmdoc.pdf》中的“Interfacing to 64-bit Programs(Unix)》一节中有如下的说明:

The first six integer arguments (from the left) are passed inRDI,RSI,RDX,RCX,R8, andR9, in that order.

与代码中的参数传递一致。

这里的参数规定也并不是nasm自己定的,而是因为mac 64位系统实现的ABI来决定的,具体可以参考《System V Application Binary Interface AMD64 Architecture Processor Supplement》,这个规范中的"Calling Conventions"一节中有如下的说明:

通过上面的说明,就可以基本理解例子中的代码了。

顺便说明下ABI是什么(摘自百度):

应用程序二进制接口 描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低级接口 。
ABI涵盖了各种细节,如:
数据类型的大小、布局和对齐;
调用约定(控制着函数的参数如何传送以及如何接受返回值),例如,是所有的参数都通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后;
系统调用的编码和一个应用如何向操作系统进行系统调用;
以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等。

另外,syscall.h中的参数并没有包含高字节中的2,原因在TheXploit Mac OS X 64 bit Assembly System Calls - TheXploit里面有说明,这里只摘抄一段:

Mac OS X or likely BSD has split up the system call numbers into several different “classes.” The upper order bits of the syscall number represent the class of the system call, in the case of write and exit, it’s SYSCALL_CLASS_UNIX and hence the upper order bits are 2! Thus, every Unix system call will be (0×2000000 + unix syscall #).

编译和运行

如下图所示:

这里需要了解nasm的编译时的一些参数。

比如-f用来指定编译环境,本机是mac x64的环境(就是这里的macho64,顺便说一句,这里的mach是一个操作系统内核,mac的系统是在此基础上开发的,所以是mach,而不是mac或者其它)。

在nasm编译器自带的nasmdoc.pdf手册中有更多的介绍。

也可以参考http://blog.csdn.net/jiangwei0512/article/details/51636602

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值