学海拾遗:汇编语言实验
学海拾遗:汇编语言实验
1.简单汇编指令回顾
指令 | 解释 | 说明 |
---|---|---|
movl %eax, %edx | edx = eax | register mode |
movl $0x123, %edx | edx = 0x123 | immediate |
movl 0x123, %edx | edx = *(int32_t*)0x123 | direct |
movl (%ebp), %edx | edx = *(int32_t*)ebp | indirect |
movl 4(%ebp), %edx | edx = *(int32_t*)(ebp+4) | displaced |
b, w, l, q分别代表8位,16位, 32位, 64位
寄存器模式:以%开头的寄存器标示符
立即数:以$开头的数值
直接寻址:直接访问一个指定的内存地址的数据
间接寻址:将寄存器的值作为一个内存地址来访问内存
变址寻址:在间接寻址之时改变寄存器的数值
Example instruction
函数调用堆栈是理解C代码在CPU上执行的关键
pushl %eax
subl $4, %esp
movl %eax, (%esp)
popl %eax
movl (%esp), %eax
addl $4, %esp
call 0x12345
pushl %eip(*)
movl $0x12345, %eip(*)
(*)表示eip寄存器不能被直接修改, 只能通过特殊指令间接修改
call指令:
将eip中的下一条指令的地址A保存在栈顶
设置eip指向被调用程序代码开始处
ret
popl %eip(*)
enter
pushl %ebp
movl %esp, %ebp
leave
movl %ebp, %esp
popl %ebp
2. 相关寄存器
计算机三大法宝:存储程序计算机、函数调用堆栈和中断机制
堆栈: C语言程序运行时必须的一个记录调用路径和参数的空间
函数调用框架
传递参数
保存返回地址
提供局部变量空间
C语言编译器对堆栈的使用有一套的规则
了解堆栈存在的目的和编译器对堆栈的使用的规则是理解操作系统一些关键性代码的基础
堆栈相关的寄存器
- esp, 堆栈指针(Stack pointer)
- ebp, 基址指针 (base pointer)
堆栈操作
- push 栈顶地址减少4个字节, 32位
- pop 栈顶地址增加4个字节
ebp在C语言中用作记录当前函数调用基址
其他关键寄存器
cs: eip: 总是指向下一条的指令地址
- 顺序执行:总是指向地址连续的下一条指令
- 跳转/分支:执行这样的指令的时候,cs:eip的值会根据程序的需要被修改
- call:将当前cs:eip的值压入栈顶,cs: eip指向被调用函数的入口地址
- ret: 从栈顶弹出原来保存在这里的cs:eip的值,放入cs:eip中
中断机制
3.C语言源码
// main.c
#include <stdio.h>
int g(int x)
{
return x+5;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(8) + 10;
}
4.汇编代码
gcc -S main.c -o main.s -m32
-m32编译选项报错时,Ubuntu下执行sudo apt-get install libc6
打开main.s文件删除所有以点开头的内容,剩下来的就纯汇编代码
aaa@qq.com:~/ProC$ gcc -S main.c -o main.s -m32
In file included from /usr/include/stdio.h:27:0,
from main.c:1:
/usr/include/features.h:367:25: fatal error: sys/cdefs.h: 没有那个文件或目录
compilation terminated.
aaa@qq.com:~/ProC$ sudo apt-get install libc6
g:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $5, %eax
popl %ebp
ret
f:
pushl %ebp
movl %esp, %ebp
pushl 8(%ebp)
call g
addl $4, %esp
leave
ret
main:
pushl %ebp
movl %esp, %ebp
pushl $8
call f
addl $4, %esp
addl $10, %eax
leave
ret
函数的返回值默认使用eax寄存器存储返回给上一级函数
call f ==> pushl eip; movl f eip
具体执行过程见下图:
上一篇: 关于设置及读取cookie的有关问题
下一篇: PHP基础问题-配置虚拟目录