c - 如何从汇编代码调用 C 函数

标签 c linker x86 bootloader osdev

我在从汇编代码转换为 C 时遇到问题。我以某种方式加载了我的内核,方法是将其放置在第二阶段引导加载程序中的填充之后,并增加了第一阶段引导加载程序中要加载的扇区数量。正如您在这里看到的:

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:

;----------------------------------------------;
;
; 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:

;----------------------------------------------;
;
; 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

内核.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

正如你所看到的,我已经从引导加载程序加载了内核,现在在汇编中一切都很好,但我的问题出现了:如何使 kernel.asm 调用像 kernelc_main 这样的 C 函数组装?

最佳答案

您可以尝试这样做:

用C语言创建一个类

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

上面的代码在 C 中创建了一个名为“kmain”的类

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

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”用于在程序集中包含外部函数或类。 然后就可以使用普通的‘call’来调用内核了。

希望这个答案有用, 谢谢

关于c - 如何从汇编代码调用 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39950084/

相关文章:

linux - 如何在 perf 中解析 "not counted"?

c - 在帕特里夏/基数树上插入单词时遇到问题

c++ - Clang 看不到 strdup 和其他一些函数

ios - 创建iOS框架时如何解决类名冲突?

ios - Objective-C 中的常量和 "duplicate symbol"链接器错误

x86 - 从 GRUB2 多重引导信息结构中获取总可用 RAM

c++ - 隐式异常处理

c - 严格的别名规则 uint8_t 缓冲区到结构

c - 我使用 fread 在 BMP 上读取 infoheader 时出现段错误。我该如何解决这个问题?

c - 对 `pow' 的 undefined reference - makefile