Here is the same non-BIOS screen print code as before, but adjusted to use 32-bit registers and offsets. The 'complex' string instructions been replaced.
;----------------------???
dochar:???call cprint???; print one character
sprint:???mov eax, [esi]???; string char to AL
???lea esi, [esi+1]
???cmp al, 0
???jne dochar???; else, we're done
???add byte [ypos], 1???;down one row
???mov byte [xpos], 0???;back to left
???ret
cprint:???mov ah, 0x0F???; attrib = white on black
???mov ecx, eax ???; save char/attribute
???movzx eax, byte [ypos]
???mov edx, 160???; 2 bytes (char/attrib)
???mul edx??????; for 80 columns
???movzx ebx, byte [xpos]
shl ebx, 1 ???; times 2 to skip attrib
???mov edi, 0xb8000 ; start of video memory
???add edi, eax ; add y offset
???add edi, ebx ; add x offset
???
???mov eax, ecx ; restore char/attribute
???mov word [ds:edi], ax
???add byte [xpos], 1 ; advance to right
??????
???ret
??????
;------------------------------------
printreg32:
???mov edi, outstr32
???mov eax, [reg32]???
???mov esi, hexstr
???mov ecx, 8???; eight nibbles
hexloop:
???rol eax, 4???;leftmost will
???mov ebx, eax???; become rightmost
???and ebx, 0x0f???;
???mov bl, [esi + ebx];index into hexstr
???mov [edi], bl
???inc edi
???dec ecx
???jnz hexloop
??????
???mov esi, outstr32
???call sprint
???
???ret
??????
;------------------------------------???
xpos???db 0
ypos???db 0
hexstr???db '0123456789ABCDEF'
outstr32???db '00000000', 0 ;register value
reg32???dd???0???; pass values to printreg32
;------------------------------------???
baby steps #8 - 32-bit printing
Re:baby steps #8 - 32-bit printing
OK, so REP MOVS etc. mess up the instruction pairing slightly, but I'm not sure why they're unsuited to a 32-bit environment. In a USE32 segment, or with the A32 (or was it O32?) prefix, they will use EAX, ESI and EDI as appropriate. MOVSD will even move DWORDs.My advice is to never use LODS, STOS, MOVS, CMPS, SCAS again. They are slow and unsuited to a 32-bit environment (IMHO).
Re:baby steps #8 - 32-bit printing
True. The remark was a bit out of context and I have removed it.Tim Robinson wrote:
OK, so REP MOVS etc. mess up the instruction pairing slightly, but I'm not sure why they're unsuited to a 32-bit environment. In a USE32 segment, or with the A32 (or was it O32?) prefix, they will use EAX, ESI and EDI as appropriate. MOVSD will even move DWORDs.
What Tim is referring to is NASM's way of prefixing as described in "baby steps #3 - encoding". Here is the relevant code, showing all three ways.
;---------------------------
dochar: call cprint ; print one character
sprint: ;mov eax, [esi] ; string char to AL
;lea esi, [esi+1]
db 0x67
lodsb ; string char to AL
;a32 lodsb ; NASM shortcut
.... other code ...
mov eax, ecx ; restore char/attribute
;mov word [ds:edi], ax
db 0x67
stosw ; write char/attribute
; a32 stosw ; NASM shortcut
add byte [xpos], 1 ; advance to right
;---------------------------
In order for the complex instructions to work you have to set-up ES just like we did DS in 'boot.asm'
;-------- start of code here
%include "print32.inc"
start: xor ax, ax ; make it zero
mov ds, ax ; DS=0
mov es, ax
mov ss, ax ; stack starts at 0
mov sp, 0x9c00 ; 200h past code start
cli ; no interrupt
push ds ; save real mode
push es
lgdt [gdtinfo] ; load gdt register
mov eax, cr0 ; switch to pmode by
inc ax ; toggling last bit
mov cr0, eax
mov bx, 0x08 ; select our gdt
mov ds, bx ;
mov es, bx
dec ax ; switch back to real mode
mov cr0, eax ; by toggling bit again
pop es
pop ds ; get back old segment
sti
mov eax, 0xdeadbeef
mov dword [reg32], eax
call printreg32
;-------- rest of code here