主世界 2021-06-25 21:57 采纳率: 50%
浏览 6

汇编的问题,BUILDER对机器码的合成问题

我想自己开发一个操作系统,在MBR部分由BUILDER来合成,

jmp部分我直接往盘里写jmp short 0x5a nop的机器玛:0xeb,0x5a,0x90

然后跳过信息部分

填充(420-64)字节的启动代码,由mbr_boot.bin直接提供.

最后填充0x55,0xaa.

但是启动不起来.

我的思路有问题吗,还是代码问题

mbr_boot.asm

%define BIOS_LOAD_MBR_ADR	0x07c0
;BIOS加载MBR的位置
%define REAL_LOAD_MBR_ADR	0x9000
;MBR实际执行的地址

entry:
	;复制MBR
	mov	ax,BIOS_LOAD_MBR_ADR
	mov	ds,ax
	sub	si,si
	mov	ax,REAL_LOAD_MBR_ADR
	mov	es,ax
	sub	di,di
	mov	cx,0x200
	rep	movsb
	jmp	REAL_LOAD_MBR_ADR:(real_start-entry)
	;跳转执行
real_start:
	;初始化寄存器
	mov	ax,cs
	mov	ds,ax
	mov	es,ax
	mov	ss,ax
	mov	dx,0xfef4
	mov	sp,dx
	;卷屏
	mov	ah,0x03
	xor	bh,bh
	int	0x10
	mov	ax,0x0600
	mov	bx,0x0700
	mov	cx,0
	mov	dx,0x184f
	int	0x10
	mov	ah,0x02
	mov	bh,0
	mov	dx,0
	int	0x10
	;打印启动信息
	mov	bp,boot_msg
	mov cx,21
	call print_str
	jmp	$
	;读取磁盘信息
.load_partions
	;寻找分区
	mov bp,0x07c0+0x1be	;分区表的开始地址
	mov	cx,0			;分区表的表项序号(0-4)
.search_active_partion
	;寻找活动分区
	jmp	$
boot_msg:	db	13,10
			dd	"CandleOS early boot"
print_str:
;打印字符串,参数:bp字符串首地址,cx:字符串总长度
	push ax
	push bx
	mov	ah,0x13
	mov al,0x01
	mov	bx,0x0007
	int	0x10
	pop ax
	pop bx
	ret

build.c

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

int main(int argc,char **argv)
{
	char file_boot[32];
	char file_disk[32];
	if(argc!=5)
	{
		fprintf(stderr,"Build:Build Failed,missing or too many argments!\n");
		return 1;
	}
	FILE *fp_disk,*fp_boot;
	int i;
	for(i=1;i<argc;i++)
	{
		if(!strcmp(argv[i-1],"-d"))
		{
			fp_disk = fopen(argv[i],"rb+");
			sprintf(file_disk,"%s",argv[i]);
		}
		else if(!strcmp(argv[i-1],"-b"))
		{
			fp_boot = fopen(argv[i],"rb+");
			sprintf(file_boot,"%s",argv[i]);
		}
		else{
			continue;}
	}
	if(fp_disk==NULL)
	{
		fprintf(stderr,"Build:Build Failed,no such a disk file!\n");
		return 1;
	}
	if(fp_boot==NULL)
	{
		fprintf(stderr,"Build:Build Failed,no such a boot file!\n");
		return 1;
	}
	
	struct stat statbuf_boot;
    stat(file_boot,&statbuf_boot);
    if(statbuf_boot.st_size>420-64)
    {
    	fprintf(stderr,"Build:Build Failed,the boot file is too large(more than 356 bytes)!\n");
    	return 1;
    }
    
	char buf[420-64];
	int j;
	for(j=0;j<420-64;j++)
	{
		buf[j]=(char)0;
	}
	fseek(fp_boot,0,SEEK_SET);
	fread(buf,420-64,1,fp_boot);
	static char jmp_prog[3] = { 0xeb,0x5a,0x90};
	static char boot_flag[2] = { 0x55,0xaa};
	fseek(fp_disk,0,SEEK_SET);
	fwrite(jmp_prog,3,1,fp_disk);
	fseek(fp_disk,0x5a,SEEK_SET);
	fwrite(buf,420-64,1,fp_disk);
	fseek(fp_disk,0x1fe,SEEK_SET);
	fwrite(boot_flag,2,1,fp_disk);
	fclose(fp_disk);
	fclose(fp_boot);
	printf("Build:Build finished!\n");
	return 0;
}
  • 写回答

1条回答 默认 最新

  • 「已注销」 2023-03-16 11:14
    关注

    参考GPT和自己的思路:

    根据你提供的代码,我看到你在写入启动程序的时候,并没有进行对齐处理,导致写入后机器代码并不符合引导扇区的要求。在MBR的代码区域中,必须要按照512字节的要求进行对齐,如果不足512字节,需要使用0x00进行填充。同时,MBR的最后两个字节必须是0x55AA,表示该扇区是可执行的引导扇区。

    建议你在使用BUILDER进行合成的时候,先把启动程序的代码合并成一个完整的二进制文件,然后再对齐到512字节,并在末尾加上0x55AA标识符。接下来,使用BUILDER将合成的文件写入MBR的相应位置即可。

    另外,你的汇编代码中,jmp指令的地址应该是实际执行的地址,而不是相对地址。因此,jmp指令应该跳转到REAL_LOAD_MBR_ADR的位置,而不是跳转到(real_start-entry)的地址。

    评论

报告相同问题?

悬赏问题

  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献