大小端
- 可以将内存想象为一个大数组。它包含字节。
- 每个地址存储内存“数组”的一个元素。每个元素都是一个字节。
- 例如我们有 4 个字节:
AA 56 AB FF
小端字节序
- 低地址存低位字节
|
1 2 3 4 |
0 FF 1 AB 2 56 3 AA |
大段字节序
- 高地址存低位字节
|
1 2 3 4 |
0 AA 1 56 2 AB 3 FF |
汇编程序组成
- data
- 用于声明初始化数据或常量
- bss
- 用于声明未初始化的变量
- text
- 用于代码
数据类型
- 字节
- 一个字节8个位
byte ptr
- 字
- 一个字两个字节
word ptr
- 双字
- 一个双字是 4 个字节
dword ptr
- 四字
- 一个四字是 8 个字节
qword ptr
- 双四字
- 一个双四字是 16 个字节
- 也就是有128位
示例1
- 数据段
- 3个常量
num1,num2,num3
|
1 2 3 4 |
section .data num1: equ 100 num2: equ 50 msg: db "hello,aet",10 |
声明数据
声明初始化数据
dbdwdddqdtdodydz
|
1 2 3 4 5 |
;; 初始化4个字节 db 0x01, 0x02, 0x03, 0x04 ;; 初始化一个字 dw ox1234 |
声明未初始化的变量
resbreswresdresqrestresoresyresz
包括外部二进制文件
incbin
定义常数
equ
|
1 |
one equ 1 |
重复指令或数据
times
算术运算
add:整数相加sub:减去mul:无符号乘法imul:有符号乘法div:无符号除法idiv:有符号除法inc:递增dec:递减neg:求补
控制流
|
1 2 3 |
;; 比较 cmp rax, 50 |
je:如果相等jz:如果为零jne:如果不等于jnz:如果不为零jg:如果第一个操作数大于第二个操作数jge:如果第一个操作数大于或等于第二个操作数ja:与jg相同,但执行无符号比较jae:与jge相同,但执行无符号比较
|
1 2 3 4 5 |
if (rax != 50) { exit(); } else { right(); } |
|
1 2 3 |
cmp rax, 50 jne .exit jmp .right |
jmp:无条件跳转
|
1 |
jmp label |
|
1 2 3 4 5 6 7 8 9 |
_start: ;; do something jmp .exit .exit: mov rax, 60 mov rdi, 0 syscall |
示例2
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
section .data num1: equ 100 num2: equ 50 msg: db "ok,ok\n" section .text global my_start my_start: mov rax, num1 mov rbx, num2 add rax, rbx cmp rax, 150 jne .exit jmp .right .right: mov rax, 1 mov rdi, 1 mov rsi, msg mov rdx, 6 syscall jmp .exit .exit: mov rax, 60 mov rdi, 0 syscall |
|
1 2 3 4 5 6 7 8 9 10 11 |
#include <iostream> extern "C" int my_start(); int main() { auto res = my_start(); std::cout << res << std::endl; return 0; } |
寄存器和栈
- 我们有
rax,rbx,rcx,rdx,rdi,rsi,rbp,rsp,以及r8-r1516个通用寄存器可以用,严格来说还是比较少 - 但是我们可以使用栈,堆栈是内存中特殊区域,运行原理为后进先出
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
global _start section .text _start: mov rax, 1 call incRax cmp rax, 2 jne exit ;; ... incRax: inc rax ret |
参数
rdi: 第一个参数rsi: 第二个参数rdx: 第三个参数rcx: 第四个参数r8: 第五个参数r9: 第六个参数- 超过6个的参数将在堆栈中传递
堆栈指针
rbp寄存器
- 堆栈的基址指针寄存器,它指向当前堆栈帧的基址
rsp寄存器
- 堆栈指针,指向当前堆栈帧的顶部
push and pop
- 递增堆栈指针(RSP)并将参数存储在堆栈指针指向的位置
|
1 |
push arg |
- 将数据从堆栈指针指向的位置复制到参数,RSP会自动增加,指向新的栈顶位置
|
1 |
pop arg |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
global _start section .text _start: mov rax, 1 mov rdx, 2 push rax push rdx mov rax, [rsp+8] ;; ... |
示例3
|
1 2 3 4 5 6 7 8 |
section .data SYS_WRITE equ 1 STD_IN equ 1 SYS_EXIT equ 60 EXIT_CODE equ 0 NEW_LINE db 0xa WRONG_ARGC db "Must be two command line argument", 0xa |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
section .text global _start _start: pop rcx cmp rcx, 3 jne argcError add rsp, 8 pop rsi call str_to_int mov r10, rax pop rsi call str_to_int mov r11, rax add r10, r11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
argcError: ;; sys_write syscall mov rax, 1 ;; file descritor, standard output mov rdi, 1 ;; message address mov rsi, WRONG_ARGC ;; length of message mov rdx, 34 ;; call write syscall syscall ;; exit from program jmp exit |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
str_to_int: xor rax, rax mov rcx, 10 next: cmp [rsi], byte 0 je return_str mov bl, [rsi] sub bl, 48 mul rcx add rax, rbx inc rsi jmp next return_str: ret |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
print: ;;;; calculate number length mov rax, 1 mul r12 mov r12, 8 mul r12 mov rdx, rax ;;;; print sum mov rax, SYS_WRITE mov rdi, STD_IN mov rsi, rsp ;; call sys_write syscall jmp exit |
|
1 2 3 4 5 |
exit: mov rax, SYS_EXIT exit code mov rdi, EXIT_CODE syscall |
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows API11/11
- ♥ Soui应用 动画一06/24
- ♥ Nsis打包相关09/29
- ♥ Windows 核心编程 _ 作业07/01
- ♥ 相关指令05/06
- ♥ Windows创建进程实例:权限及子进程监控相关10/19
热评文章
- 相关指令 0
- X86_64汇编学习记述四 0
- 定位内存与数据处理 0
- MASM:概述一 0
- 关于程序 0
- MASM:OllyDBG二 0

