учет psp сегмента и выч. эфф. адреса

Тема в разделе "WASM.BEGINNERS", создана пользователем unregistered, 5 янв 2007.

  1. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    доброго времени суток

    ситуация (продолжаем пописывать осечку, возникли непонятки)

    есть com файл, он полностью загружен в память по адресу 0000:1000 (в общем случае 0000:ABC0)
    для того, что бы запустить тот код, надо:
    Код (Text):
    1. push 0090h
    2. push 0100h
    3. retf
    все работает... =\ не пойму, что я курил когда писал это...

    но, что бы правильно учитывались адреса, искомые сегмент:смещение
    надо привести к виду X:Y=Z:0100, X:Y - где лежит код... Z нам надо найти
    путем несложных мат. преобразований получаем:

    X*10+Y=Z*10+100
    Z=(X*10+Y-100)/10

    подставляя, Z=(0*10+1000-100)/10=F0
    и
    Код (Text):
    1. push 00F0h
    2. push 0100h
    3. retf
    ни к чему хорошему не приводит

    в общем, я в заблуждении... как правильно?

    заранее спасибо
     
  2. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Управление передается, все верно. Ошибка была совсем не в ядре/загрузчике... А в процессе. Вот код:

    Загрузчик
    Код (Text):
    1.     .model  tiny
    2.     .code
    3.  
    4.     org 100h
    5. entry:
    6.     mov ax, 7B00h
    7.     mov ss, ax
    8.     mov sp, offset stkend
    9.  
    10.     ; цель MBR - загрузить ядро в память
    11.     ; и передать ему управление
    12.     ; ядро грузим в 0000:0600, сразу
    13.     ; после таблицы прерываний
    14.  
    15.     ; каждый com-файл занимает не более
    16.     ; одной дорожки, т.е. 9 килобайт
    17.  
    18.     ; после перемещения кода из MBR в 0000:7C00
    19.     ; состояние регистров будет слелующее:
    20.     ; CS = 0
    21.     ; IP = 7C00
    22.  
    23.     ; Номер сектора, дорожки, головки вычисляется так:
    24.     ; Sector   = ( LBA % SectorsPerTrack ) + 1
    25.     ; Cylinder = ( LBA / SectorsPerTrack ) / NumHeads
    26.     ; Head     = ( LBA / SectorsPerTrack ) % NumHeads
    27.     ; LBA - Linear Block Address
    28.  
    29.     ; для дорожки после MBR значения будут:
    30.     ; Sector   = 1, т.к. всегда начинаем с первого, и нумерация идет с 1
    31.     ; Cylinder = 0
    32.     ; Head     = 1
    33.  
    34.     mov al, 12h     ; читаем 18 секторов == 1 дорожка
    35.     mov dl, 00h     ; диск A
    36.     mov dh, 01h     ; первая головка
    37.     mov ch, 00000000b   ; номер цилиндра (дорожки), kernel на 1й дорожке
    38.     mov cl, 00000001b   ; номер сектора + кусок номера
    39.                 ; цилиндра (старшие 2 байта)
    40.     mov bx, 0000h   ; адрес,
    41.     mov es, bx      ; куда читать
    42.     mov bx, 0600h   ; ядро
    43.     mov ah, 02h     ; читаем ядро
    44.     int 13h
    45.  
    46.     jc  error       ; в случае ошибки выводим сообщение
    47.  
    48.     ; подготовка передачи управления ядру
    49.     ; для передачи управления необходимо
    50.     ; установить пару CS:IP
    51.  
    52.     push    0050h   ; записываем CS
    53.     push    0100h   ; записываем IP
    54.     retf        ; передаем управление
    55.  
    56. error:
    57.     mov ah, 0Eh
    58.     mov bh, 00h
    59.     mov al, 'M'
    60.     int 10h
    61.  
    62. loop1:  jmp loop1
    63.  
    64. stk db  10 dup(0)
    65. label   stkend
    66.  
    67. end entry
    Ядро
    Код (Text):
    1.     .model  tiny
    2.     .code
    3.  
    4.     org 100h
    5.  
    6. entry:
    7.     ; ядро приняло управление
    8.  
    9.     ; заводим стек
    10.     mov ax, cs
    11.     mov ss, ax
    12.     mov sp, offset stkend
    13.  
    14.     ; выводим буковку K, от kernel
    15.     mov ah, 0Eh
    16.     mov bh, 00h
    17.     mov al, 'K'
    18.     int 10h
    19.  
    20.     mov [byte ptr cnt], 00h
    21. lprcs:
    22.  
    23.     ; вычисляем номер цилиндра и головки
    24.     mov al, [byte ptr cnt]
    25.     add al, 03h
    26.     mov ah, 00h
    27.     mov dl, 02h
    28.     div dl
    29.     mov [byte ptr cyl], al
    30.     mov [byte ptr head], ah
    31.  
    32.     ; вычисляем адрес процесса в памяти
    33.     ; в рассчете, что под процесс выделяется 1280 байт
    34.     ; отсчет начинается с 0000:1000
    35.     mov ax, 0500h
    36.     mov dl, [byte ptr cnt]
    37.     mov dh, 00h
    38.     mul dx
    39.     add ax, 1100h
    40.     mov [word ptr addr], ax
    41.  
    42.     mov al, 12h         ; читаем 18 секторов == 1 дорожка
    43.     mov dl, 00h         ; диск A
    44.     mov dh, [byte ptr head] ;
    45.     mov ch, [byte ptr cyl]  ; номер цилиндра (дорожки), kernel на 1й дорожке
    46.     mov cl, 00000001b       ; номер сектора + кусок номера
    47.                     ; цилиндра (старшие 2 байта)
    48.     mov bx, 0000h       ; адрес,
    49.     mov es, bx          ; куда читать
    50.     mov bx, 1000h       ; ядро
    51. ;   mov bx, [word ptr addr] ; смещение в addr=1100+500*i
    52.     mov ah, 02h
    53.     int 13h         ; читаем ядро
    54.  
    55.     jc  error
    56.  
    57.     inc [byte ptr cnt]
    58.     cmp [byte ptr cnt], 05h
    59.     jne lprcs
    60.  
    61.     ; запускаем тестовый процесс (6й по счету)
    62.     push    00F0h
    63.     push    0100h
    64.     retf
    65.  
    66.     ; ошибка чтения с диска
    67. error:  mov ah, 0Eh
    68.     mov bh, 00h
    69.     mov al, 'E'
    70.     int 10h
    71. loop1:  jmp loop1
    72.  
    73. head    db  1
    74. cyl db  1
    75. cnt db  1
    76. addr    dw  1
    77.  
    78. stk db  128 dup(0)
    79. label   stkend
    80.  
    81. end entry
    Тестовый процесс
    Код (Text):
    1.     .model  tiny
    2.     .code
    3.  
    4.     org 100h
    5. entry:
    6.     mov ax, cs
    7.     mov ss, ax
    8.     mov sp, offset stkend
    9.  
    10.     mov [word ptr tl], 0000h
    11.     mov [word ptr th], 0000h
    12.  
    13. loop1:
    14.     ; тики будут находиться в cx:dx
    15.     mov ah, 00h
    16.     int 1Ah
    17.  
    18.     mov ax, cx
    19.     mov bx, dx
    20.  
    21.     ; ax:bx
    22.     ; cx:dx
    23.     sub bx, [word ptr tl]
    24.     sbb ax, [word ptr th]
    25.     cmp bx, 0050h
    26.     jb  loop1
    27.  
    28.     mov [word ptr tl], dx
    29.     mov [word ptr th], cx
    30.  
    31.     mov ah, 0Eh
    32.     mov bh, 00h
    33.     mov al, '6'
    34.     int 10h
    35.  
    36.     jmp loop1
    37.  
    38. tl  dw  1
    39. th  dw  1
    40. stk db  92 dup(0)
    41. label   stkend
    42.  
    43. end entry
    Экспериментально установил, что стек в моем случае должен быть как минимум 92 байта. Или так и надо, или я что-то недосмотрел. Почему так?

    В аттаче весь код + образ
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Ну ты думаешь что прерывания BIOS не используют стек?
     
  4. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Используют, ясен красен. В моем случае каждый int сбросит по три слова (cp,ip,flags), но вот почему аж 92 байта надо? Не думал, что так много...
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    unregistered
    Я имею ввиду, не сам вызов прерывания, а код обработчика, он же по идее использует тот же стек, который ты установил вначале, и в нём могут как раз и использоваться эти байты.
    Не было бы сессии на носу посмотрел бы, а так...