如何从汇编代码调用C函数 [英] How to call a C function from Assembly code
问题描述
从汇编代码转换为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屋!