为什么不打印 X?集会
Why doesnt this print X? Assembly
为什么这个程序不打印 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
... to make it print a spade as output.
...现在我真的帮不了你了,因为我不知道 ♠️ 字符的确切十六进制->ASCII 值...虽然,我可以帮助您了解如何打印 standard(击键)ASCII 字符的简单步骤。
这是完整的 NASM 示例,说明如何将字符打印到显示器;我会将其分解为 视频显示特定 块,以帮助您更好地理解该过程(请注意我只使用了 REAL示例中的MODE汇编指令(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...
好的,这就是将字符打印到 monitor/display...
的全部内容
显示 printing/displaying 个字符的大多数 common/efficient 方法:
;========================================================
; 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
) and/or 恢复 (pop
) 到 AX
寄存器。
mov ah, 0x0E
这非常简单...它将值 0x0E
分配给 AH
这是 int 0x10
的 Teletype Output Function。
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
那么在 .output16_char_array_done
处执行代码...如果 [AL]
是 不 等于0x00
继续执行代码...
jmp .output16_char_array_loop
循环或迭代某个function/handle而不使用[=34]的简单方法=] 指令(loop
需要更多的硬件资源来执行,因此尽量避免使用此指令,除非它在 您的 特定情况下更有效。
ret
一个简单的指令 return 到前一个(调用)内存地址。
int 0x10
这是BIOS Interrupt Handle for Video Services
为什么这个程序不打印 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
... to make it print a spade as output.
...现在我真的帮不了你了,因为我不知道 ♠️ 字符的确切十六进制->ASCII 值...虽然,我可以帮助您了解如何打印 standard(击键)ASCII 字符的简单步骤。
这是完整的 NASM 示例,说明如何将字符打印到显示器;我会将其分解为 视频显示特定 块,以帮助您更好地理解该过程(请注意我只使用了 REAL示例中的MODE汇编指令(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...
好的,这就是将字符打印到 monitor/display...
显示 printing/displaying 个字符的大多数 common/efficient 方法:
;========================================================
; 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
) and/or 恢复 (pop
) 到 AX
寄存器。
mov ah, 0x0E
这非常简单...它将值 0x0E
分配给 AH
这是 int 0x10
的 Teletype Output Function。
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
那么在 .output16_char_array_done
处执行代码...如果 [AL]
是 不 等于0x00
继续执行代码...
jmp .output16_char_array_loop
循环或迭代某个function/handle而不使用[=34]的简单方法=] 指令(loop
需要更多的硬件资源来执行,因此尽量避免使用此指令,除非它在 您的 特定情况下更有效。
ret
一个简单的指令 return 到前一个(调用)内存地址。
int 0x10
这是BIOS Interrupt Handle for Video Services