参考: 《Begining x64 Assembly Programming: From Novice to AVX Professional》 --- Jo Van Hoey
如果大家对汇编语言有兴趣,推荐阅读上面的书籍。上面的书籍不是简单的介绍,也不是厚重的参考书,而是由实例引导的有趣的工具书,非常值得阅读。
学习环境:Linux version 5.9.16-1-MANJARO (GCC 10.2.0, GNU LD 2.35.1, VALGRIND 3.16.1, NASM 2.15.05) ,推荐在虚拟机如VirtualBox搭建实验环境
Day1:编写 "Hello, World."程序
HelloWorld.asm
; HelloWorld.asm ;注释
section .data ;数据段
msg db "Hello, World", 10, 0 ; 10=\n
section .bss ;变量段
section .text ;文本段
global main ;全局函数入口main
main:
mov rax, 1 ;1 = 写
mov rdi, 1 ;1 = stdout
mov rsi, msg ;字符串地址
mov rdx, 13 ;字符串个数,不包含最后0
syscall ;写系统调用
mov rax, 60 ;60=exit
mov rdi, 0 ;exit code 0
syscall ;退出系统调用
说明:
1--- 可执行文件ELF的格式一般为 ELF头 + Section + 符号表及调试信息等,最重要得有.data .rodata .text .bss段。
- .text 程序代码块
- .data 含有初始值的全局变量和静态变量
- .rodata 只读数据
- .bss 未初始化的全局变量和静态变量
其他运行时的局部变量等放在stack或heap中。
2 --- CPU执行命令流程: 将执行参数(函数参数)提前放置在默认的寄存器中那个,然后调用syscall。
Makefile
# Makefile for HelloWorld.asm
HelloWorld: HelloWorld.o
gcc -o HelloWorld HelloWorld.o -no-pie
HelloWorld.o: HelloWorld.asm
gcc -Wall -f elf64 -g -F dwarf HelloWorld.asm -l HelloWorld.lst
说明:
-no-pie: pie (position independent execution) 是GCC为程序安全提供的机制,这里为了简化不使用
-f elf64 生成ELF64的可执行文件
-g -F dwarf 生成调试信息,调试文件格式为dwarf。
在这里给大家推荐一个网站,也可以在线进行汇编语言编写,很强大:) https://godbolt.org
知识汇总:
一些基本语法:
1 .赋值操作 .data <variable name> <type> <value>
.rodata <variable name> equ <value> 为常量赋值
.bss <variable name> <type> <number>
2. mov 指令必须以寄存器register作为中转站
3. syscall表: 系统调用表可以在内核源代码中查询,下文对常见的系统调用表做归纳,业余时间我会基于x86_64 Linux Kernel v5.10.2
另做一份参考表。
参考文章:Linux_System_Call_Table_for_x86_64
扩展: 利用GAS汇编编写helloworld
.global _start
.data
message:
.ascii "Hello, world\n"
.text
_start:
# write (1, msj, 13)
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handler 1 is stdout
mov $message, %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall
# exit(0)
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # we want to return code 0
syscall