鱼C论坛

 找回密码
 立即注册
查看: 1434|回复: 6

[技术交流] 01. 人工反编译 - bootsect.s

[复制链接]
发表于 2020-5-4 17:20:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
最近在学习linux 0.11源代码,bootsect.s 文件中有一个 read_it 函数,用来读取软盘上的system模块
这个函数是这个文件中最复杂的一个,相信不少同学被这个函数劝退,我也被劝退n次
这一次我使用人工反编译,把汇编语言翻译成语义上等效的C语言代码
这一次我终于理解了这个函数的逻辑,把自己的翻译结果发上来,希望可以帮到更多的同学,^_^


这个代码可以编译运行,如果有不理解的地方,还可以调试运行这个程序
#define SETUPLEN 4
#define SYSSIZE  0x3000
#define SYSSEG   0x1000
#define ENDSEG   (SYSSEG + SYSSIZE)

const int sectors = 18;
int sread = 1 + SETUPLEN;
int head  = 0;
int track = 0;

void read_track(int count) {
    (void)count;
}

void read_it(int es) {
    while(es & 0x0fff)
        ;
    
    int offset = 0;
    while(1) {
        if(es >= ENDSEG)
            return;
        
        int count = sectors - sread;
        if(count * 512 + offset > 0x10000)
            count = (0x10000 - offset) / 512;
        read_track(count);
        
        int sum = sread + count;
        if(sum == sectors) {
            if(head == 1) {
                head = 0; ++track;
            }
            else ++head;
            sum = 0;
        }
        
        sread = sum;
        offset += count * 512;
        if(offset < 0x10000)
            continue;
        es += 0x1000;
        offset = 0;
    }
}

int main(void) {
    read_it(SYSSEG);
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-5-4 17:22:22 | 显示全部楼层
本帖最后由 人造人 于 2020-5-4 17:34 编辑

把 bootsect.s 也贴上来吧
!
! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
! 0x3000 is 0x30000 bytes = 196kB, more than enough for current
! versions of linux
!
SYSSIZE = 0x3000
!
!       bootsect.s              (C) 1991 Linus Torvalds
!
! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
! iself out of the way to address 0x90000, and jumps there.
!
! It then loads 'setup' directly after itself (0x90200), and the system
! at 0x10000, using BIOS interrupts. 
!
! NOTE! currently system is at most 8*65536 bytes long. This should be no
! problem, even in the future. I want to keep it simple. This 512 kB
! kernel size should be enough, especially as this doesn't contain the
! buffer cache as in minix
!
! The loader has been made as simple as possible, and continuos
! read errors will result in a unbreakable loop. Reboot by hand. It
! loads pretty fast by getting whole sectors at a time whenever possible.

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

SETUPLEN = 4                            ! nr of setup-sectors
BOOTSEG  = 0x07c0                       ! original address of boot-sector
INITSEG  = 0x9000                       ! we move boot here - out of the way
SETUPSEG = 0x9020                       ! setup starts here
SYSSEG   = 0x1000                       ! system loaded at 0x10000 (65536).
ENDSEG   = SYSSEG + SYSSIZE             ! where to stop loading

! ROOT_DEV:     0x000 - same type of floppy as boot.
!               0x301 - first partition on first drive etc
ROOT_DEV = 0x306

entry start
start:
        mov     ax,#BOOTSEG
        mov     ds,ax
        mov     ax,#INITSEG
        mov     es,ax
        mov     cx,#256
        sub     si,si
        sub     di,di
        rep
        movw
        jmpi    go,INITSEG
go:     mov     ax,cs
        mov     ds,ax
        mov     es,ax
! put stack at 0x9ff00.
        mov     ss,ax
        mov     sp,#0xFF00              ! arbitrary value >>512

! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.

load_setup:
        mov     dx,#0x0000              ! drive 0, head 0
        mov     cx,#0x0002              ! sector 2, track 0
        mov     bx,#0x0200              ! address = 512, in INITSEG
        mov     ax,#0x0200+SETUPLEN     ! service 2, nr of sectors
        int     0x13                    ! read it
        jnc     ok_load_setup           ! ok - continue
        mov     dx,#0x0000
        mov     ax,#0x0000              ! reset the diskette
        int     0x13
        j       load_setup

ok_load_setup:

! Get disk drive parameters, specifically nr of sectors/track

        mov     dl,#0x00
        mov     ax,#0x0800              ! AH=8 is get drive parameters
        int     0x13
        mov     ch,#0x00
        seg cs
        mov     sectors,cx
        mov     ax,#INITSEG
        mov     es,ax

! Print some inane message

        mov     ah,#0x03                ! read cursor pos
        xor     bh,bh
        int     0x10
        
        mov     cx,#24
        mov     bx,#0x0007              ! page 0, attribute 7 (normal)
        mov     bp,#msg1
        mov     ax,#0x1301              ! write string, move cursor
        int     0x10

! ok, we've written the message, now
! we want to load the system (at 0x10000)

        mov     ax,#SYSSEG
        mov     es,ax           ! segment of 0x010000
        call    read_it
        call    kill_motor

! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently.

        seg cs
        mov     ax,root_dev
        cmp     ax,#0
        jne     root_defined
        seg cs
        mov     bx,sectors
        mov     ax,#0x0208              ! /dev/ps0 - 1.2Mb
        cmp     bx,#15
        je      root_defined
        mov     ax,#0x021c              ! /dev/PS0 - 1.44Mb
        cmp     bx,#18
        je      root_defined
undef_root:
        jmp undef_root
root_defined:
        seg cs
        mov     root_dev,ax

! after that (everyting loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:

        jmpi    0,SETUPSEG

! This routine loads the system at address 0x10000, making sure
! no 64kB boundaries are crossed. We try to load it as fast as
! possible, loading whole tracks whenever we can.
!
! in:   es - starting address segment (normally 0x1000)
!
sread:  .word 1+SETUPLEN        ! sectors read of current track
head:   .word 0                 ! current head
track:  .word 0                 ! current track

read_it:
        mov ax,es
        test ax,#0x0fff
die:    jne die                 ! es must be at 64kB boundary
        xor bx,bx               ! bx is starting address within segment
rp_read:
        mov ax,es
        cmp ax,#ENDSEG          ! have we loaded all yet?
        jb ok1_read
        ret
ok1_read:
        seg cs
        mov ax,sectors
        sub ax,sread
        mov cx,ax
        shl cx,#9
        add cx,bx
        jnc ok2_read
        je ok2_read
        xor ax,ax
        sub ax,bx
        shr ax,#9
ok2_read:
        call read_track
        mov cx,ax
        add ax,sread
        seg cs
        cmp ax,sectors
        jne ok3_read
        mov ax,#1
        sub ax,head
        jne ok4_read
        inc track
ok4_read:
        mov head,ax
        xor ax,ax
ok3_read:
        mov sread,ax
        shl cx,#9
        add bx,cx
        jnc rp_read
        mov ax,es
        add ax,#0x1000
        mov es,ax
        xor bx,bx
        jmp rp_read

read_track:
        push ax
        push bx
        push cx
        push dx
        mov dx,track
        mov cx,sread
        inc cx
        mov ch,dl
        mov dx,head
        mov dh,dl
        mov dl,#0
        and dx,#0x0100
        mov ah,#2
        int 0x13
        jc bad_rt
        pop dx
        pop cx
        pop bx
        pop ax
        ret
bad_rt: mov ax,#0
        mov dx,#0
        int 0x13
        pop dx
        pop cx
        pop bx
        pop ax
        jmp read_track

/*
 * This procedure turns off the floppy drive motor, so
 * that we enter the kernel in a known state, and
 * don't have to worry about it later.
 */
kill_motor:
        push dx
        mov dx,#0x3f2
        mov al,#0
        outb
        pop dx
        ret

sectors:
        .word 0

msg1:
        .byte 13,10
        .ascii "Loading system ..."
        .byte 13,10,13,10

.org 508
root_dev:
        .word ROOT_DEV
boot_flag:
        .word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

评分

参与人数 1鱼币 +2 收起 理由
Hello. + 2 鱼C有你更精彩^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-5-4 17:24:10 | 显示全部楼层
初学C语言表示瑟瑟发抖
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-4 17:25:59 | 显示全部楼层
十分有用!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-4 17:27:04 | 显示全部楼层
老八秘制 发表于 2020-5-4 17:24
初学C语言表示瑟瑟发抖

^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-4 17:50:38 | 显示全部楼层
没学c语言表示瑟瑟发抖

即将被Hello.攻破电脑表示瑟瑟发抖
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-4 17:54:05 | 显示全部楼层
乘号 发表于 2020-5-4 17:50
没学c语言表示瑟瑟发抖

即将被Hello.攻破电脑表示瑟瑟发抖

C语言不难,真的,^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-14 01:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表