1. 程式人生 > >Linux kernel-彙編基礎

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