memory write mystery (SOLVED)

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
lama
Member
Member
Posts: 83
Joined: Thu Apr 16, 2009 8:41 am

memory write mystery (SOLVED)

Post 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.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: memory write mystery

Post 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.
lama
Member
Member
Posts: 83
Joined: Thu Apr 16, 2009 8:41 am

Re: memory write mystery

Post by lama »

i said " df cleared" ;), DF stands for direction flag.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: memory write mystery

Post 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
lama
Member
Member
Posts: 83
Joined: Thu Apr 16, 2009 8:41 am

Re: memory write mystery

Post 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 ;)
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: memory write mystery

Post by Gigasoft »

Yeah, sounds like 0x210000, 0x211000 and 0x212000 are all the same page, as I thought.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: memory write mystery

Post 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.
lama
Member
Member
Posts: 83
Joined: Thu Apr 16, 2009 8:41 am

Re: memory write mystery

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