nasm示例一:调用syscall打印Hello World

简介: NASM是基于英特尔 x86 架构的汇编与反汇编工具 syscall是x86_64架构中专门做系统调用的指令

  • NASM是基于英特尔 x86 架构的汇编与反汇编工具。
  • syscall是x86_64架构中专门做系统调用的指令,可参考syscall

1、示例

foo.nasm内容
    global _start

    section .text
_start:
    mov rax, 1                  ; sys_write的系统调用编号为1
    mov rdi, 1                  ; 文件句柄1对应stdout
    mov rsi, msg                ; 要输出的字符串地址
    mov rdx, msglen             ; 要输出的字符串长度
    syscall                     ; 系统调用
    mov rax, 60                 ; sys_exit的系统调用编号为60
    xor rdi, rdi                ; exit 0
    syscall

    section .data
msg: db "Hello, World!", 10     ; ascii表中10对应换行符
msglen: equ $ - msg             ; $ 等于当前行开头的地址
编译
nasm -felf64 foo.asm && ld -o foo foo.o
运行结果
[root@localhost nasm]# ./foo
Hello, World!

2、代码解释

2.1、syscall

x86平台syscall指令的参数、返回值与寄存器的对应关系

Syscall # Param 1 Param 2 Param 3 Param 4 Param 5 Param 6
rax rdi rsi rdx r10 r8 r9
Return value
rax

在linux系统中也可通过man syscall的方式查看
各平台系统调用指令和返回值对应寄存器
9f2aa3cc8b696daa1b3cf5bf41f9f45f2502ca59
系统调用参数对应寄存器
2bfdaf67ff8a7e797e650d090a089de09f427428
在linux平台write函数对应系统调用为sys_write,对应的syscall编号可在 arch/x86/entry/syscalls/syscall_64.tbl中查看
1   common  write           sys_write
60  common  exit            sys_exit
sys_write和sys_exit的定义为
asmlinkage long sys_write(unsigned int fd, const char __user *buf,
              size_t count);
asmlinkage long sys_exit(int error_code);

2.2、sys_exit

    mov rax, 60                 ; sys_exit的系统调用编号为60
    xor rdi, rdi                ; exit 0
    syscall
语句 xor rdi, rdi 将rdi寄存器值设置为0,至于为什么不使用 mov rdi, 0 可参考 Does using xor reg, reg give advantage over mov reg, 0?,程序运行效果为
[root@localhost nasm]# nasm -felf64 foo.asm && ld -o foo foo.o
[root@localhost nasm]# ./foo
Hello, World!
[root@localhost nasm]# echo $?
0
如果修改sys_exit系统调用的参数,那么程序运行的退出结果也会发生变化,如修改为
    mov rdi, rax
    mov rax, 60                 ; sys_exit的系统调用编号为60
    syscall
则程序退出码为sys_write的返回值,因为字符串msg长度为14,所以程序运行的退出码也为14
[root@localhost nasm]# nasm -felf64 foo.asm && ld -o foo foo.o
[root@localhost nasm]# ./foo
Hello, World!
[root@localhost nasm]# echo $?
14

2.3、字符串长度计算

在nasm中 $ 等于当前行开头的地址, $$ 等于当前section的开头地址,可参考 https://www.nasm.us/doc/nasmdoc3.html 的3.5 Expressions内容

NASM supports two special tokens in expressions, allowing calculations to involve the current assembly position: the $ and $$ tokens. $ evaluates to the assembly position at the beginning of the line containing the expression; so you can code an infinite loop using JMP $. $$ evaluates to the beginning of the current section; so you can tell how far into the section you are by using ($-$$).





目录
相关文章
|
IDE 开发工具 C++
VS2015+Qt5.9.8编译报错:error MSB6006: “cmd.exe”已退出,代码为 2
VS2015+Qt5.9.8编译报错:error MSB6006: “cmd.exe”已退出,代码为 2
2719 0
|
3月前
|
Go
【go笔记】使用标准库flag解析命令行参数
【go笔记】使用标准库flag解析命令行参数
|
6月前
|
Perl
awk通过 system() 函数调用其他命令获取输出
awk通过 system() 函数调用其他命令获取输出
453 7
|
Go
一文了解 Go fmt 标准库输出函数的使用
本篇文章对 fmt 标准库的常用输出函数进行了介绍。输出函数分三类介绍,第一类是输出到输出流里,第二类是标准输出,第三类是输出到字符串里。并给出简单的示例代码。
123 1
一文了解 Go fmt 标准库输出函数的使用
|
存储 Go
一文了解 Go fmt 标准库输入函数的使用
本篇文章对 fmt 标准库的常用输入函数进行了介绍。输入函数分三类介绍,第一类是从文件获取输入的内容,第二类是从标准输入获取输入的内容,第三类是从字符串里获取输入的内容。并给出简单的示例代码。
122 1
一文了解 Go fmt 标准库输入函数的使用
VC中TRACE()的用法
个人总结:最近看网络编程是碰到了TRACE语句,不知道在哪里输出,查了一晚上资料也没找出来,今天终于在CSDN上找到了,真是个高地方啊,方法如下: 1.在MFC中加入TRACE语句 2.在TOOLS->MFC TRACER中选择 “ENABLE TRACING”点击OK 3.
1166 0
【GO】标准输入与输出
【GO】标准输入与输出
93 0
【GO】标准输入与输出
|
前端开发
Python----魔法函数__enter__/__exit__的用法
Python----魔法函数__enter__/__exit__的用法
132 0
|
NoSQL C语言
printf段错误(core dump): 一个格式化输出引起的问题
printf段错误(core dump): 一个格式化输出引起的问题
516 0
|
程序员 C++
VS2015+Qt5.9.1编译报错:Moc系统找不到指定路径,error MSB6006 cmd.exe 已退出,代码为3 -- 完美解决
VS2015+Qt5.9.1编译报错:Moc系统找不到指定路径,error MSB6006 cmd.exe 已退出,代码为3 -- 完美解决
2556 0