编译代码遇到输出文件被“拦腰截断”?

在写操作系统的的读取硬盘时遇到问题:
代码:disk.asm

global _read_disk
_read_disk:
    push ebp
    mov ebp,esp
    pusha
    xor ecx,ecx
    mov ebx,[esp+4];dis_addr
    mov cl,[esp+8];counts
    mov esi,eax;start LBA
    mov dx,0x1f2;设置读取的扇区数
    mov al,cl
    out dx,al

    mov dx,0x1f3
    mov eax,esi
    out dx,al;0-7bit(LBA)

    inc dx
    shr eax,8
    out dx,al;8-15bit

    inc dx
    shr eax,8
    out dx,al;15-23bit

    inc dx
    shr ax,8
    or al,11100000b
    out dx,al;23-27bit and set some disk args

    inc dx
    mov al,0x20
    out dx,al;read disk
.wait:
    in al,dx
    and al,0x08
    cmp al,0x08
    jnz .wait

    mov di,dx

    mov eax,ecx
    mov cx,256;每次读取2byte,所以要读取512/2*cl次
    mul cx
    mov ecx,edx

    mov dx,di
.read:
    in ax,dx
    mov [ebx],ax
    add ebx,2
    loop .read

    popa
    mov esp,ebp
    pop ebp
    ret

编译命令:

nasm syshead.asm -f elf32 -o syshead.o -l syshead.lst
nasm kernelinc/ints.asm -f elf32 -o ints.o
nasm kernelinc/vars.asm -f elf32 -o vars.o
nasm kernelinc/screen.asm -f elf32 -o screen.o
nasm kernelinc/process.asm -f elf32 -o procasm.o
nasm kernelinc/int/clock.asm -f elf32 -o clock.o
nasm kernelinc/disk/disk.asm -f elf32 -o diskasm.o
set gccargs= -std=c11 -m32 -fno-asynchronous-unwind-tables
rem  -mno-fp-ret-in-387
rem -mno-red-zone  -mgeneral-regs-only  -march=i386 -mtune=i386 -mno-80387
gcc %gccargs% -c -g kernel.c -o kernel.o
gcc %gccargs% -c -g kernelinc/interrupt.c -o interrupt.o
gcc %gccargs% -c -g kernelinc/gdtidt.c -o gdtidt.o
gcc %gccargs% -c -g kernelinc/process.c -o process.o
gcc %gccargs% -c -g kernelinc/filesys/fs.c -o fs.o
gcc %gccargs% -c -g kernelinc/disk/disk.c -o disk.o
rem ld -m i386pe -shared -T lds.lds
set head=syshead.o kernel.o
set libs=ints.o vars.o screen.o interrupt.o gdtidt.o process.o procasm.o fs.o clock.o disk.o diskasm.o
ld -m i386pe %head% %libs% -e reload_idt -o sys.elf -Ttext 0x0

没有吧disk.asm编译后的diskasm.o链接进去的时候是好好的,
但是加进去之后,出来的img文件居然缺了一半以上的代码!
不仅少了diskasm.o里面的代码,其他.o文件的
代码也离奇失踪……
加入diskasm.o之前:

img


之后:

img

代码被拦腰截断:

img

img

img就在这里结束了,但是后面还有很多本应该存在的代码……

为什么会这样?是ld的问题还是gcc的问题?

编译输出:

kernel.c: In function 'kernel':
kernel.c:32:2: warning: implicit declaration of function 'read_disk' [-Wimplicit-function-declaration]
   32 |  read_disk(0,1,0x100000);
      |  ^~~~~~~~~
boot.bin
setup.bin
sys.bin
已复制         1 个文件。
========================================================================
                        Bochs x86 Emulator 2.7
              Built from SVN snapshot on August  1, 2021
                Timestamp: Sun Aug  1 10:07:00 CEST 2021
========================================================================
00000000000i[      ] reading configuration from bochsrc.bxrc
00000000000i[      ] installing win32 module as the Bochs GUI
00000000000i[      ] using log file bochsout.txt

【以下回答由 GPT 生成】

这段代码的问题在于它是汇编代码而不是C语言代码。如果你尝试将它作为C语言代码编译,编译器会以C语言的方式处理这段代码,而不是汇编方式。这样会导致编译器无法正确解析汇编指令并生成可执行的二进制文件。

解决方案是将这段汇编代码保存为一个汇编文件(.asm),然后使用相关的汇编工具来编译生成二进制代码。在Windows环境下,你可以使用MASM(Microsoft Macro Assembler)来编译这段代码。以下是使用MASM的步骤:

  1. 安装MASM:你可以从微软的开发者工具包(Microsoft Developer Tools)中下载并安装MASM。

  2. 创建汇编文件:打开一个文本编辑器,将你的汇编代码粘贴到其中并保存为一个.asm文件。

  3. 编译代码:打开命令提示符(Command Prompt),进入保存有汇编文件的目录。然后使用以下命令编译代码:

ml /c your_asm_file.asm

这将生成一个目标文件(.obj)。

  1. 链接生成可执行文件:在同一个命令提示符下,使用以下命令将目标文件链接成可执行文件:

link your_obj_file.obj

这将生成一个可执行文件(.exe)。

现在,你应该有一个可以正确编译的可执行文件了。请注意,以上步骤是针对使用MASM来编译汇编代码的示例。如果你使用的是其他汇编工具,步骤可能会有所不同。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

找到问题了:
我最后将几个bin文件合并到一起,命令如下:

copy boot.bin+setup.bin+sys.bin floppy.img /b

这样得到img只有6kb,但是我改成这样:

copy /b boot.bin+setup.bin+sys.bin floppy.img 

就完整了。
但是为什么?