MIPS64 架构基础知识¶
Pwn 速查
- n64/n32 函数参数:
$a0-$a7;系统调用参数通常只用$a0-$a5。 - Linux MIPS 各 ABI 的 syscall 错误由
$a3标记,出错时$v0通常是正 errno。 - n64/n32 栈对齐为 16 字节;MIPS64 仍有延迟槽。
MIPS64 寄存器详解¶
通用寄存器 ($0-$31)¶
| 寄存器 | 别名 | 用途 |
|---|---|---|
$0 |
$zero |
硬件零寄存器,永远为 0 |
$1 |
$at |
汇编器临时寄存器 |
$2-$3 |
$v0-$v1 |
函数返回值;$v0 也放系统调用号 |
$4-$11 |
$a0-$a7 |
n32/n64 函数参数 |
$12-$15 |
$t4-$t7 |
n32/n64 临时寄存器 |
$16-$23 |
$s0-$s7 |
保存寄存器 |
$24-$25 |
$t8-$t9 |
临时寄存器 |
$26-$27 |
$k0-$k1 |
内核保留 |
$28 |
$gp |
全局指针 |
$29 |
$sp |
栈指针 |
$30 |
$fp / $s8 |
帧指针 / 保存寄存器 |
$31 |
$ra |
返回地址 |
寄存器别名和用途¶
| 寄存器 | 别名 | 主要用途 | 调用约定 |
|---|---|---|---|
$0 |
$zero |
硬件零寄存器 | 常数 0 |
$1 |
$at |
汇编器临时寄存器 | 汇编器保留 |
$2 |
$v0 |
函数返回值 / 系统调用号 | 调用者保存 |
$3 |
$v1 |
函数返回值 | 调用者保存 |
$4-$7 |
$a0-$a3 |
第 1-4 个参数 | 调用者保存 |
$8-$11 |
$a4-$a7 |
第 5-8 个参数(n32/n64) | 调用者保存 |
$12-$15 |
$t4-$t7 |
临时寄存器(n32/n64) | 调用者保存 |
$16-$23 |
$s0-$s7 |
保存寄存器 | 被调用者保存 |
$24-$25 |
$t8-$t9 |
临时寄存器 | 调用者保存 |
$26-$27 |
$k0-$k1 |
内核保留 | 不应在用户态随意使用 |
$28 |
$gp |
全局指针 | ABI 相关 |
$29 |
$sp |
栈指针 | 特殊 |
$30 |
$fp / $s8 |
帧指针 / 保存寄存器 | 被调用者保存 |
$31 |
$ra |
返回地址 | 特殊:非叶子函数需先保存自己的返回地址 |
特殊寄存器¶
| 寄存器 | 作用 |
|---|---|
PC |
程序计数器(64 位) |
HI |
乘法 / 除法结果高位(64 位) |
LO |
乘法 / 除法结果低位(64 位) |
字节序¶
MIPS64 (big-endian) 与 MIPS64EL (little-endian) 主要区别在内存中字节排列,上层寄存器与 ABI 规则相同。
| 架构 | 端序 | 0x1122334455667788 在内存中的字节序(地址递增) |
|---|---|---|
| MIPS64 | Big-endian | 11 22 33 44 55 66 77 88 |
| MIPS64EL | Little-endian | 88 77 66 55 44 33 22 11 |
Exploit 提醒
地址泄漏、栈覆盖和 ROP payload 写入时要同时确认 ABI 与端序;MIPS64 的“64 位 CPU”不等于一定是 n64 ABI。
三种主要 ABI¶
| ABI | 指针 / long |
参数寄存器 | 栈对齐 | Pwn 关注点 |
|---|---|---|---|---|
| o32 | 32 位 | $a0-$a3 |
8 字节 | 兼容 MIPS32,syscall 基址 4000 |
| n32 | 32 位指针 + 64 位寄存器 | $a0-$a7 |
16 字节 | 指针仍是 32 位,但可使用 64 位运算 |
| n64 | 64 位 | $a0-$a7 |
16 字节 | 现代 64 位 MIPS 主要 ABI,syscall 基址 5000 |
Warning
同一个 MIPS64 ELF 不能只看“64 位 CPU”,还要看 ABI:o32/n32/n64 的系统调用号、参数数量和栈布局都不同。
函数调用约定详解¶
参数传递¶
不同 ABI 的参数传递规则:
| ABI | 参数寄存器 | 更多参数 | 返回值 | 栈对齐 |
|---|---|---|---|---|
| n64 | $a0-$a7 ($4-$11) |
栈传递 | $v0, $v1 ($2, $3) |
16 字节 |
| n32 | $a0-$a7 ($4-$11) |
栈传递 | $v0, $v1 ($2, $3) |
16 字节 |
| o32 | $a0-$a3 ($4-$7) |
栈传递 | $v0, $v1 ($2, $3) |
8 字节 |
Note
$ra 不是普通“被调用者保存”寄存器:非叶子函数执行新的 jal 前必须先保存自己的返回地址。
栈帧结构 (n64)¶
| Text Only | |
|---|---|
函数调用流程¶
返回值寄存器¶
| 寄存器 | 用途 | 说明 |
|---|---|---|
| \(v0 (\)2) | 主要返回值 | 64位整数或指针 |
| \(v1 (\)3) | 辅助返回值 | 128位整数返回值的高64位;浮点返回值通常走浮点寄存器 |
Linux MIPS64 系统调用表¶
系统调用号 ABI 对比¶
MIPS64 支持三种 ABI,每种都有不同的系统调用号基址:
| ABI | 系统调用号基址 | 说明 |
|---|---|---|
| o32 | 4000 |
兼容 MIPS32 |
| n32 | 6000 |
32 位指针 + 64 位寄存器 |
| n64 | 5000 |
64 位 ABI |
常用系统调用号¶
n64 ABI 系统调用约定¶
n32 ABI 系统调用号¶
o32 ABI (MIPS32 兼容)¶
系统调用约定¶
不同 ABI 的系统调用约定略有差异:
| ABI | 调用号 | 参数 | 返回值 / errno | 错误指示 | 指令 |
|---|---|---|---|---|---|
| n64 | $v0 ($2) |
$a0-$a5 ($4-$9) |
$v0 |
$a3 != 0 表示错误 |
syscall |
| n32 | $v0 ($2) |
$a0-$a5 ($4-$9) |
$v0 |
$a3 != 0 表示错误 |
syscall |
| o32 | $v0 ($2) |
$a0-$a3,第 5-6 参数走栈 |
$v0 |
$a3 != 0 表示错误 |
syscall |
Note
出错时 $v0 通常为正 errno,不要按 x86/AArch64/RISC-V 的 -errno 模型判断。
系统调用示例(基本用法)¶
n64 ABI 示例¶
| GAS | |
|---|---|
o32 ABI 示例¶
| GAS | |
|---|---|
系统调用详解¶
系统调用寄存器约定¶
系统调用号寄存器¶
| 寄存器 | ABI | 说明 |
|---|---|---|
| \(v0 (\)2) | o32 | MIPS32兼容模式系统调用号 |
| \(v0 (\)2) | n32 | n32 ABI系统调用号 |
| \(v0 (\)2) | n64 | n64 ABI系统调用号 |
参数传递寄存器 (系统调用)¶
不同 ABI 的系统调用参数传递方式:
o32 ABI 系统调用¶
| GAS | |
|---|---|
n32 ABI 系统调用¶
| GAS | |
|---|---|
n64 ABI 系统调用¶
| GAS | |
|---|---|
系统调用返回值¶
| 寄存器 | 用途 | 说明 |
|---|---|---|
| \(v0 (\)2) | 返回值 / errno | 成功时为返回值;失败时通常为正 errno |
| \(a3 (\)7) | 错误指示 | Linux MIPS 各 ABI 中,非零表示错误 |
常用系统调用号对比¶
| 系统调用 | o32 | n32 | n64 | 参数 |
|---|---|---|---|---|
| read | 4003 | 6000 | 5000 | fd, buf, count |
| write | 4004 | 6001 | 5001 | fd, buf, count |
| open | 4005 | 6002 | 5002 | pathname, flags, mode |
| close | 4006 | 6003 | 5003 | fd |
| mmap | 4090 | 6009 | 5009 | addr, len, prot, flags, fd, offset |
| execve | 4011 | 6057 | 5057 | filename, argv, envp |
系统调用示例¶
完整的 write 系统调用 (n64)¶
系统调用错误处理¶
| GAS | |
|---|---|
指令集特性¶
64 位专用指令¶
MIPS64 在 MIPS32 基础上增加了 64 位操作指令:
| 指令 | 功能 | 示例 | 描述 |
|---|---|---|---|
| ld | 64 位加载 | ld $t0, 0($sp) |
从内存加载64位数据 |
| sd | 64 位存储 | sd $t0, 8($sp) |
向内存存储64位数据 |
| daddi | 64 位立即数加法 | daddi $t0, $t1, 100 |
64位有符号加法 |
| daddiu | 64 位无符号立即数加法 | daddiu $t0, $t1, 100 |
64位无符号加法 |
| daddu | 64 位无符号加法 | daddu $t0, $t1, $t2 |
64位寄存器加法 |
| dsubu | 64 位无符号减法 | dsubu $t0, $t1, $t2 |
64位寄存器减法 |
| dsll | 64 位逻辑左移 | dsll $t0, $t1, 16 |
64位数据左移 |
| dsrl | 64 位逻辑右移 | dsrl $t0, $t1, 8 |
64位数据右移 |
| dsra | 64 位算术右移 | dsra $t0, $t1, 4 |
64位算术右移 |
| dsllv | 64 位变量左移 | dsllv $t0, $t1, $t2 |
根据寄存器左移 |
| dsrlv | 64 位变量右移 | dsrlv $t0, $t1, $t2 |
根据寄存器右移 |
| dsrav | 64 位变量算术右移 | dsrav $t0, $t1, $t2 |
根据寄存器算术右移 |
| dmult | 64 位乘法 | dmult $t0, $t1 |
64位有符号乘法 |
| dmultu | 64 位无符号乘法 | dmultu $t0, $t1 |
64位无符号乘法 |
| ddiv | 64 位除法 | ddiv $t0, $t1 |
64位有符号除法 |
| ddivu | 64 位无符号除法 | ddivu $t0, $t1 |
64位无符号除法 |
兼容的 32 位指令¶
32 位指令在 64 位寄存器上执行时,结果会进行符号扩展:
| 指令 | 64位结果 | 示例 | 说明 |
|---|---|---|---|
| lw | 符号扩展到64位 | lw $t0, 0($sp) |
加载32位,符号扩展 |
| addiu | 符号扩展到64位 | addiu $t0, $t1, 100 |
32位加法,符号扩展 |
| sll | 符号扩展到64位 | sll $t0, $t1, 4 |
32位左移,符号扩展 |
| addu | 符号扩展到64位 | addu $t0, $t1, $t2 |
32位加法,符号扩展 |
地址计算与64位立即数加载¶
64位立即数加载技术¶
常用地址计算模式¶
指令格式与指令集合¶
指令格式¶
MIPS64 继承了 MIPS32 的三种指令格式,指令长度仍为 32 位:
R-Type (寄存器类型)¶
| Text Only | |
|---|---|
I-Type (立即数类型)¶
| Text Only | |
|---|---|
J-Type (跳转类型)¶
| Text Only | |
|---|---|
指令分类¶
算术运算指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| dadd | dadd rd, rs, rt | rd = rs + rt | dadd $t0, $t1, $t2 |
64位有符号加法 |
| daddu | daddu rd, rs, rt | rd = rs + rt | daddu $t0, $t1, $t2 |
64位无符号加法 |
| daddi | daddi rt, rs, imm | rt = rs + imm | daddi $t0, $t1, 100 |
64位立即数加法 |
| daddiu | daddiu rt, rs, imm | rt = rs + imm | daddiu $t0, $t1, 100 |
64位无符号立即数加法 |
| dsub | dsub rd, rs, rt | rd = rs - rt | dsub $t0, $t1, $t2 |
64位有符号减法 |
| dsubu | dsubu rd, rs, rt | rd = rs - rt | dsubu $t0, $t1, $t2 |
64位无符号减法 |
| dmult | dmult rs, rt | HI:LO = rs * rt | dmult $t0, $t1 |
64位有符号乘法 |
| dmultu | dmultu rs, rt | HI:LO = rs * rt | dmultu $t0, $t1 |
64位无符号乘法 |
| ddiv | ddiv rs, rt | LO=rs/rt, HI=rs%rt | ddiv $t0, $t1 |
64位有符号除法 |
| ddivu | ddivu rs, rt | LO=rs/rt, HI=rs%rt | ddivu $t0, $t1 |
64位无符号除法 |
| add | add rd, rs, rt | rd = rs + rt | add $t0, $t1, $t2 |
32位有符号加法(符号扩展) |
| addu | addu rd, rs, rt | rd = rs + rt | addu $t0, $t1, $t2 |
32位无符号加法(符号扩展) |
| addi | addi rt, rs, imm | rt = rs + imm | addi $t0, $t1, 100 |
32位立即数加法(符号扩展) |
| addiu | addiu rt, rs, imm | rt = rs + imm | addiu $t0, $t1, 100 |
32位无符号立即数加法(符号扩展) |
| sub | sub rd, rs, rt | rd = rs - rt | sub $t0, $t1, $t2 |
32位有符号减法(符号扩展) |
| subu | subu rd, rs, rt | rd = rs - rt | subu $t0, $t1, $t2 |
32位无符号减法(符号扩展) |
| mult | mult rs, rt | HI:LO = rs * rt | mult $t0, $t1 |
32位有符号乘法 |
| multu | multu rs, rt | HI:LO = rs * rt | multu $t0, $t1 |
32位无符号乘法 |
| div | div rs, rt | LO=rs/rt, HI=rs%rt | div $t0, $t1 |
32位有符号除法 |
| divu | divu rs, rt | LO=rs/rt, HI=rs%rt | divu $t0, $t1 |
32位无符号除法 |
逻辑运算指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| and | and rd, rs, rt | rd = rs & rt | and $t0, $t1, $t2 |
64位按位与 |
| andi | andi rt, rs, imm | rt = rs & imm | andi $t0, $t1, 0xFF |
立即数按位与 |
| or | or rd, rs, rt | rd = rs | rt | or $t0, $t1, $t2 |
64位按位或 |
| ori | ori rt, rs, imm | rt = rs | imm | ori $t0, $t1, 0xFF |
立即数按位或 |
| xor | xor rd, rs, rt | rd = rs ^ rt | xor $t0, $t1, $t2 |
64位按位异或 |
| xori | xori rt, rs, imm | rt = rs ^ imm | xori $t0, $t1, 0xFF |
立即数按位异或 |
| nor | nor rd, rs, rt | rd = ~(rs | rt) | nor $t0, $t1, $t2 |
64位按位或非 |
移位指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| dsll | dsll rd, rt, shamt | rd = rt << shamt | dsll $t0, $t1, 2 |
64位逻辑左移 |
| dsllv | dsllv rd, rt, rs | rd = rt << rs | dsllv $t0, $t1, $t2 |
64位变量逻辑左移 |
| dsrl | dsrl rd, rt, shamt | rd = rt >> shamt | dsrl $t0, $t1, 2 |
64位逻辑右移 |
| dsrlv | dsrlv rd, rt, rs | rd = rt >> rs | dsrlv $t0, $t1, $t2 |
64位变量逻辑右移 |
| dsra | dsra rd, rt, shamt | rd = rt >> shamt | dsra $t0, $t1, 2 |
64位算术右移 |
| dsrav | dsrav rd, rt, rs | rd = rt >> rs | dsrav $t0, $t1, $t2 |
64位变量算术右移 |
| dsll32 | dsll32 rd, rt, shamt | rd = rt << (shamt+32) | dsll32 $t0, $t1, 0 |
64位左移32+shamt位 |
| dsrl32 | dsrl32 rd, rt, shamt | rd = rt >> (shamt+32) | dsrl32 $t0, $t1, 0 |
64位右移32+shamt位 |
| dsra32 | dsra32 rd, rt, shamt | rd = rt >> (shamt+32) | dsra32 $t0, $t1, 0 |
64位算术右移32+shamt位 |
| sll | sll rd, rt, shamt | rd = rt << shamt | sll $t0, $t1, 2 |
32位逻辑左移(符号扩展) |
| sllv | sllv rd, rt, rs | rd = rt << rs | sllv $t0, $t1, $t2 |
32位变量逻辑左移(符号扩展) |
| srl | srl rd, rt, shamt | rd = rt >> shamt | srl $t0, $t1, 2 |
32位逻辑右移(符号扩展) |
| srlv | srlv rd, rt, rs | rd = rt >> rs | srlv $t0, $t1, $t2 |
32位变量逻辑右移(符号扩展) |
| sra | sra rd, rt, shamt | rd = rt >> shamt | sra $t0, $t1, 2 |
32位算术右移(符号扩展) |
| srav | srav rd, rt, rs | rd = rt >> rs | srav $t0, $t1, $t2 |
32位变量算术右移(符号扩展) |
数据传输指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| ld | ld rt, offset(rs) | rt = Memory[rs+offset] | ld $t0, 0($sp) |
加载64位字 |
| lw | lw rt, offset(rs) | rt = Memory[rs+offset] | lw $t0, 0($sp) |
加载32位字(符号扩展) |
| lwu | lwu rt, offset(rs) | rt = Memory[rs+offset] | lwu $t0, 0($sp) |
加载32位字(零扩展) |
| lh | lh rt, offset(rs) | rt = Memory[rs+offset] | lh $t0, 0($sp) |
加载16位半字(有符号) |
| lhu | lhu rt, offset(rs) | rt = Memory[rs+offset] | lhu $t0, 0($sp) |
加载16位半字(无符号) |
| lb | lb rt, offset(rs) | rt = Memory[rs+offset] | lb $t0, 0($sp) |
加载8位字节(有符号) |
| lbu | lbu rt, offset(rs) | rt = Memory[rs+offset] | lbu $t0, 0($sp) |
加载8位字节(无符号) |
| sd | sd rt, offset(rs) | Memory[rs+offset] = rt | sd $t0, 0($sp) |
存储64位字 |
| sw | sw rt, offset(rs) | Memory[rs+offset] = rt | sw $t0, 0($sp) |
存储32位字 |
| sh | sh rt, offset(rs) | Memory[rs+offset] = rt | sh $t0, 0($sp) |
存储16位半字 |
| sb | sb rt, offset(rs) | Memory[rs+offset] = rt | sb $t0, 0($sp) |
存储8位字节 |
立即数加载指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| lui | lui rt, imm | rt = imm << 16 | lui $t0, 0x1234 |
加载立即数到高16位 |
| li | li rt, imm | rt = imm | li $t0, 100 |
加载立即数(伪指令) |
| la | la rt, label | rt = &label | la $t0, string |
加载地址(伪指令) |
| dla | dla rt, label | rt = &label | dla $t0, string |
加载64位地址(伪指令) |
| dli | dli rt, imm | rt = imm | dli $t0, 0x123456789ABCDEF0 |
加载64位立即数(伪指令) |
比较指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| slt | slt rd, rs, rt | rd = (rs < rt) ? 1 : 0 | slt $t0, $t1, $t2 |
64位有符号小于设置 |
| sltu | sltu rd, rs, rt | rd = (rs < rt) ? 1 : 0 | sltu $t0, $t1, $t2 |
64位无符号小于设置 |
| slti | slti rt, rs, imm | rt = (rs < imm) ? 1 : 0 | slti $t0, $t1, 100 |
立即数64位有符号小于设置 |
| sltiu | sltiu rt, rs, imm | rt = (rs < imm) ? 1 : 0 | sltiu $t0, $t1, 100 |
立即数64位无符号小于设置 |
分支跳转指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| beq | beq rs, rt, label | if (rs == rt) PC = label | beq $t0, $t1, loop |
相等则分支 |
| bne | bne rs, rt, label | if (rs != rt) PC = label | bne $t0, $t1, end |
不相等则分支 |
| bgtz | bgtz rs, label | if (rs > 0) PC = label | bgtz $t0, positive |
大于0则分支 |
| blez | blez rs, label | if (rs <= 0) PC = label | blez $t0, nonpos |
小于等于0则分支 |
| bltz | bltz rs, label | if (rs < 0) PC = label | bltz $t0, negative |
小于0则分支 |
| bgez | bgez rs, label | if (rs >= 0) PC = label | bgez $t0, nonneg |
大于等于0则分支 |
| j | j target | PC = target | j main |
无条件跳转 |
| jal | jal target | $ra = PC+8; PC = target | jal function |
跳转并链接;返回地址跳过延迟槽 |
| jr | jr rs | PC = rs | jr $ra |
寄存器跳转 |
| jalr | jalr rd, rs | rd = PC+8; PC = rs | jalr $ra, $t0 |
寄存器跳转并链接;返回地址跳过延迟槽 |
特殊指令¶
| 指令 | 格式 | 含义 | 示例 | 描述 |
|---|---|---|---|---|
| nop | nop | 空操作 | nop |
无操作(sll \(0,\)0,0) |
| move | move rd, rs | rd = rs | move $t0, $t1 |
数据移动(伪指令) |
| mfhi | mfhi rd | rd = HI | mfhi $t0 |
从HI寄存器移动 |
| mflo | mflo rd | rd = LO | mflo $t0 |
从LO寄存器移动 |
| mthi | mthi rs | HI = rs | mthi $t0 |
移动到HI寄存器 |
| mtlo | mtlo rs | LO = rs | mtlo $t0 |
移动到LO寄存器 |
| syscall | syscall | 系统调用 | syscall |
触发系统调用 |
| break | break | 断点异常 | break |
触发断点异常 |
寻址模式详解¶
立即数寻址¶
| GAS | |
|---|---|
寄存器寻址¶
| GAS | |
|---|---|
基址加偏移寻址¶
| GAS | |
|---|---|
PC相对寻址(分支指令)¶
绝对寻址(跳转指令)¶
数据类型支持¶
MIPS64支持多种数据类型的操作:
数据类型表¶
| 数据类型 | 大小 | 后缀 | 有符号后缀 | 描述 |
|---|---|---|---|---|
| 字节 (Byte) | 8位 | b | b/bu | 有符号/无符号字节 |
| 半字 (Halfword) | 16位 | h | h/hu | 有符号/无符号半字 |
| 字 (Word) | 32位 | w | w/wu | 32位数据 |
| 双字 (Doubleword) | 64位 | d | 无 | 64位数据 |
加载指令示例¶
| GAS | |
|---|---|
存储指令示例¶
| GAS | |
|---|---|
数据类型范围¶
| 类型 | 范围 | 用途 |
|---|---|---|
| 无符号字节 | 0 ~ 255 | 字符、小整数 |
| 有符号字节 | -128 ~ 127 | 有符号小整数 |
| 无符号半字 | 0 ~ 65535 | 较大整数、Unicode |
| 有符号半字 | -32768 ~ 32767 | 有符号整数 |
| 无符号字 | 0 ~ 4294967295 | 32位整数、地址(o32) |
| 有符号字 | -2147483648 ~ 2147483647 | 32位有符号整数 |
| 无符号双字 | 0 ~ 18446744073709551615 | 64位整数、地址 |
| 有符号双字 | -9223372036854775808 ~ 9223372036854775807 | 64位有符号整数 |
常用编程模式¶
延迟槽提示
为了突出控制流,下面部分示例按“易读伪汇编”书写。若在 .set noreorder、shellcode 或手写 gadget 中使用,请为每条分支/跳转后的延迟槽显式填入 nop 或一条确定安全的指令。
循环结构¶
条件判断¶
函数调用模板¶
数组操作¶
位操作技巧¶
内存对齐和优化¶
延迟槽 (Delay Slot)¶
MIPS64架构继承了MIPS的分支延迟槽特性:
内存模型与字节序特性¶
字节序示例¶
| Text Only | |
|---|---|
内存布局¶
实际编程示例¶
简单的Hello World程序¶
函数调用汇编示例¶
| C | |
|---|---|
对应的汇编代码:
字符串处理示例¶
数组操作示例¶
递归函数示例¶
完整的程序示例¶
这些示例展示了MIPS64汇编编程的核心概念,包括:
- 系统调用:使用n64 ABI进行系统调用
- 函数调用:正确的栈管理和参数传递
- 64位运算:使用64位指令处理长整型数据
- 字符串处理:基本的字符串操作函数
- 数组操作:遍历和计算数组元素
- 递归:栈管理和递归调用
- 完整程序:数据段、文本段和程序结构