Linux kernel-汇编基础

mov

ASSEMABLE            C LANGUAGE
movl %eax,%edx     edx = eax;                --->register mode
movl $0x123,%edx   edx = 0x123;              --->immediate (0x123 is a value)
movl 0x123,%edx    edx = *(int32_t *)0x123   --->direct (0x123 is memory address)
movl (%ebx),%edx   edx = *(int32_t *)ebx     --->indirect (fetch address from register ebx, and fetch the value from the address )
movl 4(%ebx),%edx  edx = *(int32_t *)(ebx+4) --->displaced (address from register and offset)

movb
movw
movl
movq
b,w,l,q:  8bit, 16bit, 32bit, 64bit

几个重要指令pushl, popl, call, ret

pushl %eax  ==  subl $4, %esp
                movl %eax, (%esp)

popl %eax  ==  movl (%esp), %eax
               addl $4, %esp

call 0x12345 == pushl %eip(*)
                movl $0x12345, %eip(*)

ret          == popl %eip(*)                                 
push - 栈顶地址减少8个字节(64位,如果32位就是4个字节)
pop - 栈顶地址增加8个字节(64位)

cs寄存器: 代码段寄存器
cs:rip - 总是指向下一条指令地址

call: 将当前cs:rip 的值压入栈顶, cs:rip 指向的是被调用函数的入口地址
ret: 从栈顶弹出原来保存在这里的cs:rip的值,放到cs:rip 

函数调用关系
//建立被调用者函数的堆栈框架
pushl %ebp   //我的理解,在这里,默认%esp就是比%ebp要加1的
movl %esp, %ebp

///被调用函数的函数体
///do sth
///

//拆除被调用者的堆栈框架
movl %ebp, %esp
popl %ebp
ret

分析case

...
pushl $8
movl  %esp, %ebp
subl  $4, %esp
movl  $8, (%esp)
...
#cat hello.c
#include <stdio.h>

int g(int x)
{
	return x + 3;
}

int f(int x)
{
	return g(x);
}

int main(void)
{
	return f(8) + 1;
}
#gcc -S -o hello.s hello.c
#cat  hello.s
g:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	%edi, -4(%rbp)
	movl	-4(%rbp), %eax
	addl	$3, %eax
	popq	%rbp
	ret
f:
	pushq	%rbp
	movq	%rsp, %rbp
	subq	$8, %rsp
	movl	%edi, -4(%rbp)
	movl	-4(%rbp), %eax
	movl	%eax, %edi
	call	g
	leave
	ret
main:
	pushq	%rbp
	movq	%rsp, %rbp
	movl	$8, %edi
	call	f
	addl	$1, %eax
	popq	%rbp
	ret
posted @ 2018-11-09 13:49  苏小北1024  阅读(497)  评论(0编辑  收藏  举报