Suche…


BIOS-Aufrufe

So interagieren Sie mit dem BIOS

Das grundlegende Eingabe- / Ausgabesystem (BIOS) steuert den Computer, bevor ein Betriebssystem ausgeführt wird. Um auf vom BIOS bereitgestellte Dienste zuzugreifen, verwendet der Assemblycode Interrupts . Ein Interrupt hat die Form von

int <interrupt> ; interrupt must be a literal number, not in a register or memory

Die Interruptnummer muss zwischen 0 und 255 (einschließlich 0x00 - 0xFF) liegen.

Die meisten BIOS-Aufrufe verwenden das AH Register als "Funktionsauswahl" -Parameter und das AL Register als Datenparameter. Die von AH gewählte Funktion hängt von dem aufgerufenen Interrupt ab. Einige BIOS-Aufrufe erfordern einen einzigen 16-Bit-Parameter in AX oder akzeptieren keine Parameter und werden einfach vom Interrupt aufgerufen. Einige haben noch mehr Parameter, die in anderen Registern übergeben werden.

Die für BIOS-Aufrufe verwendeten Register sind festgelegt und können nicht mit anderen Registern ausgetauscht werden.

Verwenden von BIOS-Aufrufen mit Funktionsauswahl

Die allgemeine Syntax für einen BIOS-Interrupt unter Verwendung eines Funktionsauswahlparameters lautet:

mov ah, <function>
mov al, <data>
int <interrupt>

Beispiele

So schreiben Sie einen Buchstaben auf das Display:

mov ah, 0x0E             ; Select 'Write character' function
mov al, <char>           ; Character to write
int 0x10                 ; Video services interrupt

So lesen Sie ein Zeichen von der Tastatur (sperren):

mov ah, 0x00             ; Select 'Blocking read character' function
int 0x16                 ; Keyboard services interrupt
mov <ascii_char>, al     ; AL contains the character read
mov <scan_code>, ah      ; AH contains the BIOS scan code

So lesen Sie einen oder mehrere Sektoren von einem externen Laufwerk (mit CHS-Adressierung):

mov ah, 0x02             ; Select 'Drive read' function
mov bx, <destination>    ; Destination to write to, in ES:BX
mov al, <num_sectors>    ; Number of sectors to read at a time
mov dl, <drive_num>      ; The external drive's ID
mov cl, <start_sector>   ; The sector to start reading from
mov dh, <head>           ; The head to read from
mov ch, <cylinder>       ; The cylinder to read from
int 0x13                 ; Drive services interrupt
jc <error_handler>       ; Jump to error handler on CF set

So lesen Sie das System RTC (Real Time Clock):

mov ah, 0x00             ; Select 'Read RTC' function
int 0x1A                 ; RTC services interrupt
shl ecx, 16              ; Clock ticks are split in the CX:DX pair, so shift ECX left by 16...
or cx, dx                ; and add in the low half of the pair
mov <new_day>, al        ; AL is non-zero if the last call to this function was before midnight
                         ; Now ECX holds the clock ticks (approx. 18.2/sec) since midnight
                         ; and <new_day> is non-zero if we passed midnight since the last read

So lesen Sie die Systemzeit aus dem RTC:

mov ah, 0x02             ; Select 'Read system time' function
int 0x1A                 ; RTC services interrupt
                         ; Now CH contains hour, CL minutes, DH seconds, and DL the DST flag,
                         ; all encoded in BCD (DL is zero if in standard time)
                         ; Now we can decode them into a string (we'll ignore DST for now)

mov al, ch               ; Get hour
shr al, 4                ; Discard one's place for now
add al, 48               ; Add ASCII code of digit 0
mov [CLOCK_STRING+0], al ; Set ten's place of hour
mov al, ch               ; Get hour again
and al, 0x0F             ; Discard ten's place this time
add al, 48               ; Add ASCII code of digit 0 again
mov [CLOCK_STRING+1], al ; Set one's place of hour

mov al, cl               ; Get minute
shr al, 4                ; Discard one's place for now
add al, 48               ; Add ASCII code of digit 0
mov [CLOCK_STRING+3], al ; Set ten's place of minute
mov al, cl               ; Get minute again
and al, 0x0F             ; Discard ten's place this time
add al, 48               ; Add ASCII code of digit 0 again
mov [CLOCK_STRING+4], al ; Set one's place of minute

mov al, dh               ; Get second
shr al, 4                ; Discard one's place for now
add al, 48               ; Add ASCII code of digit 0
mov [CLOCK_STRING+6], al ; Set ten's place of second
mov al, dh               ; Get second again
and al, 0x0F             ; Discard ten's place this time
add al, 48               ; Add ASCII code of digit 0 again
mov [CLOCK_STRING+7], al ; Set one's place of second
...
db CLOCK_STRING "00:00:00", 0   ; Place in some separate (non-code) area

So lesen Sie das Systemdatum aus dem RTC:

mov ah, 0x04             ; Select 'Read system date' function
int 0x1A                 ; RTC services interrupt
                         ; Now CH contains century, CL year, DH month, and DL day, all in BCD
                         ; Decoding to a string is similar to the RTC Time example above

So erhalten Sie die Größe des zusammenhängenden niedrigen Speichers:

int 0x12                 ; Conventional memory interrupt (no function select parameter)
and eax, 0xFFFF          ; AX contains kilobytes of conventional memory; clear high bits of EAX
shl eax, 10              ; Multiply by 1 kilobyte (1024 bytes = 2^10 bytes)
                         ; EAX contains the number of bytes available from address 0000:0000

So starten Sie den Computer neu:

int 0x19                 ; That's it! One call. Just make sure nothing has overwritten the
                         ; interrupt vector table, since this call does NOT restore them to the
                         ; default values of normal power-up. This means this call will not
                         ; work too well in an environment with an operating system loaded.

Fehlerbehandlung

Einige BIOS-Aufrufe werden möglicherweise nicht auf jedem Computer implementiert und es kann nicht garantiert werden, dass sie funktionieren. Häufig gibt ein nicht implementierter Interrupt im Register AH entweder 0x86 oder 0x80 zurück. Bei fast jedem Interrupt wird das Übertragsflag (CF) auf einen Fehlerzustand gesetzt. Dies macht es leicht, mit dem bedingten Sprung jc zu einem Fehlerhandler zu springen. (Siehe Bedingte Sprünge )

Verweise

Eine ziemlich vollständige Liste der BIOS-Aufrufe und anderer Interrupts ist die Interrupt-Liste von Ralf Brown . Eine HTML-Version finden Sie hier .

Interrupts, von denen angenommen wird, dass sie verfügbar sind, finden Sie in einer Liste auf Wikipedia .

Eine umfassendere Übersicht über allgemein verfügbare Interrupts finden Sie unter osdev.org



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow