到底日更变成拖更变成月更了,水一篇吧,实在太忙了,或者你们想看的话我更新高等数学也行
借鉴来源:
# ASM 源码:
section .data
msg db "Welcome_to_CTFshow_PWN", 0
section .text
global _start
_start:
; 立即寻址方式
mov eax, 11 ; 将11赋值给eax
add eax, 114504 ; eax加上114504
sub eax, 1 ; eax减去1
; 寄存器寻址方式
mov ebx, 0x36d ; 将0x36d赋值给ebx
mov edx, ebx ; 将ebx的值赋值给edx
; 直接寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
; 寄存器间接寻址方式
mov esi, msg ; 将msg的地址赋值给esi
mov eax, [esi] ; 将esi所指向的地址的值赋值给eax
; 寄存器相对寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
add ecx, 4 ; 将ecx加上4
mov eax, [ecx] ; 将ecx所指向的地址的值赋值给eax
; 基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 2 ; 将2赋值给edx
mov eax, [ecx + edx*2] ; 将ecx+edx*2所指向的地址的值赋值给eax
; 相对基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 1 ; 将1赋值给edx
add ecx, 8 ; 将ecx加上8
mov eax, [ecx + edx*2 - 6] ; 将ecx+edx*2-6所指向的地址的值赋值给eax
; 输出字符串
mov eax, 4 ; 系统调用号4代表输出字符串
mov ebx, 1 ; 文件描述符1代表标准输出
mov ecx, msg ; 要输出的字符串的地址
mov edx, 22 ; 要输出的字符串的长度
int 0x80 ; 调用系统调用
; 退出程序
mov eax, 1 ; 系统调用号1代表退出程序
xor ebx, ebx ; 返回值为0
int 0x80 ; 调用系统调用
# 详解:
# 1. .data 段
section .data
msg db "Welcome_to_CTFshow_PWN", 0
解释:
-
.data段:用来存放程序中的已初始化数据,这些数据在程序运行时会被加载到内存中。 -
msg db:声明一个字符串"Welcome_to_CTFshow_PWN",以字节(db= Define Byte)存储,并以0结尾,表示字符串结束符(类似 C 语言的\0)。 - 地址:
msg是一个标签,代表该字符串的内存地址,供后续使用。
# 2. .text 段
section .text
global _start
_start:
解释:
-
.text段:存放程序的代码(指令)。 -
_start:程序的入口,系统从这里开始执行程序(对应 Linux 的 ELF 文件格式的起点)。
# 3. 立即寻址方式
mov eax, 11 ; 将11赋值给eax
add eax, 114504 ; eax加上114504
sub eax, 1 ; eax减去1
解释:
-
立即寻址方式:操作数是一个立即数,直接嵌入在指令中。例如
11和114504。 -
过程
:
mov eax, 11:将立即数11加载到寄存器eax中。add eax, 114504:将立即数114504加到eax的当前值上。sub eax, 1:将eax的值减去立即数1。
-
硬件实现:立即数直接写入指令的操作数字段,CPU 解码指令后直接将值加载到指定寄存器中。
# 4. 寄存器寻址方式
mov ebx, 0x36d ; 将0x36d赋值给ebx
mov edx, ebx ; 将ebx的值赋值给edx
解释:
-
寄存器寻址方式:操作数在寄存器中,CPU 直接对寄存器进行操作。
-
过程
:
mov ebx, 0x36d:将立即数0x36d加载到寄存器ebx。mov edx, ebx:将寄存器ebx的值复制到寄存器edx。
-
硬件实现:寄存器之间的数据传递不需要访问内存,速度非常快。
# 5. 直接寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
解释:
-
直接寻址方式:操作数的地址直接给出,即指令中明确指出操作数所在的内存地址。
-
过程
:
mov ecx, msg:将标签msg所指向的内存地址加载到寄存器ecx。
-
硬件实现:CPU 将指令中的地址字段直接解析为内存地址,然后取出对应地址的内容。
# 6. 寄存器间接寻址方式
mov esi, msg ; 将msg的地址赋值给esi
mov eax, [esi] ; 将esi所指向的地址的值赋值给eax
解释:
-
寄存器间接寻址方式:寄存器中存储的是操作数的内存地址,操作数存储在该地址中。
-
过程
:
mov esi, msg:将msg的地址加载到寄存器esi。mov eax, [esi]:从esi指向的内存地址中读取数据,并存储到寄存器eax。
-
硬件实现
:
- CPU 读取寄存器
esi的值(作为内存地址)。 - 然后去内存中访问该地址,取出存储的值加载到寄存器
eax。
- CPU 读取寄存器
# 7. 寄存器相对寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
add ecx, 4 ; 将ecx加上4
mov eax, [ecx] ; 将ecx所指向的地址的值赋值给eax
解释:
-
寄存器相对寻址方式:寄存器中存储基地址,操作数的地址是基地址加上一个偏移量。
-
过程
:
mov ecx, msg:将msg的地址加载到寄存器ecx。add ecx, 4:将ecx加上偏移量4。mov eax, [ecx]:从ecx指向的地址读取数据到寄存器eax。
-
硬件实现
:
- 计算内存地址:
ecx + 4。 - 访问该地址并读取数据。
- 计算内存地址:
# 8. 基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 2 ; 将2赋值给edx
mov eax, [ecx + edx*2] ; 将ecx+edx*2所指向的地址的值赋值给eax
解释:
-
基址变址寻址方式:地址是基地址加上索引值(
edx),并根据一个比例因子(如*2)计算得到。 -
过程
:
mov ecx, msg:加载基地址到寄存器ecx。mov edx, 2:加载索引值2到寄存器edx。mov eax, [ecx + edx*2]:计算地址为ecx + edx*2,然后读取该地址的数据到eax。
-
硬件实现
:
- 地址计算:
ecx + edx*2。 - 访问该内存地址并读取数据。
- 地址计算:
# 9. 相对基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 1 ; 将1赋值给edx
add ecx, 8 ; 将ecx加上8
mov eax, [ecx + edx*2 - 6] ; 将ecx+edx*2-6所指向的地址的值赋值给eax
解释:
-
相对基址变址寻址方式:地址是基地址加索引值乘比例因子再加偏移量。
-
过程
:
mov ecx, msg:加载基地址到ecx。mov edx, 1:加载索引值1到edx。add ecx, 8:将偏移量8加到ecx。mov eax, [ecx + edx*2 - 6]:计算地址为ecx + edx*2 - 6,然后读取数据到eax。
-
硬件实现
:
- 地址计算:
ecx + edx*2 - 6。 - 访问该地址并读取数据。
- 地址计算:
# 10. 系统调用(输出字符串)
mov eax, 4 ; 系统调用号4代表输出字符串
mov ebx, 1 ; 文件描述符1代表标准输出
mov ecx, msg ; 要输出的字符串的地址
mov edx, 22 ; 要输出的字符串的长度
int 0x80 ; 调用系统调用
解释:
-
过程
:
mov eax, 4:设置系统调用号为4(sys_write)。mov ebx, 1:文件描述符为1(标准输出)。mov ecx, msg:输出字符串的地址。mov edx, 22:字符串的长度。int 0x80:触发软中断,调用 Linux 内核的系统调用。
-
硬件实现
:
- 将参数放入寄存器(
eax,ebx,ecx,edx)。 - 调用
int 0x80,切换到内核模式执行sys_write。
- 将参数放入寄存器(
# 11. 退出程序
mov eax, 1 ; 系统调用号1代表退出程序
xor ebx, ebx ; 返回值为0
int 0x80 ; 调用系统调用
解释:
-
过程
:
mov eax, 1:设置系统调用号为1(sys_exit)。xor ebx, ebx:返回值为0。int 0x80:触发软中断,调用内核终止程序。
# 总结
-
寻址方式:
- 立即寻址:直接在指令中给出操作数。
- 寄存器寻址:操作数在寄存器中。
- 直接寻址:操作数的地址直接给出。
- 间接寻址:通过寄存器指向的地址访问数据。
- 相对寻址:基址 + 偏移量。
- 基址变址寻址:基址 + 索引 * 比例因子。
- 相对基址变址寻址:基址 + 索引 * 比例因子 + 偏移量。
-
系统调用:
- 使用
int 0x80切换到内核模式执行特定操作。
这个 int 0x80 有点小关键的,有时候打 shellcode 会用
- 使用

