如何从汇编代码调用C函数 [英] How to call a C function from Assembly code

查看:80
本文介绍了如何从汇编代码调用C函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从汇编代码转换为C时遇到了麻烦.通过某种方式将内核放置在第二阶段引导程序的填充区中,并增加了要在第一阶段引导程序中加载的扇区数,从而以某种方式加载了内核.如您所见:

I am having trouble converting from Assembly code to C. I have somehow loaded my kernel by placing it after the padding in the second stage bootloader and increasing the number of sectors to load in the first stage bootloader. As you can see here:

boot1.asm:

boot1.asm:

;----------------------------------------------;
;
; The BoneOS Stage 1 Bootloader
; -----------------------------
;
;
; Contributors : @amanuel2
;
;
;----------------------------------------------;

[ORG 0x7c00]   ;We Will Set Registers to point to 0x7C00 Later

[  BITS  16  ]; 16 bits real mode

JMP main_first ; Jump to Main Function of the Bootloader

 ;/////////////////////////////////////////////
 ;  Include Files
 ;////////////////////////////////////////////

     ;--------------------------------------
     ;      STDIO.h
     ; I/O Functions. Such as printfb which 
     ; prints a string to the screen.
     ; 
     ; @functions:
     ;     printfb ARGS: <SI = String>
     ;     printfbln ARGS: <SI = String>
     ;     clearscreen
     ;     print_new_line
     ;--------------------------------------
     %include "stdiobios.inc" 

;-----------------------------------------------
;-----------------------------------------------
;  Label "Function" Main Declarations :)
; 
;   Bone Project
;----------------------------------------------




;----------------------------------------------
;  Label "Variable" Main Declaractions :)
;
;  Bone Project
;----------------------------------------------

FirstMessageExecution : db "Stage 1 Bootloader Executing .  .  .", 0
SECONDSTAGEXECUTION : db "Stage 2 Bootloader Executing . . .",0

;align 4
gdt_start:                              ; Start of global descriptor table
    gdt_null:                           ; Null descriptor chunk
        dd 0x00
        dd 0x00
    gdt_code:                           ; Code descriptor chunk
        dw 0xFFFF
        dw 0x0000
        db 0x00
        db 0x9A
        db 0xCF
        db 0x00
    gdt_data:                           ; Data descriptor chunk
        dw 0xFFFF
        dw 0x0000
        db 0x00
        db 0x92
        db 0xCF
        db 0x00
    gdt_end:                            ; Bottom of table
gdt_descriptor:                         ; Table descriptor
    dw gdt_end - gdt_start - 1          ; Size of table
    dd gdt_start                        ; Start point of table

gdt_codeSeg equ gdt_code - gdt_start    ; Offset of code segment from start
gdt_dataSeg equ gdt_data - gdt_start    ; Offset of data segment from start

    a20wait:
        in   al,0x64 ; input from 0x64 port, goes to al register
        test    al,2 ; compares al register with 2
        jnz     a20wait ; If it is zero loop again
        ret


    a20wait2:
        in      al,0x64 ; input from 0x64 port, goes to al register
        test    al,1 ; compares al register with 2
        jz      a20wait2 ; If it is zero loop again
        ret 

                                                ;-----                              -----;
                                                ;-----      Main Function           -----;
                                                ;-----                              -----;


main_first:  
                CLI ; Clear Interupts Before Manupulating Segments

                ;------------------------------
                ; Bootloader Repsonsibility To 
                ; Setup Registers to point to our 
                ; Segments (Except Code Segment)
                ;
                ;------------------------------

SEGMENTS:               
                ; 0x0000 : 0x7c00 
                xor ax,ax ; 0x0000
                MOV ds,ax ; Data Segment
                MOV es,ax ; Extra Segment (E)
                MOV fs,ax ; Extra Extra Segment (F Comes after E)
                MOV gs,ax ; Extra Extra Extra Segment (G Comes after F)

                ;-------------------------------
                ;--Setting Up The Stack
                ;--Stack Grows Downwards
                ;-------------------------------

STACK:              
                MOV ax,0
                MOV ss,ax ; Cant Directly MOVe to Stack Segment
                MOV sp,0xFFFE ; Start Stackpointer from the top, growing downward


                STI ; Restore Interupts
                MOV     ax, 0x3
                INT     0x10    

SECONDSTAGE:        
                MOV si, FirstMessageExecution
                CALL printfbln      

                ; Load stage 2 to memory.
                MOV ah, 0x02
                ; Number of sectors to read.
                MOV al, 20
                ; This may not be necessary as many BIOS set it up as an initial state.
                MOV dl, 0x00
                ; Cylinder number.
                MOV ch, 0
                ; Head number.
                MOV dh, 0
                ; Starting sector number 2 because 1 was already loaded.
                MOV cl, 2
                ; Where to load to.
                MOV bx, stage2
                INT 0x13

                JMP stage2

                ; Magic bytes.    
                times ((0x200 - 2) - ($ - $$)) db 0x00
                dw 0xAA55


;--------------------------------------
;       load2.asm
;   Second Stage Bootloader
;   Which then loads the kernel
;   in 32 bit protected mode!
;   
;--------------------------------------
%include "boot2.asm"

boot2.asm:

boot2.asm:

;----------------------------------------------;
;
; The BoneOS Stage 2 Bootloader
; -----------------------------
;
;
; Contributors : @amanuel2
;
;
;----------------------------------------------;



  stage2:

    MOV si, SECONDSTAGEXECUTION
    CALL printfbln  


    ; enable A20 gate
    enable_A20: ; Enabling A20 Line For Full Memory
            cli ; Stop Interupts before doing so

            call    a20wait ; a20wait call
            mov     al,0xAD ; Send 0xAD Command to al register
            out     0x64,al ; Send command 0xad (disable keyboard).

            call    a20wait ; When controller ready for command
            mov     al,0xD0 ; Send 0xD0 Command to al register
            out     0x64,al ; Send command 0xd0 (read from input)

            call    a20wait2 ; When controller ready for command
            in      al,0x60 ; Read input from keyboard
            push    eax ; Save Input by pushing to stack

            call    a20wait ; When controller ready for command
            mov     al,0xD1 ; mov 0xD1 Command to al register
            out     0x64,al ; Set command 0xd1 (write to output)

            call    a20wait ; When controller ready for command
            pop     eax ; Pop Input from Keyboard
            or      al,2 ; Mov 0xD3 to al register
            out     0x60,al ; Set Command 0xD3

            call    a20wait ; When controller ready for command
            mov     al,0xAE ; Mov Command 0xAE To al register
            out     0x64,al ; Write command 0xae (enable keyboard)

            call    a20wait ; When controller ready for command
            sti ; Enable Interrupts after enabling A20 Line


    ;load a GDT
    ; enter pmode
    loadgdt:
        cli             ; disable int
        LGDT [gdt_descriptor]                   ; Load global descriptor table for protected mode

        mov EAX, CR0                            ; Move CR0 to GP register
        or EAX, 0x1                             ; Set first bit to switch to protected mode
        mov CR0, EAX                            ; Update CR0 from GP register to complete switch



        ;JMP gdt_codeSeg:start32                 ; Jump to start of 32-bit code
        jmp 0x08:stage3 ; go to 32-bit code

        %include "boot3.asm"


    times ((0x400) - ($ - $$)) db 0x00

    %include "kernel.asm"

boot3.asm:

boot3.asm:

;----------------------------------------------;
;
; The BoneOS Bootloader Third Stage Bootloader
; ------------------------------
;
;
; Contributors : @amanuel2
;
;
;----------------------------------------------;

%include "stdio32boot.inc"

[BITS 32]

        stage3:
          ; set segment registers
          mov ax, 0x10
          mov ds, ax
          mov ss, ax

          mov esp, 0x090000 ; set up stack pointer

          push 'A'
          call puts32char
          add esp, 4
             jmp 0x08:k_main
            cli
            loopend:                ;Infinite loop when finished
                hlt
          jmp loopend

          cli
          hlt

kernel.asm:

kernel.asm:

 ;ORG 0x9000
BITS 32

k_main:
    mov byte [0xB8000], 88
    mov byte [0xB8000+1], 0x1B


    mov byte [0xB8000+4], 89
    mov byte [0xB8000+5], 0x1B
    cli
    hlt

如您所见,我已经从引导加载程序中加载了内核,现在在Assembly中一切都很好,但是我的问题出现了:如何使kernel.asm从C调用 kernelc_main 这样的C函数组装吗?

As you can see, I have the kernel loaded from bootloader, and it's all good in Assembly now, but my question arises: How do I make kernel.asm call a C function like kernelc_main from Assembly?

推荐答案

您可以尝试执行以下操作:

You can try doing this:

在C语言中创建一个类

void kmain()
{
//Do here.....
}

上面的代码在C语言中创建了一个名为"kmain"的类

This above code creates a class called 'kmain' in C

现在,在您的汇编代码中,

Now, in your assembly code,

ORG 0x9000
BITS 32
extern kmain
k_main:
    mov byte [0xB8000], 88
    mov byte [0xB8000+1], 0x1B


    mov byte [0xB8000+4], 89
    mov byte [0xB8000+5], 0x1B
    call kmain
    cli
    hlt

语法"extern"用于在汇编中包括外部函数或类.然后,您可以使用普通的调用"来调用内核.

The syntax 'extern' is used to include an external function or class in assembly. Then you can use normal 'call' to call the kernel.

希望这个答案会有用,谢谢

Hope this answer would be useful, Thanks

这篇关于如何从汇编代码调用C函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆