Şimdi Ara

Boot-up asembly code yardım!

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
1 Misafir - 1 Masaüstü
5 sn
5
Cevap
0
Favori
826
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • code segment
    assume cs:code, ds:code
    org 7c00h
    start:
    jmp st1
    mesaj db "calisiyor..."
    ekran equ 0b800h
    st1:
    mov ax,cs
    mov ds,ax
    mov es,ax

    mov bx,offset mesaj
    mov ax,ekran
    mov es,ax
    mov si,780h
    mov cx,12
    st2:
    mov al,byte ptr [bx]
    mov es:[si],al
    add si,2
    inc bx
    loop st2
    jmp st1
    code ends
    end start

    Ben yeni yeni assembly öğreniyorum. Bunu da sağdan soldan topladığım bilgilerle yazdım. Bu bir boot kodu. Aslında boot kodu olmadığı bariz ama bunu floppy nin boot sektörüne kopyaladımızda ekrana "calisiyor..." yazmasını istedim. Ve sonra sonsuz döngüye soktum zaten atlayacak bir yer olmayacak. Ben bunu Virtual machine de denedim ama çalışmadı zaten link yapamadım .obj dosyasını direk kullanıdım ama oda çalışmadı. Tasm da derlediğimde "geçersiz başlama noktası" diye bir hata veriyor. Gerçi linux kullanıcıları tasm dam falan pek anlamaz ama neyse yardıma ihtiyacım var.







  • Sence bu soru için uygun bir yer mi? Belki de programlama bölümüne yazmalısın.
  • Derledikten sonra bunu boot sektörüne nasıl yazmayı düşünüyordun ki?
  • Ben yüzeysel bir şekilde boot edebilir assembly kodunun nasıl yazıldığı ve çalıştığı konusunda açıklama yapayım.

    Sistem çalışmaya ilk başladığında, BIOS ROM olarak bilinen küçük bir ROM entegresinden BIOS (Temel Giriş Çıkış Sistemi)'u okur ve çalıştırır. BIOS programı POST (Power On SelfTest) işlemini gerçekleştirerek bilgisayarda mevcut olan donanımları algılamaya çalışır. Bu aşamada işletim sistemi programcılarını birkaç küçük şey dışında ilgilendiren fazla birşey yoktur. Sistem açıldığında çalışan bu ilk program işini bitirdikten sonra fiziksel belleğin 0x7C00 adresine BIOS ayarları yüklenerek hangi aygıtların boot kaydı içerdiği incelenmeye başlanır. Boot kaydı dediğimiz şey boot edebilen çeşitli aygıtların ilk sektörlerine yüklenen programlardır. Boot kaydı 510'uncu ofset adresinde bir 0xAA55 boot sinyalini içerir. BIOS tüm boot edebilir aygıtlarda bu imzanın varlığını araştırır. Eğer incelemiş olduğu aygıt boot sinyali içermiyorsa, bir sonraki boot edebilir aygıta geçerek incelemesini sürdürür. Eğer incelemiş olduğu aygıtların hiçbiri, geçerli bir boot sinyali içermiyorsa, ekrana "Non-system disk" mesajına benzer bir mesaj basar. Geçerli bir boot kaydına rastlarsa, çalıştırmak üzere boot koduna sıçrar.

    Assembly bildiğini varsayarak, aşağıya da örnek bir assembly kodu ekliyorum.


    code_seg segment use16 
    assume cs: code_seg

    jmp start

    DisplayMsg db ‘GNU/Linux Kernel 2.6.21.5 Loading...’,0

    display proc near
    prnt:
    lodsb
    or al,al
    jz over
    mov ah,0Eh
    mov bh,0
    int 10h
    jmp prnt
    over: ret
    display endp

    start:
    mov ax,07C0h
    mov ds,ax

    cli
    mov ax,1000h
    mov ss,ax
    mov sp,0ffffh
    sti

    mov si,offset DisplayMsg
    call display

    mov ah,0
    int 16h

    db 0eah
    dw 0000h
    dw 0ffffh

    org 510
    dw 0aa55h

    code_seg ends
    end




  • Biraz uzun olacak ama harika bir inceleme olanağı sağlayacağını düşünerek Linux 2.0 boot sektörünü ekliyorum.

    ! 
    ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
    ! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
    ! versions of linux which compress the kernel
    !
    #include <linux/config.h>
    SYSSIZE = DEF_SYSSIZE
    !
    ! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds
    ! modified by Drew Eckhardt
    ! modified by Bruce Evans (bde)
    !
    ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
    ! itself out of the way to address 0x90000, and jumps there.
    !
    ! bde - should not jump blindly, there may be systems with only 512K low
    ! memory. Use int 0x12 to get the top of memory, etc.
    !
    ! It then loads 'setup' directly after itself (0x90200), and the system
    ! at 0x10000, using BIOS interrupts.
    !
    ! NOTE! currently system is at most (8*65536-4096) bytes long. This should
    ! be no problem, even in the future. I want to keep it simple. This 508 kB
    ! kernel size should be enough, especially as this doesn't contain the
    ! buffer cache as in minix (and especially now that the kernel is
    ! compressed :-)
    !
    ! The loader has been made as simple as possible, and continuous
    ! read errors will result in a unbreakable loop. Reboot by hand. It
    ! loads pretty fast by getting whole tracks at a time whenever possible.

    .text

    SETUPSECS = 4 ! nr of setup-sectors
    BOOTSEG = 0x07C0 ! original address of boot-sector
    INITSEG = DEF_INITSEG ! we move boot here - out of the way
    SETUPSEG = DEF_SETUPSEG ! setup starts here
    SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536).

    ! ROOT_DEV & SWAP_DEV are now written by "build".
    ROOT_DEV = 0
    SWAP_DEV = 0
    #ifndef SVGA_MODE
    #define SVGA_MODE ASK_VGA
    #endif
    #ifndef RAMDISK
    #define RAMDISK 0
    #endif
    #ifndef CONFIG_ROOT_RDONLY
    #define CONFIG_ROOT_RDONLY 1
    #endif

    ! ld86 requires an entry symbol. This may as well be the usual one.
    .globl _main
    _main:
    #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
    int 3
    #endif
    mov ax,#BOOTSEG
    mov ds,ax
    mov ax,#INITSEG
    mov es,ax
    mov cx,#256
    sub si,si
    sub di,di
    cld
    rep
    movsw
    jmpi go,INITSEG

    ! ax and es already contain INITSEG

    go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of
    ! bootsect + length of setup + room for stack
    ! 12 is disk parm size

    ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
    ! wouldn't have to worry about this if we checked the top of memory. Also
    ! my BIOS can be configured to put the wini drive tables in high memory
    ! instead of in the vector table. The old stack might have clobbered the
    ! drive table.

    mov ds,ax
    mov ss,ax ! put stack at INITSEG:0x4000-12.
    mov sp,di
    /*
    * Many BIOS's default disk parameter tables will not
    * recognize multi-sector reads beyond the maximum sector number
    * specified in the default diskette parameter tables - this may
    * mean 7 sectors in some cases.
    *
    * Since single sector reads are slow and out of the question,
    * we must take care of this by creating new parameter tables
    * (for the first disk) in RAM. We will set the maximum sector
    * count to 36 - the most we will encounter on an ED 2.88.
    *
    * High doesn't hurt. Low does.
    *
    * Segments are as follows: ds=es=ss=cs - INITSEG,
    * fs = 0, gs is unused.
    */

    ! cx contains 0 from rep movsw above

    mov fs,cx
    mov bx,#0x78 ! fs:bx is parameter table address
    push ds
    seg fs
    lds si,(bx) ! ds:si is source

    mov cl,#6 ! copy 12 bytes
    cld
    push di

    rep
    movsw

    pop di
    pop ds

    movb 4(di),*36 ! patch sector count

    seg fs
    mov (bx),di
    seg fs
    mov 2(bx),es

    ! load the setup-sectors directly after the bootblock.
    ! Note that 'es' is already set up.
    ! Also cx is 0 from rep movsw above.

    load_setup:
    xor ah,ah ! reset FDC
    xor dl,dl
    int 0x13

    xor dx, dx ! drive 0, head 0
    mov cl,#0x02 ! sector 2, track 0
    mov bx,#0x0200 ! address = 512, in INITSEG
    mov ah,#0x02 ! service 2, nr of sectors
    mov al,setup_sects ! (assume all on head 0, track 0)
    int 0x13 ! read it
    jnc ok_load_setup ! ok - continue

    push ax ! dump error code
    call print_nl
    mov bp, sp
    call print_hex
    pop ax

    jmp load_setup

    ok_load_setup:

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

    #if 0

    ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
    ! disks. It doesn't work for one of my BIOS's (1987 Award). It was
    ! fatal not to check the error code.

    xor dl,dl
    mov ah,#0x08 ! AH=8 is get drive parameters
    int 0x13
    xor ch,ch
    #else

    ! It seems that there is no BIOS call to get the number of sectors. Guess
    ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
    ! 15 if sector 15 can be read. Otherwise guess 9.

    mov si,#disksizes ! table of sizes to try

    probe_loop:
    lodsb
    cbw ! extend to word
    mov sectors, ax
    cmp si,#disksizes+4
    jae got_sectors ! if all else fails, try 9
    xchg ax, cx ! cx = track and sector
    xor dx, dx ! drive 0, head 0
    xor bl, bl
    mov bh,setup_sects
    inc bh
    shl bh,#1 ! address after setup (es = cs)
    mov ax,#0x0201 ! service 2, 1 sector
    int 0x13
    jc probe_loop ! try next value

    #endif

    got_sectors:

    ! Restore es

    mov ax,#INITSEG
    mov es,ax

    ! Print some inane message

    mov ah,#0x03 ! read cursor pos
    xor bh,bh
    int 0x10

    mov cx,#9
    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
    call print_nl

    ! 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, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
    ! depending on the number of sectors we pretend to know we have.

    seg cs
    mov ax,root_dev
    or ax,ax
    jne root_defined
    seg cs
    mov bx,sectors
    mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
    cmp bx,#15
    je root_defined
    mov al,#0x1c ! /dev/PS0 - 1.44Mb
    cmp bx,#18
    je root_defined
    mov al,#0x20 ! /dev/fd0H2880 - 2.88Mb
    cmp bx,#36
    je root_defined
    mov al,#0 ! /dev/fd0 - autodetect
    root_defined:
    seg cs
    mov root_dev,ax

    ! after that (everything 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 0 ! sectors read of current track
    head: .word 0 ! current head
    track: .word 0 ! current track

    read_it:
    mov al,setup_sects
    inc al
    mov sread,al
    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:
    #ifdef __BIG_KERNEL__
    #define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
    ! NOTE: as86 can't assemble this
    CALL_HIGHLOAD_KLUDGE ! this is within setup.S
    #else
    mov ax,es
    sub ax,#SYSSEG
    #endif
    cmp ax,syssize ! have we loaded all yet?
    jbe ok1_read
    ret
    ok1_read:
    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
    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 ah,#0x10
    mov es,ax
    xor bx,bx
    jmp rp_read

    read_track:
    pusha
    pusha
    mov ax, #0xe2e ! loading... message 2e = .
    mov bx, #7
    int 0x10
    popa

    mov dx,track
    mov cx,sread
    inc cx
    mov ch,dl
    mov dx,head
    mov dh,dl
    and dx,#0x0100
    mov ah,#2

    push dx ! save for error dump
    push cx
    push bx
    push ax

    int 0x13
    jc bad_rt
    add sp, #8
    popa
    ret

    bad_rt: push ax ! save error code
    call print_all ! ah = error, al = read


    xor ah,ah
    xor dl,dl
    int 0x13


    add sp, #10
    popa
    jmp read_track

    /*
    * print_all is for debugging purposes.
    * It will print out all of the registers. The assumption is that this is
    * called from a routine, with a stack frame like
    * dx
    * cx
    * bx
    * ax
    * error
    * ret <- sp
    *
    */

    print_all:
    mov cx, #5 ! error code + 4 registers
    mov bp, sp

    print_loop:
    push cx ! save count left
    call print_nl ! nl for readability

    cmp cl, #5
    jae no_reg ! see if register name is needed

    mov ax, #0xe05 + 'A - 1
    sub al, cl
    int 0x10

    mov al, #'X
    int 0x10

    mov al, #':
    int 0x10

    no_reg:
    add bp, #2 ! next register
    call print_hex ! print it
    pop cx
    loop print_loop
    ret

    print_nl:
    mov ax, #0xe0d ! CR
    int 0x10
    mov al, #0xa ! LF
    int 0x10
    ret

    /*
    * print_hex is for debugging purposes, and prints the word
    * pointed to by ss:bp in hexadecimal.
    */

    print_hex:
    mov cx, #4 ! 4 hex digits
    mov dx, (bp) ! load word into dx
    print_digit:
    rol dx, #4 ! rotate so that lowest 4 bits are used
    mov ax, #0xe0f ! ah = request, al = mask for nybble
    and al, dl
    add al, #0x90 ! convert al to ascii hex (four instructions)
    daa
    adc al, #0x40
    daa
    int 0x10
    loop print_digit
    ret


    /*
    * 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
    xor al, al
    outb
    pop dx
    ret

    sectors:
    .word 0

    disksizes:
    .byte 36,18,15,9

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

    .org 497
    setup_sects:
    .byte SETUPSECS
    root_flags:
    .word CONFIG_ROOT_RDONLY
    syssize:
    .word SYSSIZE
    swap_dev:
    .word SWAP_DEV
    ram_size:
    .word RAMDISK
    vid_mode:
    .word SVGA_MODE
    root_dev:
    .word ROOT_DEV
    boot_flag:
    .word 0xAA55




  • Yapay Zeka’dan İlgili Konular
    Daha Fazla Göster
    
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.