baby steps #8 - 32-bit printing

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
crazybuddha

baby steps #8 - 32-bit printing

Post by crazybuddha »

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

;------------------------------------???
Tim

Re:baby steps #8 - 32-bit printing

Post by Tim »

My advice is to never use LODS, STOS, MOVS, CMPS, SCAS again. They are slow and unsuited to a 32-bit environment (IMHO).
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.
crazybuddha

Re:baby steps #8 - 32-bit printing

Post by crazybuddha »

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.
True. The remark was a bit out of context and I have removed it.

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
Post Reply