добавление ассемблерного кода, удаление отображаемых строк

Пытаюсь написать свою мини ОС. Я учусь на других проектах, поэтому понятия не имею, подходит ли мой код для загрузчика и ядра. Я использую сборку 16 бит, NASM, и загружаю загрузчик и ядро ​​как файлы .bin на образ дискеты. Я запускаю ОС с qemu. Я дошел до того, что добавление дополнительных строк кода стирает отображаемые строки, которые появляются при запуске ОС. Например, если я запускаю операционную систему, и она говорит: «Добро пожаловать в мою ОС!», После добавления нескольких строк кода она будет выглядеть как «Добро пожаловать в м» (конец исчезает).

вот мой код:

bootloader.asm

[bits 16]
[org 0x7c00]

                                ; Use the boot drive number passed to us by BIOS in register DL
start:
    xor ax,ax                   ; We want a segment of 0 for DS
    mov ds,ax                   ;     Set AX to appropriate segment value
    mov es,ax                   ; In this case we'll default to ES=DS
    mov bx,0x8000               ; Stack segment can be any usable memory

    mov ss,bx                   ; This places it with the top of the stack @ 0x80000.
    mov sp,ax                   ; Set SP=0 so the bottom of stack will be @ 0x8FFFF


    cld                         ; Set the direction flag to be positive direction

    mov si, welcome_msg
    call print_string

    mov si, kernel_load
    call print_string

    pushf
    stc

    mov ah,00h                  ; Reset Disk Drive
    int 13h

    read_sector:
        mov ax, 0x0
        mov es, ax              ; ES = 0
        mov bx, 0x1000          ; BX = 0x1000. ES:BX=0x0:0x1000 
                                ; ES:BX = starting address to read sector(s) into
        mov ah, 02              ; Int 13h/AH=2 = Read Sectors From Drive
        mov al, 01              ; Sectors to read = 1
        mov ch, 00              ; CH=Cylinder. Second sector of disk
                                ; is at Cylinder 0 not 1
        mov cl, 02              ; Sector to read = 2
        mov dh, 00              ; Head to read = 0
                                ; DL hasn't been destroyed by our bootloader code and still
                                ;     contains boot drive # passed to our bootloader by the BIOS
        int 13h                 ; Read Sectors From Drive

        jc error_kernel_load    ; error loading kernel
        popf
        jmp 0x0:0x1000          ; jmp to kernel offset
        cli                     ; Disable interrupts to circumvent bug on early 8088 CPUs
        hlt                     ; halts the central processing unit (CPU) until the next external interrupt

error_kernel_load:
        mov si, error_msg
        call print_string
        mov si, restart_msg
        call print_string
        mov ah,00               ; wait for key press
        int 16h
        xor ax,ax               
        int 19h                 ; reboot the computer

print_string:                   ; Routine: output string in SI to screen
        lodsb                   ; Get character from string
        or al,al
        jz exit
        mov ah,0x0e
        int 10h                 ; int 10h 'print char' function
        jmp print_string
exit:
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Messages to print
    welcome_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0
    kernel_load db 'Loading kernel....',0x0D,0x0A,0
    error_msg db 'Kernel.bin not found!',0x0D,0x0A,0
    restart_msg db 'Press any key to restart..',0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


times 510-($-$$) db 0       ; Create padding to fill out to 510 bytes
dw      0xaa55              ; Magic number in the trailer of a boot secto

kernel.asm

[bits 16]
[org 0x1000]

section .data:
    cursor_col:     db     0                ; cursor column
    cursor_row:     db     0                ; cursor row
    line_col:       dw     0                ; line column
    line_row:       dw     0                ; line row

    color:          db     3Fh              ; background and forground color (at start set random the formal way > number+letter)

    mode:           db     0


start:
    mov ax, 07C0h                           ; Set up 4K stack space after this bootloader
    add ax, 288                             ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

mov byte [color], 3Fh
    call clear_screen                       ; clear the screen and color it

                                            ; VVV print "Minerald welcome" message VVV
    mov byte [cursor_col], 08               
    mov byte [cursor_row], 28
    call set_cursor                         ; print at the requested position of the screen
    mov si, welcome_string                  ; Put string position into SI
    call print_string                       ; Call our string-printing routine


                                            ; VVV print "Press Space" message VVV
    mov byte [cursor_col], 14
    mov byte [cursor_row], 26
    call set_cursor                         ; print at the requested position of the screen
    mov si, press_key_string                ; Put string position into SI
    call print_string                       ; Call our string-printing routine


    mov ah, 0h                              ; wait for key press
    int 16h                                                 

    mov byte [color], 1Fh
    call clear_screen                       ; clear the screen and color it


    mov byte [cursor_col], 2
    mov byte [cursor_row], 0
    call set_cursor                         ; print at the requested position of the screen
    mov si, basic_background                ; Put string position into SI
    call print_string   

    mov byte [cursor_col], 22
    mov byte [cursor_row], 0
    call set_cursor                         ; print at the requested position of the screen
    mov si, basic_background                ; Put string position into SI
    call print_string                       ; Call our string-printing routine


    mov ah, 0                               ; set display mode function.
    mov al, 13h                             ; mode 13h = 320x200 pixels, 256 colors.
    int 10h                                 ; set it!

    ;=================================      ; rectangles
    mov byte [line_col], 80
    mov byte [line_row], 165

    call print_rectangle                    ; print rectangle

    mov byte [line_col], 80
    mov byte [line_row], 135

    call print_rectangle                    ; print rectangle
    ;==================================


end:
    jmp $                                   ; Jump here - infinite loop!
    ;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;
clear_screen:
    mov ah, 06h                             ; Scroll up function
    xor al, al                              ; Clear entire screen
    xor cx, cx                              ; Upper left corner CH=row, CL=column
    mov dx, 184Fh                           ; lower right corner DH=row, DL=column 
    mov bh, byte [color]                    ; set background and foreground color
    int 10h
    ret
;;;;;;;;;;

;;;;;;;;;;
print_string:                               ; Routine: output string in SI to screen
    lodsb                                   ; Get character from string
    or al,al
    jz exit
    mov ah,0x0e                             ; int 10h 'print char' function
    int 10h
    jmp print_string
exit:
    ret

;;;;;;;;;;

;;;;;;;;;;
set_cursor:
    mov dh, byte [cursor_col]               ; cursor col 
    mov dl, byte [cursor_row]               ; cursor row
    mov ah, 02h                             ; move cursor to the right place
    xor bh, bh                              ; video page 0
    int 10h                                 ; call bios service
    ret
;;;;;;;;;;

;;;;;;;;;;
print_rectangle:
    %INCLUDE "print_rectangle.asm"
;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Messages to print
    welcome_string       db 'Welcome to  my OS!', 0
    press_key_string     db 'Press any key to continue...', 0
    enter_message_string db 'Enter your message below',0
    APM_ERROR_string     db 'APM Error...'
    basic_background     db '--------------------------------------------------------------------------------'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;END OF KERNEL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

это команды нагрузки:

nasm -f bin -o kernel.bin kernel.asm
nasm -f bin -o bootloader.bin bootloader.asm

dd if=bootloader.bin of=floppy.flp bs=512 seek=0 conv=notrunc 
dd if=kernel.bin of=floppy.flp bs=512 seek=1 conv=notrunc

qemu-system-i386 -fda floppy.flp

редактировать:

из файла листинга nasm до усечения сообщений:

   300                                  ; Messages to print
   301 00000191 57656C636F6D652074-         welcome_string       db 'Welcome to my OS!', 0
   302 0000019A 6F204D696E6572616C-
   303 000001A3 644F532100         
   304 000001A8 507265737320616E79-         press_key_string     db 'Press any key to continue...', 0
   305 000001B1 206B657920746F2063-
   306 000001BA 6F6E74696E75652E2E-
   307 000001C3 2E00               
   308 000001C5 456E74657220796F75-         enter_message_string db 'Enter your message below',0
   309 000001CE 72206D657373616765-
   310 000001D7 2062656C6F7700     
   311 000001DE 41504D204572726F72-         APM_ERROR_string     db 'APM Error...'
   312 000001E7 2E2E2E             
   313 000001EA 2D2D2D2D2D2D2D2D2D-         basic_background     db '--------------------------------------------------------------------------------'

из файла листинга nasm после усечения сообщений:

   332                                  ; Messages to print
   333 000001E8 57656C636F6D652074-         welcome_string       db 'Welcome to MineraldOS!', 0
   334 000001F1 6F204D696E6572616C-
   335 000001FA 644F532100         
   336 000001FF 507265737320616E79-         press_key_string     db 'Press any key to continue...', 0
   337 00000208 206B657920746F2063-
   338 00000211 6F6E74696E75652E2E-
   339 0000021A 2E00               
   340 0000021C 456E74657220796F75-         enter_message_string db 'Enter your message below',0
   341 00000225 72206D657373616765-
   342 0000022E 2062656C6F7700     
   343 00000235 41504D204572726F72-         APM_ERROR_string     db 'APM Error...'
   344 0000023E 2E2E2E             
   345 00000241 2D2D2D2D2D2D2D2D2D-         basic_background     db '--------------------------------------------------------------------------------'
   346 0000024A 2D2D2D2D2D2D2D2D2D-

person Joker    schedule 08.04.2018    source источник
comment
Можете ли вы добавить строки с сообщениями из листингового файла NASM? (Параметр -l kernel.lst и скопируйте только несколько строк вокруг welcome_string) - чтобы увидеть, как он компилируется и по какому смещению они размещаются.   -  person Ped7g    schedule 08.04.2018
comment
@ Ped7g Редактировал вопрос.   -  person Joker    schedule 08.04.2018
comment
Это из версии, в которой строки уже усечены, или из версии, которая работает? Я как бы боялся, что вы пересекаете границу сектора 512 Б, но в листинге этого не говорится, последнее смещение 0x1EA все еще находится в пределах 512 Б, так что это, вероятно, что-то в коде (который я еще не читал).   -  person Ped7g    schedule 08.04.2018
comment
В коде это может быть не связано с вашей ошибкой, но использование вами int 10,0E службы является неверно, вы не устанавливаете BH на текущую страницу, и мне кажется, что может быть какое-то значение из чтения сектора, вероятно 0x10, что делает его, вероятно, работать случайно, но я не хочу копаться в коде, который написан небрежно и, вероятно, проверен, просто выполнив его и проверив вывод. Прекратите это делать, запустите его в отладчике, пошагово перебирая каждую инструкцию, и проверьте все предположения / эффекты инструкций, не полагайтесь на вывод.   -  person Ped7g    schedule 08.04.2018
comment
На самом деле еще одна важная вещь ... проверьте список kernel.lst в начале, я не верю, что директива section актуальна, поскольку вы используете формат bin для вывода, поэтому ваше ядро, скорее всего, начинается с 0000:1000 с байтами данных, а не с инструкциями , что, вероятно, является еще одной чистой удачей, поскольку вы получаете даже несколько значимый результат после выполнения данных. Смешивание section с org не имеет смысла, либо вы используете section и более сложный исполняемый формат, где компоновщик будет сортировать макет памяти в соответствии с предоставленным скриптом компоновщика, либо вы используете двоичный файл, где вам нужно разметить себя.   -  person Ped7g    schedule 08.04.2018
comment
@ Ped7g Спасибо за комментарии. Я новичок в этом и все еще учусь. Я отредактировал сообщение с файлом листинга после добавления строк кода, предыдущее было до того, как сообщения были усечены. Если я действительно перейду на 512B, что мне делать? загрузить другой сектор? и еще кое-что, я тоже новичок в Linux, и я не мог понять, как я отлаживаю сборку с помощью gdb, есть ли у вас какие-либо предложения?   -  person Joker    schedule 08.04.2018
comment
И я не совсем понял, что такое «раздел» и «организация». Не могли бы вы объяснить, что такое раздел и что мне делать? Просто стереть метку раздела .data?   -  person Joker    schedule 08.04.2018
comment
Если вы пересекаете границу сектора 512B, тогда да, тогда вам нужно загрузить более 1 сектора (вам нужно загрузить (size_of_kernel / 512) с округлением в большую сторону). Вы запускаете код загрузчика внутри виртуальной машины QEMU, поэтому вам нужен отладчик, способный отлаживать код виртуальной машины, это не так тривиально, как отладка обычного кода приложения, работающего под вашей ОС хоста (и это нетривиально), поэтому я хмуриться, когда я вижу, что люди, которые плохо знакомы со сборкой, начинают разбираться в программировании загрузчика и ядра вместо того, чтобы сначала изучать основы сборки, потому что это все равно, что утроить размер проблем при запуске.   -  person Ped7g    schedule 08.04.2018
comment
И я не занимаюсь разработкой ОС, поэтому я не знаю, как отлаживать код, работающий внутри QEMU, из других вопросов разработчика ОС здесь похоже, что запуск загрузчиков с симулятором BOCHS немного более удобен для отладки, хотя я сам не смог для настройки за 5 минут выделил на попытку. ... о разделе ... возьмем это с другой точки зрения, вы загружаете машинный код байтовых данных с диска в память, а затем выполняете его (без какой-либо пост-обработки загруженных данных), поэтому все инструкции и адреса уже определен в двоичных данных. Директива org регулирует внутренние смещения во время сборки.   -  person Ped7g    schedule 08.04.2018
comment
С другими исполняемыми форматами, такими как ELF (32 или 64 бит), в процессе сборки будут созданы первые объектные файлы, которые имеют только относительные локальные смещения внутри объектного файла, а не конечные адреса, org вообще не используется. Затем объектные файлы собираются компоновщиком, и из них собирается окончательный исполняемый файл, соединяя различные символы между разными объектными файлами, а также помещая данные и код в [иногда отдельные] области, где они принадлежат согласно сценарию компоновщика, используемому для связывания, каждого данных или часть кода определила целевой раздел директивой section, которая предназначена для компоновщика.   -  person Ped7g    schedule 08.04.2018
comment
Когда вы создаете двоичный файл, то, что вы видите в листинге: line_number address(offset) machine_code_bytes - это буквально то, что у вас есть в файле .bin (ну, только часть машинного кода, номера строк и смещения - это просто информация для вас, откуда был взят машинный код. скомпилирован, и туда, где он приземлится) ... наш kernel.bin начинается с нескольких нулей, созданных db 0, и вы будете в загрузчике jmp 0:0x1000 с этими байтами данных и выполнять их как инструкции. (поскольку для ЦП байт памяти - это байт памяти, он не может сказать, что такое код, а что такое данные, разницы нет).   -  person Ped7g    schedule 08.04.2018
comment
А в реальном режиме 16b машинный код 00 00 - это код операции инструкции add [bx+si],al ... и т. Д., Так что это то, что вы выполняете. (db не является инструкцией, это директива для выдачи байтовых значений ассемблером, поэтому, когда вам нужен какой-то байт в машинном коде со значением 13, вам не нужно вспоминать, какая инструкция имеет код операции, начинающийся с 13, но вы можете написать db 13 .. . и наоборот, мнемоника инструкций поможет вам не вспоминать, что ret есть db 195 (хотя это и работает, для большинства людей было бы слишком сложно запоминать все кодировки инструкций и записывать их в виде чисел).   -  person Ped7g    schedule 08.04.2018
comment
Спасибо за уделенное время. Я все еще учусь в старшей школе, и раньше я писал код на ассемблере [в Windows], но, по-видимому, я все еще не на 100% со всеми основами. Последний комментарий о том, что вы можете использовать db 195 вместо ret, для меня нов и довольно интересен. Это действительно помогло, спасибо большое :)   -  person Joker    schedule 08.04.2018
comment
Хм, прочтите что-нибудь о принципах / архитектуре компьютеров, о том, что такое машинный код и как кодируются инструкции по сборке ... и еще раз взгляните на файл листинга и сравните его, просматривая содержимое kernel.bin (в linux install hd = hexdump? В Ubuntu вы можете найти его в пакете bsdmainutils), чтобы увидеть, как этот машинный код в листинге является единственным содержимым, которое заканчивается в файле bin, и это то, что ЦП видит + выполнение (но в двоичном формате, поскольку ЦП работает только с битами, т. е. с электричеством текущие уровни в ячейках, которые обрабатываются как логические значения 0 или 1).   -  person Ped7g    schedule 08.04.2018
comment
Это может показаться все немного сложным и странным, но постарайтесь подумать об этом больше с точки зрения разработчика оборудования, как вы все время работаете с токами 0/1 и как все спроектировано так, чтобы быть на самом деле тупо-простым , т.е. содержимое памяти не имеет никаких флагов, если в нем хранятся инструкции, целые числа или числа с плавающей запятой, это было бы слишком сложно, чтобы иметь дело с транзисторами и т. д. после того, как вы войдете в эту машинную точку зрения, вы поймете, что Скоро выйдет вся машина и сборка на самом деле очень простой переросший детерминированный калькулятор, меняющий свое состояние каждый такт часов.   -  person Ped7g    schedule 08.04.2018
comment
Тогда большая часть этой странной сборки будет иметь гораздо больше смысла, поскольку сборка - это не столько язык программирования (логический, ориентированный на человека), сколько языки высокого уровня, поскольку он больше является зеркалом HW-конструкции процессора, поэтому он логичен с точки зрения С точки зрения размещения миллионов транзисторов на маленьком кристалле, логика программирования является вторичной в процессе, позволяя создавать приложения с помощью ЦП, но не беспокоясь, если какая-то конкретная инструкция ведет себя странно с точки зрения человеческой логики, если дизайн HW так будет более элегантно и производительно.   -  person Ped7g    schedule 08.04.2018
comment
Все, что вы сказали, имеет смысл, я узнаю больше об архитектуре :)   -  person Joker    schedule 08.04.2018


Ответы (1)


Ответьте на ваш исходный вопрос:

Это связано с тем, что ваше ядро ​​становится длиннее, и в целом оно превышает размер одного сектора диска, но вы продолжаете загружать в память только один его сектор (512 байт), поэтому остальная часть строки остается только на диске, никогда не попадая в объем памяти.

Есть также несколько других проблем (некоторые упомянутые в моих комментариях), но они не имеют отношения к усечению строки, и у меня нет настроения + время проверять весь ваш загрузчик + ядро и исправьте все ошибки, которые у вас там есть, поэтому я остановлюсь на этом (с ответом).

person Ped7g    schedule 08.04.2018