我正在使用包含C语言和汇编代码的混合代码在bootloader上创建简单的计算器应用程序。
我的C语言代码是(addasm.c): #include
int main() {
bootmain();
return 0 ;
}
int bootmain()
{
int arg1, arg2, add, sub, mul, quo, rem ;
printf( "Enter two integer numbers : " );
scanf( "%d%d", &arg1, &arg2 );
/* Perform Addition, Subtraction, Multiplication & Division */
__asm__ ( "addl %%ebx, %%eax;" : "=a" (add) : "a" (arg1) , "b" (arg2) );
__asm__ ( "subl %%ebx, %%eax;" : "=a" (sub) : "a" (arg1) , "b" (arg2) );
__asm__ ( "imull %%ebx, %%eax;" : "=a" (mul) : "a" (arg1) , "b" (arg2) );
__asm__ ( "movl $0x0, %%edx;"
"movl %2, %%eax;"
"movl %3, %%ebx;"
"idivl %%ebx;" : "=a" (quo), "=d" (rem) : "g" (arg1), "g" (arg2) );
printf( "%d + %d = %d\n", arg1, arg2, add );
printf( "%d - %d = %d\n", arg1, arg2, sub );
printf( "%d * %d = %d\n", arg1, arg2, mul );
printf( "%d / %d = %d\n", arg1, arg2, quo );
printf( "%d %% %d = %d\n", arg1, arg2, rem );
return 0;
}
我在C中创建了bootmain()函数,我需要在汇编代码中使用它。
我的汇编代码(ccode.asm)是:
[BITS 16] ; 16 bit code generation
[ORG 0x7C00] ; ORGin location is 7C00
extern bootmain
;Main program
main: ; Main program label
call bootmain
; End matter
times 510-($-$$) db 0 ; Fill the rest of the sector with zeros
dw 0xAA55 ; Boot signature
现在我正在编译这个
nasm -f elf -o main.o ccode.asm #assemble our asm file
但它给了我ORG关键字的错误,它是未定义的关键字。
如果我将删除此关键字,那么它将为我提供无错输出。
删除ORG关键字后,我正在编译:
nasm -f elf -o main.o ccode.asm #assemble our asm file
gcc addasm.c main.o -o add_asm #compile and link in one step
./add_asm
所以我使用这个最终的add_asm文件,并通过使用磁盘资源管理器放置此add_asm文件使我的USB驱动器可启动。 但在启动时它显示消息:缺少操作系统 这是在Assembly文件中不使用ORG的问题。 这主要是我使用NASM的ELF问题。但是对于外部C函数和EXTERN关键字,我需要使用ELF。
ORG的替代代码是:
[Bits 16]
extern bootmain
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
call bootmain
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
times 510-($-$$) db 0; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC boot signature
但它也不起作用......它在启动时给出了与“缺少操作系统”相同的错误。
有没有其他方法在程序集文件(* .asm)中包含C函数? 我被困在这里。如果有任何建议请给我。 谢谢。
答案 0 :(得分:1)
你无法将普通的C程序变成这样的引导加载程序。
引导加载程序运行的环境与普通可执行文件明显不同。特别是,它不包含您可以链接的C库(或者,就此而言,根本就是任何链接器!),因此除非您链接,否则printf()
和scanf()
等函数不可用适当的版本,你没有做。
您正在将程序编译为32位可执行文件。 x86系统以16位模式启动。切换到该模式时必须进行大量的初始化,这里没有任何一个。
您是将程序编译为Linux ELF(或可能是Windows PE?)可执行文件。这不是引导加载程序的正确格式。