IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation d'OS Assembleur Discussion :

Lire plusieurs secteurs d'un floppy et les placer côte à côte en RAM


Sujet :

Programmation d'OS Assembleur

  1. #1
    Futur Membre du Club Avatar de Folaefolc
    Homme Profil pro
    Alive
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Alive

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Points : 9
    Points
    9
    Par défaut Lire plusieurs secteurs d'un floppy et les placer côte à côte en RAM
    Bonjour à tous

    J'essaye de charger depuis un floppy disk 32 secteurs de 512 octets chacun, et je connais uniquement le LBA.
    Pour me faciliter la tâche j'ai voulu coder une fonction qui prendrait en paramètre le LBA, la taille et l'androit en RAM où je veux charger les secteurs (plus précisément c'est un Kernel).
    Hélas, la fonction charge bien les secteurs (mais seulement 25 après vérification, et non pas les 32 souhaités) mais au moment du saut à l'emplacement choisi, le système plante et j'ai une exception 0x5 (out of bound). Je pense que j'ai raté la modification de la destination des secteurs chargés (es:bx) mais je ne comprends ni comment ni pourquoi cela a pu être possible.

    Si quelqu'un veut bine m'aider à trouver le problème je lui en serais reconnaissant c:

    filesystem.asm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
     
    %ifndef filesystem_asm
    %define filesystem_asm
     
    bits 16
     
    ; Macro to read file more easily
    ; INPUT  : AX (LBA number for sector), BX (linear address, where it will be loaded), CX (sectors count)
    ; OUTPUT : CF if an error happen while to find it, ES:BX (where it's loaded)
    %macro load_file 3
        mov ax, %1
        mov bx, %2
        mov cx, %3
        call proj_e_read_file
    %endmacro
     
    ; parameters
    sectors_per_track dw  18
    heads_per_track   dw   2
    bytes_per_sector  dw 512
    drive_number      dw   0
    msg_error_reading_floppy db '[!] Error while reading floppy', 13, 10, 0
    ; variables
    abs_sector        dw   0
    abs_head          dw   0
    abs_track         dw   0
    lba_number        dw   0
    file_size         dw   0
    destination       dw   0
     
    ; Routine to convert a LBA (Logical Block Addresing) to CHS (Cylinder/Head/Sector)
    ; INPUT  : AX (LBA addr), sectors_per_track, heads_per_track
    ; OUTPUT : abs_sector (CHS sector addr), abs_head (CHS head addr), abs_track (CHS track addr)
    proj_e_lbachs:
        xor dx, dx
        div word [sectors_per_track]
        inc dl
        mov byte [abs_sector], dl
     
        xor dx, dx
        div word [heads_per_track]
        mov byte [abs_head], dl
        mov byte [abs_track], al
     
        ret
     
    ; Routine to read files into memory more easily
    ; INPUT  : AX (LBA number for sector), BX (linear address, where it will be loaded), CX (sectors count)
    ; OUTPUT : CF if an error happen while to find it, ES:BX (where it's loaded)
    proj_e_read_file:
    .begin:
        ; save destination
        mov word [destination], bx
     
        ; sectors count starts from 1
        mov word [lba_number], ax
        inc word [lba_number]
    .main:
        mov di, 0x0005  ; retry count
    .loop:
        ; get track, sector, and head
        mov ax, word [lba_number]
        call proj_e_lbachs
     
        ; move forward to avoid overwriting
        push word [destination]
        pop es
        xor bx, bx
     
        ; save counter (for loop)
        push cx
     
        ; read floppy
        mov ah, 0x02
        mov al, 0x01
        mov ch, byte [abs_track]
        mov cl, byte [abs_sector]
        mov dh, byte [abs_head]
        mov dl, byte [drive_number]
        int 0x13
     
        ; restore counter
        pop cx
     
        ; if no error, go to next sector
        jnc .sectordone
     
        ; otherwise reset disk
        xor ax, ax
        int 0x13
        ; decrement number of trials left
        dec di
     
        ; retry
        jnz .loop
        ; we got an error, impossible to read.
        jmp .error
    .sectordone:
        ; move forward
        mov ax, word [destination]
        add ax, 0x10  ;word [bytes_per_sector]
        mov word [destination], ax
     
        ; increment LBA
        inc word [lba_number]
     
        ; decrement ecx, go to label while non-zero
        loop .main
        jmp .quit
    .error:
        ; set carry flag
        stc
        ; optionnal but well it's handy
        print msg_error_reading_floppy
        ; cleaning up things
        jmp .end
    .quit:
        ; if we "quit" it means there were no errors, so clear the carry flag
        clc
    .end:
        ret
     
    %endif
    boot.asm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    bits 16
    org 0x7c00
     
    start:
        jmp main
     
    %include "std/stdio.asm"
    %include "std/filesystem.asm"
     
    data:
        ; strings
        new_line db 13, 10, 0
        title    db 'Project E', 13, 10, '=========', 13, 10, 13, 10, 0
        message  db '[Bootloader] Press any key to load kernel', 0
        msg_kernel_loaded   db '[Bootloader] Kernel loaded', 13, 10, 0
        msg_kernel_load_err db '[!] [Bootloader] Could not load kernel', 13, 10, 0
     
        ; parameters
        KERNEL_BLOCK_START equ      1
        KERNEL_BLOCKS_SIZE equ     32  ; 32*512B=16384B
        KERNEL_SEGMENT     equ 0x0100  ; 0x0100:0x0000=0x1000
     
    main:
        cli
        xor ax, ax
        mov ds, ax
        mov es, ax
     
        ; init the stack
        mov ss, ax
        mov sp, 0x7c00
        sti
     
        ; display message on startup
        print title
        print message
        call proj_e_waitkeypress16
        print new_line
     
        ; prepare to load the kernel
        load_file KERNEL_BLOCK_START, KERNEL_SEGMENT, KERNEL_BLOCKS_SIZE
        jnc .jump_to_kernel              ; loading success, no error in carry flag
     
    .kernel_loading_error:
        print msg_kernel_load_err
        cli
        hlt
     
    .jump_to_kernel:
        print msg_kernel_loaded
        call KERNEL_SEGMENT:0x0000
     
    ; pad to 510 bytes (boot sector - 2)
    times 510-($-$$) db 0
    ; standard boot signature
    dw 0xAA55
    PS: je n'ai pas trouvé comment modifier la coloration syntaxique, si jamais c'est gênant faites le moi savoir

  2. #2
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    Pourquoi dans boot.asm la fonction s'appelle-t-elle "load_file" et dans filesystem.asm elle s'appelle proj_e_read_file ?

    À mon avis un des problèmes viendrait de là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        mov ax, word [destination]
        add ax, 0x10  ;word [bytes_per_sector]
        mov word [destination], ax
    Si j'ai bien compris, tu incrémentes le segment de la mémoire de 16, ce qui fait avancer l'adresse de 16*16=256 octets, sauf que les secteurs de la disquette font 512 octets ! Ce qui fait que le code recopié a été écrasé par le contenu du secteur suivant (et évite de travailler les adresses sur segment, ça n'est pas une bonne habitude).

    À mon avis pour remplacer ces lignes fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        add word[destination],20h
    Pour le problème des 25 secteurs copiés à la place de 32, je pense que ça peut venir de l'appel de la fonction car "load_file KERNEL_BLOCK_START, KERNEL_SEGMENT, KERNEL_BLOCKS_SIZE" doit peut-être empiler les arguments (comme c'est fait habituellement en C) au lieu de les mettre dans les registres.

  3. #3
    Futur Membre du Club Avatar de Folaefolc
    Homme Profil pro
    Alive
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Alive

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Points : 9
    Points
    9
    Par défaut
    Oh c'est juste une macro load_file, parce que j'avais un peu "la flemme" de mettre dans les bons registres les différents paramètres, elle permet d'appeler proj_e_read_file.

    Oh bien vu pour l'incrémentation ! De tête j'avais effectivement divisé 256 et par 512 :c Merci beaucoup, quel idiot je suis.

    Pour le coup du
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    add word [destination], 20h
    je crois juste que j'avais oublié qu'on pouvait le faire comme ça c:

    En ayant fait ce correctif, les 32 secteurs sont maintenant lus, mais toujours le même problème, j'ai une exception 0x5 :/
    En tout cas merci pour ton aide, un problème (que je n'avais même pas vu ) de résolu, c'est déjà ça !

    PS: le nouveau code donne donc ceci pour ceux qui se demandent

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
     
    %ifndef filesystem_asm
    %define filesystem_asm
     
    bits 16
     
    ; Macro to read file more easily
    ; INPUT  : AX (LBA number for sector), BX (linear address, where it will be loaded), CX (sectors count)
    ; OUTPUT : CF if an error happen while to find it, ES:BX (where it's loaded)
    %macro load_file 3
        mov ax, %1
        mov bx, %2
        mov cx, %3
        call proj_e_read_file
    %endmacro
     
    ; parameters
    sectors_per_track dw  18
    heads_per_track   dw   2
    bytes_per_sector  dw 512
    drive_number      dw   0
    msg_error_reading_floppy db '[!] Error while reading floppy', 13, 10, 0
    ; variables
    abs_sector        dw   0
    abs_head          dw   0
    abs_track         dw   0
    lba_number        dw   0
    file_size         dw   0
    destination       dw   0
     
    ; Routine to convert a LBA (Logical Block Addresing) to CHS (Cylinder/Head/Sector)
    ; INPUT  : AX (LBA addr), sectors_per_track, heads_per_track
    ; OUTPUT : abs_sector (CHS sector addr), abs_head (CHS head addr), abs_track (CHS track addr)
    proj_e_lbachs:
        xor dx, dx
        div word [sectors_per_track]
        inc dl
        mov byte [abs_sector], dl
     
        xor dx, dx
        div word [heads_per_track]
        mov byte [abs_head], dl
        mov byte [abs_track], al
     
        ret
     
    ; Routine to read files into memory more easily
    ; INPUT  : AX (LBA number for sector), BX (linear address, where it will be loaded), CX (sectors count)
    ; OUTPUT : CF if an error happen while to find it, ES:BX (where it's loaded)
    proj_e_read_file:
    .begin:
        ; save destination
        mov word [destination], bx
     
        ; sectors count starts from 1
        mov word [lba_number], ax
        inc word [lba_number]
    .main:
        mov di, 0x0005  ; retry count
    .loop:
        ; get track, sector, and head
        mov ax, word [lba_number]
        call proj_e_lbachs
     
        ; move forward to avoid overwriting
        push word [destination]
        pop es
        xor bx, bx
     
        ; save counter (for loop)
        push cx
     
        ; read floppy
        mov ah, 0x02
        mov al, 0x01
        mov ch, byte [abs_track]
        mov cl, byte [abs_sector]
        mov dh, byte [abs_head]
        mov dl, byte [drive_number]
        int 0x13
     
        ; restore counter
        pop cx
     
        ; if no error, go to next sector
        jnc .sectordone
     
        ; otherwise reset disk
        xor ax, ax
        int 0x13
        ; decrement number of trials left
        dec di
     
        ; retry
        jnz .loop
        ; we got an error, impossible to read.
        jmp .error
    .sectordone:
        ; move forward
        add word [destination], 0x20
        ; increment LBA
        inc word [lba_number]
        ; decrement ecx, go to label while non-zero
        loop .main
        jmp .quit
    .error:
        ; set carry flag
        stc
        ; optionnal but well it's handy
        print msg_error_reading_floppy
        ; cleaning up things
        jmp .end
    .quit:
        ; if we "quit" it means there were no errors, so clear the carry flag
        clc
    .end:
        ret
     
    %endif

  4. #4
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    Si l'exception est générée après le saut vers le code qui vient d'être chargé, c'est peut-être que c'est le code qui pose problème et plus le loader. Il faudrait à la limite nous montrer ce qui est chargé après.

    Je me souviens qu'à mes débuts j'avais un code simple qui écrivait simplement une lettre a l'écran pour valider le passage à certaines étapes de mon programme et/ou vérifier que les données avait été bien chargées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    push ax
    push ds
    mov ax,0B800h ;le segment de l'écran video texte
    mov ds,ax
    mov byte[0],"A" ;0=en haut a gauche
    mov byte[1],07h ;code couleur de la lettre (7=gris clair)
    pop ds
    pop ax
    Il ne reste plus qu'à rajouter ce petit bout de code (en changeant la lettre) à différents endroits de ton programme pour valider le passage de certaines étapes.

  5. #5
    Futur Membre du Club Avatar de Folaefolc
    Homme Profil pro
    Alive
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Alive

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Points : 9
    Points
    9
    Par défaut
    Ah pas bête je vais essayer de faire ça

    Actuellement, le bootloader charge ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
     
    bits 16
    org 0
     
    start:
        jmp main
     
    %include "std/stdio.asm"
    %include "std/string.asm"
    %include "std/video.asm"
    %include "std/filesystem.asm"
     
    data:
        msg_info db 'Project E is developped by SuperFola', 13, 10, 0
        ret_line db 13, 10, 0
        msg_app_load_ok  db '[Kernel] App loaded', 13, 10, 0
        msg_app_load_err db '[!] [Kernel] Could not load app', 13, 10, 0
     
        buffer times 72 db 0
        flag_gdt_installed db 0
     
        shell_cursor       db 'kernel> ',     0
        shell_command_help db 'help',   0
        shell_action_help  db 'help reboot info test', 13, 10, 0
        shell_command_rbt  db 'reboot', 0
        shell_command_info db 'info',   0
        shell_command_test db 'test',   0
     
        shell_error_wrong_command db 'Unknown command', 13, 10, 0
     
        APP_BLOCK_START equ     33
        APP_BLOCKS_SIZE equ      8  ; 8*512B=4096B
        APP_SEGMENT     equ 0x07e0  ; 0x07e0:0x0000=0x8000
     
    main:
        mov ax, cs
        mov ds, ax
     
    shell_begin:
        print ret_line
        print shell_cursor            ; print cursor
     
        ; ask for user input
        input buffer, 72
     
        ; to be able to do the comparisons tests
        mov si, buffer
     
        ; checks if user typed help command
        mov di, shell_command_help
        call proj_e_compare_string16
        jc .command_help
     
        ; check if user typed reboot command
        mov di, shell_command_rbt
        call proj_e_compare_string16
        jc .command_rbt
     
        ; check if user typed info command
        mov di, shell_command_info
        call proj_e_compare_string16
        jc .command_info
     
        mov di, shell_command_test
        call proj_e_compare_string16
        jc .command_test
     
    ; wrong user input (command not recognized)
    .wrong_input_error:
        print shell_error_wrong_command
        jmp shell_begin
     
    ; command help (shell_command_help) selected
    .command_help:
        print shell_action_help
        jmp shell_begin
     
    ; command reboot (shell_command_rbt) selected
    ; this specific subroutine must be placed at the very end to avoid rebooting for nothing
    .command_rbt:
        call proj_e_reboot16
     
    ; command info (shell_command_info) selected
    .command_info:
        print msg_info
        jmp shell_begin
     
    ; command command_test
    .command_test:
        mov ah, CREATE_COLOUR(CHAR_ATTR_CYAN, CHAR_ATTR_RED)  ; cyan on red background
        call proj_e_clear_screen16
        ; move cursor in x=0,y=0
        move_cursor 0x0000
     
        ; prepare to load app
        load_file APP_BLOCK_START, APP_SEGMENT, APP_BLOCKS_SIZE
        jnc .jump_to_app                 ; loading success, no error in carry flag
     
    .app_loading_error:
        print msg_app_load_err
        jmp shell_begin
     
    .jump_to_app:
        print msg_app_load_ok
        jmp APP_SEGMENT:0x0000
     
    ; 16kB kernel
    times 16384-($-$$) db 0
    Mais comme ni le new_line ni le shell_cursor ne sont affichés, j'en déduis qu'il n'arrive pas à sauter sur mon kernel. Et le dernier message affiché (juste avant le call KERNEL_SEGMENT:0x0000) est '[Bootloadr] Kernel loaded', ça veut dire que c'est le call qui ne marche pas (enfin pas comme voulu).

    Le truc c'est qu'avant, ça marchait très bien, j'arrivais à charger mon kernel en faisant comme dans ce fichier : https://github.com/SuperFola/project...f4f9f/boot.asm (c'est le repo github du projet). Mais évidemment ca ne me plait pas trop, parce que je suis très limité sur ce que je peux charger en utilisant cette méthode, c'est pour ça que j'ai fait cette fonction.

  6. #6
    Futur Membre du Club Avatar de Folaefolc
    Homme Profil pro
    Alive
    Inscrit en
    Mai 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Alive

    Informations forums :
    Inscription : Mai 2018
    Messages : 4
    Points : 9
    Points
    9
    Par défaut Solution trouvé, une bête erreur...
    Bonjour !

    Je poste ici car ça pourrait intéresser d'autres personnes quand même, et je m'excuse du double post d'avance.

    J'ai trouvé le "bogue", cela venait juste du fait que j'incrémentais AX avant de le donner à proj_e_lbchs (les secteurs sont comptés à partir de 1 mais le LBA commence à 0 lui !).

    Tout bête en fait, j'ai du mal à croire que ça marche, c'est super c:

    Merci beaucoup pour ton aide !

  7. #7
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    mais de rien!
    et bon courage pour la suite

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 13/09/2014, 22h28
  2. [GRAPH] Comment présenter les sous-groupes côte à côte et pas l'un au-dessus de l'autre ?
    Par Françoise_ dans le forum ODS et reporting
    Réponses: 4
    Dernier message: 14/03/2014, 15h05
  3. Réponses: 12
    Dernier message: 18/06/2006, 19h42
  4. Réponses: 5
    Dernier message: 05/01/2006, 18h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo