Page 1 of 1

memory write mystery (SOLVED)

Posted: Sun Apr 04, 2010 8:33 am
by lama
hello, quick question:
simple rep insw instruction - i used it at least 10000x but i have never seen this happen: edi was set to 0x211000, df cleared, es pointed to gdt entry with base 0, dx set properly, interrupts disabled...but when the instruction chain has finished, the data appeared at 0x210000 !! what is wrong again? tested on both qemu and bochs - so it must be my fault.
thanks for the help.
EDIT: this also happens even if movsb/w/d is used.

Re: memory write mystery

Posted: Sun Apr 04, 2010 8:55 am
by Owen
Direction (D) flag set, therefore the movs/ins/etc instructions are moving down through memory. Use the cld instruction beforehand to clear it.

Re: memory write mystery

Posted: Sun Apr 04, 2010 9:04 am
by lama
i said " df cleared" ;), DF stands for direction flag.

Re: memory write mystery

Posted: Sun Apr 04, 2010 9:28 am
by Gigasoft
Does your page allocator by any chance allocate the same page over and over again? I had that bug once, and it took a while before I realized it :P

Re: memory write mystery

Posted: Sun Apr 04, 2010 9:37 am
by lama
it does not matter - edi IS already set to desired location (0x211000); and then follows insw. imagine something like this :

Code: Select all

cli
cld
mov edi, 0x211000
mov ecx, 256
rep insw ; or movs whatever..
:cry: :cry:
EDIT:
plus - now i have changed edi to 0x212000 (after successfull read to 0x210000) - and memory 0x210000 gets STILL overriden with data from rep insw.
EDIT 2:
and if you want a "real snippet" from that code:

Code: Select all

ata_rd:
; eax = lba
; edi = location where to put the data (512 bytes)
; dl  = drive, 0 = master, 1 = slave
push dx ; given gdt selector
mov dl, bl
  test eax, 0xF0000000	; test for bits 28-31
  jnz short .return_error
  test dl, 0xFE		; test for invalid device ids
  jnz short .return_error
  push edx
  push eax
  call ata_wait_not_busy

  mov dl, 0xF2		; port 0x1F2 (sector count register)
  mov al, 0x01		; read one sector at any given time
  out dx, al		;

  inc edx		; port 0x1F3 (sector number register)
  pop ecx		; set ecx = lba
  mov al, cl		; al = lba bits 0-7
  out dx, al		;

  inc edx		; port 0x1F4 (cylinder low register)
  mov al, ch		; al = lba bits 8-15
  out dx, al		;

  inc edx		; port 0x1F5 (cylinder high register)
  ror ecx, 16		;
  mov al, cl		; set al = lba bits 16-23
  out dx, al		;

  pop eax		; restore drive id
  inc edx		; port 0x1F6 (device/head register)
  and ch, 0x0F		; set ch = lba bits 24-27
  shl al, 4		; switch device id selection to bit 4
  or al, 0xE0		; set bit 7 and 5 to 1, with lba = 1
  or al, ch		; add in lba bits 24-27
  out dx, al		;

  call _wait_drdy	; wait for DRDY = 1 (Device ReaDY)
  test al, 0x10		; check DSC bit (Drive Seek Complete)
  jz short .return_error

  mov al, 0x20		; set al = read sector(s) (with retries)
  out dx, al		; edx = 0x1F7 == command/status register

  ; TODO: ask for thread yield, giving time for hdd to read data
  jmp short $+2
  jmp short $+2

  call ata_wait_not_busy.waiting	; bypass the "mov edx, 0x1F7"
  test al, 0x01     ; check for errors
  jnz short .return_error

  mov dl, 0xF0		; set dx = 0x1F0 (data register)
  mov ecx, 256		; 256 words (512 bytes)
cld
;==================================== I CHECKED THE EDI HERE - SET PROPERLY TO 0x210000 =================
;==================================== works well when edi is not higher then 0x210000, i guess ================
  repz insw		; read the sector to memory
  clc			; set completion flag to successful
pop dx
  ret			;

.return_error:
pop dx
mov ds, dx
mov esi, error_msg
call prints
  mov dl, 0xF1		; error status register 0x1F1
  in al, dx		; read error code
mov al, bl
mov eax, 8
int 0x80
  stc			; set completion flag to failed
  ret			;
I should note, that i have not written this code. i found it somewhere and did just a few things to get it work under my faulty system..
So please do not stone me, if someone regognizes this code as one's own ;)

Re: memory write mystery

Posted: Sun Apr 04, 2010 10:02 am
by Gigasoft
Yeah, sounds like 0x210000, 0x211000 and 0x212000 are all the same page, as I thought.

Re: memory write mystery

Posted: Sun Apr 04, 2010 10:06 am
by Owen
lama wrote:i said " df cleared" ;), DF stands for direction flag.
My brain is evidently broken. I thought I saw that initially, looked at it again and didn't see it.

Re: memory write mystery

Posted: Sun Apr 04, 2010 2:18 pm
by lama
solved ! :)))))) thanks to a guy named bcos :) thanks man, you have helped me a lot ! :)
and ofcourse thanks anyone who replied at my question :)
and if anyone is interested in what was wrong - problem was i my paging routine, whitch allocates memory. some pages were allocated more than o once. in page directory was the same pages allocated twice or moretimes. bcos told me what is wrong and he also made a fix.
thanks again man :)
you may lock this thread.