assembly x86 nasm bare-metal real-mode

assembly - ¿Cómo escribir en la pantalla con la dirección de memoria de video 0xb8000 desde el modo real?



x86 nasm (1)

Al escribir en la memoria de video (comenzando @ 0xb8000 ), hay 2 bytes por cada celda en la pantalla. El carácter a mostrar está en el primer byte y el atributo en el segundo. Para imprimir un carácter rojo (código de color 0x40) espacio (0x20) en la primera celda de la pantalla, los bytes deben colocarse en la memoria de esta manera:

0xb800:0x0000 : 0x20 ; ASCII char for 0x20 is '' '' 0xb800:0x0001 : 0x40 ; Red background, black foreground

En tu código, parece que intentaste hacer esto con un código como:

mov al,0x40 ;colour mov ah,'' '' ;character .red: cmp bx,0x0FA0 je .end mov WORD [es:bx], ax inc bx jmp .red

Desafortunadamente, debido a que la arquitectura x86 es poco endian, los valores que se colocan en la memoria tienen el byte menos significativo primero y el byte más significativo al último (cuando se trata de un WORD de 16 bits). Tiene AX que contiene 0x2040 y movió la PALABRA completa con mov WORD [es:bx], ax a la memoria de video. Por ejemplo, habría escrito estos bytes en la primera celda:

0xb800:0x0000 : 0x40 ; ASCII char for 0x40 is `@'' 0xb800:0x0001 : 0x20 ; Green background, black foreground

Creo que esto es un green @ pero debido al segundo error mencionaré que puede haber aparecido rojo. Para solucionar esto, necesita invertir la posición del carácter y el atributo en el registro AX (intercambie los valores en AH y AL ). El código se vería así:

mov ah,0x40 ;colour is now in AH, not AL mov al,'' '' ;character is now in AL, not AH .red: cmp bx,0x0FA0 je .end mov WORD [es:bx], ax inc bx jmp .red

El segundo error está relacionado con atravesar el área de video. Debido a que cada celda toma 2 bytes, necesita incrementar el contador BX en 2 en cada iteración. Tu código hace:

mov WORD [es:bx], ax inc bx ; Only increments 1 byte where it should be 2 jmp .red

Modifique el código para agregar 2 a BX :

mov WORD [es:bx], ax add bx,2 ; Increment 2 since each cell is char/attribute pair jmp .red

Podría haber simplificado el código utilizando la instrucción STOSW que toma el valor en AX y lo copia a ES: [DI] . Puede prefijar esta instrucción con REP, que la repetirá CX veces (se actualizará DI en consecuencia durante cada iteración). El código podría haber sido así:

error: mov ax,0xb800 mov es,ax ;Set video segment to 0xb800 mov ax,0x4020 ;colour + space character(0x20) mov cx,2000 ;Number of cells to update 80*25=2000 xor di,di ;Video offset starts at 0 (upper left of screen) rep stosw ;Store AX to CX # of words starting at ES:[DI]

Su código ya borra el indicador de dirección con CLD al comienzo de su código, por lo que REP aumentará DI durante cada iteración. Si la bandera de dirección se hubiera establecido con STD , DI habría disminuido.

Creé un código simple para cargar el segundo sector desde el disco duro, y luego escribo en pantalla completa, con espacios con fondo rojo. El problema es que siempre en lugar de espacios obtuve @ signos. Este es el código:

org 0x7C00 bits 16 xor ax,ax mov ds,ax mov es,ax mov bx,0x8000 cli mov ss,bx mov sp,ax sti cld clc xor ah,ah int 0x13 mov bx,0x07E0 mov es,bx xor bx,bx mov ah,0x2 ;function mov al,0x5 ;sectors to read mov ch,0x0 ;track mov cl,0x2 ;sector mov dh,0x0 ;head int 0x13 ;jc error ;mov ah, [0x7E00] ;cmp ah,0x0 ;je error jmp error cli hlt jmp 0x07E0:0x0000 error: xor bx,bx mov ax,0xb800 mov es,ax mov al,0x40 ;colour mov ah,'' '' ;character .red: cmp bx,0x0FA0 je .end mov WORD [es:bx], ax inc bx jmp .red .end: cli hlt times 0x1FE - ($ - $$) db 0x0 db 0x55 db 0xAA

de acuerdo con este código, la pantalla debe estar llena de espacios, pero no es así.