学海拾遗:汇编语言实验

学海拾遗:汇编语言实验

1.简单汇编指令回顾

指令解释说明
movl %eax, %edxedx = eaxregister mode
movl $0x123, %edxedx = 0x123immediate
movl 0x123, %edxedx = *(int32_t*)0x123direct
movl (%ebp), %edxedx = *(int32_t*)ebpindirect
movl 4(%ebp), %edxedx = *(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指令:

  1. 将eip中的下一条指令的地址A保存在栈顶

  2. 设置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文件删除所有以点开头的内容,剩下来的就纯汇编代码

zbb@ubuntu:~/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.
zbb@ubuntu:~/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


具体执行过程见下图:

ex_01
ex_02
ex_03

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Erice_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值