x64汇编:内存工作的基本原理
大家好你们可以叫我凌是个16岁网络安全学习者。想不到吧我也有学习研究x64汇编语言察觉现在安全领域该人才较少。可是我发现目前市面上对于x64汇编的资料少之又少参考的文章也不多对于我这个英语渣来说。所以我准备在学习的时候也顺便写写文章来分享分享我的学习笔记供大家一起学习分享。本栏目永远坚持无偿分享欢迎各路学者内存的本质一排带编号的开关计算机内存其实就是一个巨大连续的开关阵列微观角度俗语叫做“晶体管”。每个开关只能处于两种状态0 断开没电1 闭合有电这些开关被分成8个一组每组称为一个字节byte。为什么要8个一组因为8个开关能表示2**8 256种不同的0/1组合足够表示英文字母、数字、小整数等。每一组开关每一个字节都有一个唯一的编号这个编号叫做地址。例如- 第0组开关的地址是0- 第1组开关的地址是1- 第2组开关的地址是2- 略......地址通常用十六进制书写比如0x1000相当于门牌号。下面是个微型内存只有3个字节地址开关状态8个开关解释可以当作什么001000001字母A的编码101000010字母B的编码201000011字母C的编码内存里只存储这些0和1至于它们代表字母还是数字完全由程序决定。如何找到一组开关地址与标签在汇编语言里我们可以直接使用数字地址比如 [0]但更常见的做法是给地址个名字标签。例如下面这个section .datamy_byte db 01000001b; 把地址 X 命名为 my_byte并让那组开关变成 01000001这里db表示“定义一个字节”01000001b后面的b表示二进制数。之后my_byte就代表那个地址[my_byte]代表该地址里开关的状态。读写内存用 mov 指令CPU不能直接操作内存里的开关它必须先把开关状态复制到自己内部的“记事本”寄存器里。寄存器也有名字比如al是一个8位的“记事本”正好装下一组开关。- 读内存把开关状态复制到寄存器mov al, [my_byte]; 把 my_byte 那组开关的0/1状态复制到 al- 写内存把寄存器的值复制到开关组mov [my_byte], al; 把 al 里的0/1状态复制到 my_byte 那组开关注意[my_byte]表示“开关组本身”而my_byte表示“开关组的地址编号”。-mov al, [my_byte]→ 正确读开关状态-mov al, my_byte→ 错误会把地址编号当成数据一个完整的例子可编译运行下面这个程序定义了三个字节变量然后交换它们的值最后以退出码形式输出其中一个变量的值作为验证。; 文件名: swap_bytes.asm; 功能: 交换两个字节变量的值并退出section .dataa db 00000001b ; 地址 a 里存 1b db 00000010b ; 地址 b 里存 2c db 00000000b ; 地址 c 里存 0section .textglobal _start_start:; 把 a 和 b 的值读到寄存器mov al, [a] ; al 1mov bl, [b] ; bl 2; 交换mov [a], bl ; a 变成 2mov [b], al ; b 变成 1; 把 a 的新值作为退出码movzx rdi, byte [a] ; rdi 2 (movzx 将8位扩展到64位)mov rax, 60syscall编译和运行在 Linux 终端中nasm -f elf64 swap_bytes.asm -o swap_bytes.old swap_bytes.o -o swap_bytes./swap_bytesecho $?# 输出 2证明交换成功这个程序虽没有任何打印输出但它通过退出码告诉了我们结果。你可以修改a和b的初始值重新编译运行观察退出码的变化。小结-内存 无数个8个一组的开关每个开关只能0或1。-地址 开关组的编号我们可以给编号起名字标签。-读写内存用mov指令配合中括号[]表示开关组本身。-寄存器CPU内部的“记事本”用于临时存放数据。拓展以上只讲了内存最核心的模型开关、地址、读写。但实际编程中还会遇到以下概念它们将在本栏目的后续笔记中逐一深入- 空指针引用为什么崩溃简单来说地址0被操作系统保护访问它会导致程序终止。- 内存分配谁来决定你能用哪些地址操作系统给每个程序划了一块地址范围程序只能在这块范围内读写。- 堆和栈是什么栈用于函数调用和局部变量堆用于动态申请内存。- 堆溢出、栈溢出、内存泄漏以上拓展内容都会在之后进行讲解现在不要求掌握大概了解下也行