Функция х86-16 01 -> изменить пункт назначения и/или отображения страниц


Этот код предназначен для включения с архитектурой x86-16 письменном виде ASCIIZ строк сразу к видео и зависит от некоторых заявлений в этой код. В сочетании с этим код строки заявленных @ 1000:0 в следующем порядке будет;

AscTxt:  db  01, 84H                           ; View page 0 output to 4
         db  'This is an example', 01, 40H     ; View page 4 output to 0
         db  'This is replacing whatever is on top line of page 0'
         db  0, 01, 0FH, 0, 0   ; Waits for response then view page 0

В качестве примера, давайте начнем с этого.

Page 0

Это следующая вещь, которую вы увидите после ввода .Комманд именем функции @ Prompt.

enter image description here

Обратите внимание, как курсор не перемещается в ЭОС. То есть по дизайну. Затем после нажатия любой клавиши, кроме Esc, что мы будем вернуться к странице 0 с верхней линии заменяются.

enter image description here

; =============================================================================================
;    Change display and/or destination page

;   ENTER:  00  -     7 = Set do not change current page being displayed
;                   6-4 = Display page. Ignored if equal to active or but 7 set
;                     3 = Set, do not change display page
;                   2-0 = Destination page. Ignored if already pointing there or bit 3 set.

;   LEAVE:   DI = New pointer when applicable
;            DX = volatile, all others unchanged.

;   FLAGS:  Undefined
; ---------------------------------------------------------------------------------------------

    F01:    cmp     al, 1
            jnz     F02
            lodsb                       ; Read only parameter for this function

    ; Real mode has a few limitations in addressing far data, so this just seems to be the
    ; most practical way of addressing data in BDA

            push    bx

    ; Test bit 7 to determine if display page should be changed. If so, then bits 6-4 are
    ; ignored.

            test    al, 10000000B       ; Is bit 7 on
            jnz     .cDest              ; if so we are not changing display page

            push    ax                  ; Still going to need low nibble
            shr     ax, 4               ; Shift page number into low nibble
            cmp     al, [fs:DispPg]     ; Check BDA if anything actually needs done
            jz      .cDest - 1          ; Already on that page

    ; The intent of procedurd e as a whole is to avoid BIOS as much as possible, but I
    ; did not want to implement code to manipulate controller.

            mov     ah, SAP
            int     VIDEO
            pop     ax                  ; Restore value in low nibble

   .cDest:  test    al, 1000B           ; Is bit 3 on
            jnz     .exit               ; if so we are not changing destination page            ; Return to instruction just before label .next

    ; Check if there is any need to do anything by determining if destination video segment
    ; is already being pointed too.

            and     al, 7
            mov     dx, es              ; Get current video segment
            mov     dl, al
            add     dl, 0B8H
            cmp     dh, dl              ; ZF will be set if same segments
            jz      .exit

    ; Set new segment and then determine offset based on that pages cursor position from
    ; x/y coordinates specified in BDA.

            shl     dx, 8
            mov     es, dx              ; Set new segment

    ; Caret position of new page or even one that has been written to before is assumed
    ; to be the starting point of next write.

            mov     bx, Cursors         ; Point to beginning of array of vectors
            shl     ax, 1
            add     bl, al
            mov     dx, [bx]                ; Points into arrary of vectors in BDA

            mov     di, dx              ; Just in case we are already at 0,0.
            or      dx, dx
            jz      .exit

    ; If position is top/left, not much point multiplying by zero

            mov     al, dh
            imul    ax, 80              ; 80 x 25 x 16 color assumed
            and     di, 0FFH
            add     di, ax
            shl     di, 1               ; ES:DI set to new page & offset

    ; Restore non-volatile

    .exit:  pop     bx
            ret

      F02:  ret


113
1
задан 6 февраля 2018 в 11:02 Источник Поделиться
Комментарии
1 ответ

Первоначальный комментарий: не понятно, что входит (за вычетом он о байт [ds:si]) и я бы предпочел использовать "аргументы" или "ввод" слово. Не понятно описание про биты. Не все аргументы описаны (код использует также ds:si адрес lodsb). Опечатки. Модифицированные регистры являются неполными тоже (опять же si). И т. д..


F01:    cmp     al, 1
jnz F02

Почему имя нравится F01? Это было просто для этого обзора, или это фактическое этикетке? Лучше использовать что-то более описательное.


Почему функция заканчивается, когда al не равно 1? Что следует упомянуть в описании, что al должно быть 1 чтобы заставить его работать.


Я бы двигаться push bx гораздо ближе к той области, где он изменяется, поэтому он может быть легко видно с глаз, где весь push/pop блок, и пядь за меньшее количество точками "ветвления" (которое всегда подвержено ошибкам, чтобы сохранить правильный стек по некоторым ветвления). Вы можете на самом деле окружают лишь несколько инструкций с push/pop bxне имея никакого ветвления на всех.


        push    ax                  ; Still going to need low nibble
shr ax, 4 ; Shift page number into low nibble
cmp al, [fs:DispPg] ; Check BDA if anything actually needs done
jz .cDest - 1 ; Already on that page

Баг: если ah содержит некоторые младшие биты, вы получите неправильным отображением страницы значение. Должно быть shr al,4 вместо.

Почему .cDest-1? Во-первых, почему cDestэто не английский, а почему -1, вы находитесь на x86 мощная машина, нет абсолютно никаких причин, чтобы сохранить байт на символ имена или количество символов. 1988 называют, они хотят ваши привычки обратно.


Еще несколько опечаток... у тебя нет проверки орфографии в Редакторе? :-О (я использую простые Кейт источников в NASM, и Shift+сочетание клавиш Ctrl+O будет переключить проверку орфографии вкл/выкл, так что не беспокоить меня по инструкции, но я могу использовать его для просмотра комментариев время от времени).


        mov     ah, SAP
int VIDEO

Это не будет компилироваться, необходимо обеспечить рабочего источника для просмотра. Построив его самостоятельно, прежде чем отправлять вам помешает какой-то несчастный случай, как больше, чем ты хочешь. Также я понятия не имею, что это SAP или VIDEOтак нет способа, чтобы рассмотреть его и ставить какие-либо советы на этот счет. За исключением стоп, используя загадочные короткие имена символ, который не может быть понято, читая, как обычный английский.


        mov     bx, Cursors         ; Point to beginning of array of vectors
shl ax, 1
add bl, al

Делать просто shl al, 1 если вы используете только al позже. Это сначала выглядит как ошибка для меня, потому что у вас есть что-нибудь в ahтогда я понял, что вы избежите, что с помощью al только.

На самом деле это не удастся, если Cursors массив насчитывает более 256Б границы, затем add bl,al будет производить неправильный адрес.

Но ты не показал как ты определяешь Cursorsвозможно, вы уверены, что это хорошо согласуется и будет всегда вписываются в 256Б "страницы".

Еще может считать более надежной версии, делаете все and ax,7 add ax,ax add bx,ax для расчета с полным 16в значения.


И весь набор курсоров код-это немного подозрительно, я имею в виду расчет di основываясь на [Х, Y], у тебя есть такой код уже где-то?

Вы платите за скорость, что вы не можете себе позволить назвать это? (наверное, нет, а вы все еще в реальном режиме)

Также imul ax, 80 опять же рискованно, как вы не определите ah содержание (будет работать с моим модификации выше and ax,7).

Я бы, наверное, написать отдельную подпрограмму для расчета di на основе [x, y] координаты, как например:

; input: dh:dl = y:x of cursor
; output: di = text mode offset for cursor position
getDiForCursorPosition:
push dx
movzx di, dh ; di = y
imul di, 80 ; di = 80 * y
movzx dx, dl ; dx = x
add di, dx ; di = 80 * y + x
add di, di ; di = (80 * y + x) * 2
pop dx
ret

И использовать, что отовсюду (после того, как вы будете проверять его работоспособность, я не отлаживать его :) ).

-1
ответ дан 7 февраля 2018 в 08:02 Источник Поделиться