You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复汇编代码中的‘error: invalid combination of opcode and operands’错误?

Fixing the "invalid combination of opcode and operands" Error in Your Bootloader

Let's break down the issues with your code and fix them step by step:

1. Resolve the Compilation Error (Line 16)

The error on line 16 (mov si,prompt) is likely due to one of two scenarios:

  • Assembler-specific address syntax: If you're using MASM/TASM instead of NASM, you need to explicitly use offset to fetch the address of a label:
    mov si, offset prompt
    
    For NASM, the original line should work, but if you still hit the error, try replacing lea si,string with mov si,string—since you only need the buffer's starting address, lea is unnecessary here.
  • Unterminated string: While this is a runtime issue, some assemblers throw unexpected errors when parsing strings without a null terminator. We'll fix this next.

2. Critical Runtime Fixes (Even If They Don't Break Compilation)

Your bootloader has a few issues that will fail at runtime, even after fixing the compilation error:

A. Null-Terminate All Strings

Your print_string function stops when it hits a 0 byte, but your prompt string doesn't have one. Add a null terminator to avoid infinite loops:

prompt db "Hello>", 0

B. Replace DOS Interrupt int 21h with BIOS Interrupt

int 21h is a DOS-specific interrupt, which doesn't exist in the raw BIOS environment where bootloaders run. Use the BIOS keyboard interrupt int 16h instead to read keystrokes. Here's a fixed read_string function with backspace support:

read_string:
.repeat:
    mov ah, 00h        ; int 16h function 0: read raw keystroke
    int 16h             ; Get key into AX (AL = ASCII char, AH = scan code)
    cmp al, 0x0D        ; Check if it's Enter (carriage return)
    je .done            ; Exit loop if Enter is pressed
    cmp al, 0x08        ; Check if it's Backspace
    je .backspace
    mov [si], al        ; Store character in buffer
    mov ah, 0Eh         ; Echo the character to screen
    int 10h
    inc si              ; Move buffer pointer forward
    jmp .repeat
.backspace:
    cmp si, string      ; Don't backspace past the buffer start
    je .repeat
    dec si
    mov byte [si], 0    ; Clear the deleted character
    mov ah, 0Eh         ; Erase character on screen (backspace + space + backspace)
    mov al, 0x08
    int 10h
    mov al, ' '
    int 10h
    mov al, 0x08
    int 10h
    jmp .repeat
.done:
    mov byte [si], 0    ; Null-terminate the input string
    ret

C. Proper Newline Handling

BIOS expects both carriage return (13) and line feed (10) for a proper newline. Update your eol definition:

eol db 13,10,0

Fixed Full Code

Here's the complete corrected bootloader code:

BITS 16
jmp short bootloader_start
nop

bootloader_start:
    mov ax, 07C0h        ; Set up 4K of stack space above buffer
    add ax, 544          ; 8k buffer = 512 paragraphs + 32 paragraphs (loader)
    ;cli                 ; Disable interrupts while changing stack
    mov ss, ax
    mov sp, 4096
    ;sti                 ; Restore interrupts

    mov ax, 07C0h        ; Set data segment to where we're loaded
    mov ds, ax

    mov si,prompt
    call print_string

    mov si,string
    call read_string

    mov si, string
    call print_string

print_string:
    ; Routine: output string in SI to screen
    ;pusha
    mov ah, 0Eh         ; int 10h 'print char' function
.repeat:
    lodsb               ; Get character from string
    cmp al, 0
    je .main_done       ; If char is zero, end of string
    int 10h             ; Otherwise, print it
    jmp .repeat

.main_done:
    mov si,eol
.eol_repeat:
    lodsb               ; Get character from string
    cmp al, 0
    je .done            ; If char is zero, end of string
    int 10h             ; Otherwise, print it
    jmp .eol_repeat

.done:
    ;popa
    ret

read_string:
.repeat:
    mov ah, 00h        ; int 16h function 0: read raw keystroke
    int 16h             ; Get key into AX (AL = ASCII char, AH = scan code)
    cmp al, 0x0D        ; Check if it's Enter (carriage return)
    je .done            ; Exit loop if Enter is pressed
    cmp al, 0x08        ; Check if it's Backspace
    je .backspace
    mov [si], al        ; Store character in buffer
    mov ah, 0Eh         ; Echo the character to screen
    int 10h
    inc si              ; Move buffer pointer forward
    jmp .repeat
.backspace:
    cmp si, string      ; Don't backspace past the buffer start
    je .repeat
    dec si
    mov byte [si], 0    ; Clear the deleted character
    mov ah, 0Eh         ; Erase character on screen
    mov al, 0x08
    int 10h
    mov al, ' '
    int 10h
    mov al, 0x08
    int 10h
    jmp .repeat
.done:
    mov byte [si], 0    ; Null-terminate the input string
    ; Print newline after input
    mov si, eol
.eol_loop:
    lodsb
    cmp al, 0
    je .read_done
    mov ah, 0Eh
    int 10h
    jmp .eol_loop
.read_done:
    ret

eol db 13,10,0          ; Carriage return + line feed + null terminator
prompt db "Hello>", 0    ; Null-terminated prompt string
string times 80 db 0
times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
dw 0xAA55               ; The standard PC boot signature

内容的提问来源于stack exchange,提问作者Dorian Niemiec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:01:26