Почему здесь не отображается X? сборка

Почему эта программа не печатает X? Может ли кто-нибудь объяснить шаг за шагом, что происходит, чтобы заставить его печатать лопату в качестве вывода.

mov ah, 0x0e ; Set higher bit of ax to 0e (probably the instruction opcode)
mov al, the_secret ; Set lower bit of ax to bytes of H
int 0x10

the_secret:
    db 'X'

jmp $ ;Jump to the current address forever

; Padding

times 510 - ($-$$) db 0

dw 0xaa55

person Raees Rajwani    schedule 19.11.2016    source источник
comment
Я думаю, вы хотите [the_secret] (обратите внимание на скобки). Вы также должны установить регистр сегмента DS на то, что вы ожидаете. У вас нет директивы ORG, и мы не видим ваших команд для создания загрузчика, поэтому я не могу с уверенностью сказать, какое значение вы должны указать в DS. Если вы используете nasm с -f bin, тогда ваша ORG по умолчанию будет 0x0000. В этом случае вам следует переместить 0x07c0 в DS с чем-то вроде mov ax, 0x07c0 mov ds, ax в качестве первой части вашего загрузчика.   -  person Michael Petch    schedule 19.11.2016
comment
Под [the_secret] я имел в виду то, что инструкция должна была выглядеть как mov al, [the_secret], поскольку вы хотели получить байт по адресу памяти the_secret и поместить его в AL, а не помещать адрес памяти в AL   -  person Michael Petch    schedule 19.11.2016
comment
И если у вас есть ORG 0x7c00 в вашем коде, но вы просто не указали его в своем вопросе, вы хотите поместить значение 0 в DS.   -  person Michael Petch    schedule 19.11.2016
comment
Еще одна проблема. Вы должны поместить jmp $ перед вашими данными и после int 0x10, иначе ЦП попытается выполнить the_secret как код.   -  person Michael Petch    schedule 19.11.2016


Ответы (1)


... чтобы он напечатал лопату в качестве вывода.

... теперь я не могу вам помочь, так как я не знаю точное значение Hex- ›ASCII для символа ♠ ️ ... хотя я могу помочь вам понять простые шаги в том, как напечатать стандартный (нажатие клавиши) символ ASCII.

Вот полный NASM пример того, как печатать символы на дисплее монитора; Я разделю его на части, относящиеся к отображению видео, чтобы помочь вам лучше понять процесс (обратите внимание, что я использовал только РЕАЛЬНЫЙ РЕЖИМ инструкции по сборке (16 бит) в примере):

[bits   16]                                             ; Declare CPU Instructions as [REAL_MODE]
[org    0x0000]                                         ; Organize Memory to Start @ [0x0000]
                                                        ; We'll Manually setup Memory Organization Later...


jmp _glEntry                                            ; Relocate to Function:



;========================================================
; This Function Prints an Entire Character Stream until
; NULL Terminated Hex Character (0x00) is Detected...
;========================================================
output16_char_array:                                    ; Legacy BIOS Output CHAR_STREAM Function
    ;push   ax                                          ; Store [AX] Register to [STACK_SPACE]
    xor ax, ax                                          ; Zero [AX] Register
    mov ah, 0x0E                                        ; Assign [0x0E] to [AX] : (Legacy BIOS Function Code for BIOS Display)
                                                        ; Continue Code Execution:
    .output16_char_array_loop:
        lodsb                                           ; Collect Single Byte from [DS:SI] and increment SI by 1 : ([AL] = [DS:SI]; inc [SI])
        or  al, al                                      ; Check Whether [AL] is [0x00]
        jz  .output16_char_array_done                   ; [AL] == [0x00] Proceed to Function:
        int 0x10                                        ; [AL] != [0x00] Continue to Display Hex->ASCII [CHAR]
        jmp .output16_char_array_loop                   ; Relocate [CS] to create an Infinite Loop...
    
    .output16_char_array_done:
        ;pop    ax                                      ; Restore [AX] Register from [STACK_SPACE]
        ret                                             ; Return to Calling [CS] Memory Position...



;========================================================
; For Simplicity I've created a Single Character Output
; Method, but in the form of a MACRO
;
; There is really no difference in the method if Output
; other than that this method only prints a single
; Character and doesn't require a NULL Terminated Hex
; Character (0x00) for EndOf(..) CHAR_STREAM...
;========================================================
%macro  output16_char_byte  1                           ; Define Macro with a single input method...
    ;push   ax                                          ; Store [AX] Register to [STACK_SPACE]
    xor ax, ax                                          ; Zero [AX] Register
    mov ah, 0x0E                                        ; Assign [0x0E] to [AH] : (Legacy BIOS Function Code for BIOS Display)
    mov al, %1                                          ; Assign [MACRO_INPUT] to [AL] : (Refer to ['%macro output16_char_byte <..>'])
    int 0x10                                            ; Legacy BIOS Interrupt for Teletype Output
    xor ax, ax                                          ; Zero [AX] Register
    ;pop    ax                                          ; Restore [AX] Register from [STACK_SPACE]
%endmacro                                               ; End of ['output16_char_byte'] Macro


WELCOME_MSG db  "Hello, World!",    0x0D,   0x0A,   0x00



;========================================================
; This Function is the Entry Point for the Global Master
; Boot Record
;========================================================
_glEntry:
    cli                                                 ; Disable CPU Interrupts
    xor ax, ax                                          ; Zero [AX] Register
    mov ax, 0x07E0                                      ; Assign [0x07E0] to [AX] : (0x07E0)
    mov ss, ax                                          ; Assign [AX] to [SS] : ([AX]*[0x0010]) : (0x7E00)
    mov sp, 0x1000                                      ; Assign [0x1000] to [SP] : (0x1000) ([0x07E0]:[0x1000])
    sti                                                 ; Enable CPU Interrupts
                                                        ; Continue Code Execution:
    xor ax, ax                                          ; Zero [AX] Register
    mov ax, 0x07C0                                      ; Assign [0x07C0] to [AX] : (0x07C0)
    mov ds, ax                                          ; Assign [AX] to [DS] : ([AX]*[0x0010]) : (0x7C00)
                                                        ; Continue Code Execution:
    mov si, WELCOME_MSG                                 ; Assign [WELCOME_MSG] to [SI] : (0x[....])
    call    output16_char_array                         ; Call our Output [CHAR_STREAM] Function
    
    mov si, WELCOME_MSG                                 ; Assign [WELCOME_MSG] to [SI] : (0x[....])
    output16_char_byte  BYTE    [ds:si+0x0008]          ; Assign (BYTE) [DS:SI+0x0008] to Macro Input Method...
                                                        ; we should have the (9th - 1) letter from [WELCOME_MSG] 'o'
    
                                                        ; Continue Code Execution on Return:
    xor ax, ax                                          ; Zero [AX] Register
    int 0x16                                            ; Call BIOS Await Keystroke Interrupt
    xor ax, ax                                          ; Zero [AX] Register
    int 0x19                                            ; Call BIOS Reboot Interrupt
                                                        ; Continue Code Execution if interrupts fail...
    cli                                                 ; Disable CPU Interrupts
    hlt                                                 ; Halt CPU Execution:



times   510 - ( $ - $$ )    db  0x00                    ; Pad [BOOTSECTOR] with [0x00] up to 510 Bytes...
dw  0xAA55                                              ; Assign [MAGIC_MBR] Value...

Хорошо, это все, как можно было бы печатать символы на мониторе / дисплее ... < img src = "https://i.stack.imgur.com/YLKXv.png" alt = "вот фото-свидетельство истинного результата:" />

Наиболее распространенный / эффективный метод печати / отображения символа (ов) на дисплее:

;========================================================
; This Function Prints an Entire Character Stream until
; NULL Terminated Hex Character (0x00) is Detected...
;========================================================
output16_char_array:                                    ; Legacy BIOS Output CHAR_STREAM Function
    ;push   ax                                          ; Store [AX] Register to [STACK_SPACE]
    xor ax, ax                                          ; Zero [AX] Register
    mov ah, 0x0E                                        ; Assign [0x0E] to [AX] : (Legacy BIOS Function Code for BIOS Display)
                                                        ; Continue Code Execution:
    .output16_char_array_loop:
        lodsb                                           ; Collect Single Byte from [DS:SI] and increment SI by 1 : ([AL] = [DS:SI]; inc [SI])
        or  al, al                                      ; Check Whether [AL] is [0x00]
        jz  .output16_char_array_done                   ; [AL] == [0x00] Proceed to Function:
        int 0x10                                        ; [AL] != [0x00] Continue to Display Hex->ASCII [CHAR]
        jmp .output16_char_array_loop                   ; Relocate [CS] to create an Infinite Loop...

    .output16_char_array_done:
        ;pop    ax                                      ; Restore [AX] Register from [STACK_SPACE]
        ret                                             ; Return to Calling [CS] Memory Position...

Я хотел бы отметить, что я прокомментировал push ax & pop ax, поскольку эти инструкции не требуются в этом простом примере. Хотя (не по теме) эти инструкции просто преобразуют хранилище стека памяти (push) и / или восстанавливают (pop) в регистр AX.

mov ah, 0x0E это довольно просто ... он присваивает значение 0x0E AH это Функция вывода телетайпа для int 0x10.

lodsb это более эффективный способ предварительной формовки:

mov    al,    BYTE    [SI]           ; Assign Single [BYTE] from [SI] to [AL]
inc    si                            ; Increment [SI] by 1 equivalent to [SI]++

or al, al проверяет, равно ли [AL] 0x00. Это NULL завершающий символ символьного потока.

jz .output16_char_array_done если [AL] равно 0x00, тогда выполнить код на _21 _... если [AL] не равно 0x00 продолжить выполнение кода ...

jmp .output16_char_array_loop простой способ цикла или итерации определенной функции / дескриптора без использования инструкции loop (loop требует больше аппаратных ресурсов для выполнения, поэтому старайтесь избегать этой инструкции, если она больше эффективно в ваших конкретных обстоятельствах).

ret простая инструкция для возврата к предыдущему (вызывающему) адресу памяти.

int 0x10 это обработчик прерывания BIOS для видеосервисов

person EchoXTeknology    schedule 24.11.2020