linux 0.12之head.s跳转到main.c的说明

因为只有引导代码中使用了as86的编译器,linux0.12其他汇编都是基于GNU as汇编的,这是背景。 head.s是在gnu as下编译的,使用的是AT&T汇编模式。主要完成一些GDT的初始化,,然后跳转到main.c函数执行,这两者如何顺利调用的,今天研究一下。 下面是linus给出的关键源码:

after_page_tables: pushl $0 # These are the parameters to main 🙂 pushl $0 pushl $0 pushl $L6 # return address for main, if it decides to. pushl $main jmp setup_pagingL6: jmp L6 # main should never return here, but# just in case, we know what happens./* * Setup_paging * * This routine sets up paging by setting the page bit * in cr0. The page tables are set up, identity-mapping * MB. The pager assumes that no illegal * addresses are produced (ie >4Mb on a 4Mb machine). * * NOTE! Although all physical memory should be identity * mapped by this routine, only the kernel page functions * use the >1Mb addresses directly. All “normal” functions * use just data space, which * will be mapped to some other place – mm keeps track of * that. * * For those with more memory than 16 Mb – tough luck. I’ve * not got it, why should you 🙂 The source is here. Change * it. (Seriously – it shouldn’t be too difficult. Mostly * change Mb, as my machine * even cannot be extended past that (ok, but it was cheap 🙂 * I’ve tried to show which constants to change by having * some kind of marker at them (search for “16Mb”), but I * won’t guarantee that’s all 🙁 ) */.align 2setup_paging: movl $1024*5,%ecx /* 5 pages – pg_dir+4 page tables */ xorl %eax,%eax xorl %edi,%edi /* pg_dir */ cld;rep;stosl movl $pg0+7,pg_dir/* set present bit/user r/w */ movl $pg1+7,pg_dir+4 /* ——— ” ” ——— */ movl $pg2+7,pg_dir+8 /* ——— ” ” ——— */ movl $pg3+7,pg_dir+12 /* ——— ” ” ——— */ movl $pg3+4092,%edi movl $0xfff007,%eax /* 16Mb – 4096 + 7 (r/w user,p) */ std1: stosl /* fill pages backwards – more efficient 🙂 */ subl $0x1000,%eax jge 1b xorl %eax,%eax /* pg_dir */ movl %eax,%cr3 /* cr3 – page directory start */ movl %cr0,%eax orl $0x80000000,%eax movl %eax,%cr0 /* set paging (PG) bit */ ret/* this also flushes prefetch-queue */

setup_paging的实现这次不研究,重点在于main函数。 首先看看c代码的调用模式 依旧看一个小c代码的汇编

void swap(){ int c; c=*a; *a=*b; *b=c;}int main(){ int a,b; a=1,b=2; swap(&a,&b); return a+b;}

在mingw32下gcc -Wall -S -o exch.s exch.c 汇编代码为

.file “exch.c” .text .globl _swap .def _swap; .scl 2; .type 32; .endef_swap:LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $16, %esp movl 8(%ebp), %eax movl (%eax), %eax movl %eax, -4(%ebp) movl 12(%ebp), %eax movl (%eax), %edx movl 8(%ebp), %eax movl %edx, (%eax) movl 12(%ebp), %eax movl -4(%ebp), %edx movl %edx, (%eax) leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endprocLFE0: .def ___main; .scl 2; .type 32; .endef .globl _main .def _main; .scl 2; .type 32; .endef_main:LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $32, %esp call ___main movl $1, 28(%esp) movl $2, 24(%esp) leal 24(%esp), %eax movl %eax, 4(%esp) leal 28(%esp), %eax movl %eax, (%esp) call _swap movl 28(%esp), %edx movl 24(%esp), %eax addl %edx, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endprocLFE1:父母养我不容易,我在学校争口气。

linux 0.12之head.s跳转到main.c的说明

相关文章:

你感兴趣的文章:

标签云: