10 Replies - 1894 Views - Last Post: 23 April 2012 - 02:08 PM

#1 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

[x86] A few questions

Posted 09 April 2012 - 08:13 AM

Well this is the second time through writing this thread so lets see if it actually posts this time.

I have been having some trouble with assembly related things through the reading I have been doing (and in practice).

1 - Some instructions have what appear to be ranges that they work on (such as movsb) where it works on say es:bx. Is this a range? Or (and I believe this one is more likely) is it a way to concatenate to registers to provide a larger address space (such as upconverting 8 or 16-bit addresses to say 32-bit addresses)?

2 - I read that loading data from a floppy with es = 0x1000 and bx = 0x0 (through the BIOS) will result in the data being loaded at the physical address 0x10000, this doesn't seem correct. Shouldn't it be es = 0x0010 and bx = 0x0?

3 - Is there any way to tell if a rodata segment is linked in the correct place in a kernel without running it and seeing if the output is correct? I have been running into a bit of trouble with my rodata either not being in the correct place, or it not being linked at all and am not sure how to track the error down.

Thanks for your time. I can post code (some of which will be relevant) if needed.

Is This A Good Question/Topic? 0
  • +

Replies To: [x86] A few questions

#2 ishkabible   User is offline

  • spelling expret
  • member icon





Reputation: 1747
  • View blog
  • Posts: 5,898
  • Joined: 03-August 09

Re: [x86] A few questions

Posted 09 April 2012 - 09:53 AM

Quote

is it a way to concatenate to registers to provide a larger address space


yes, in Intel syntax the ':' will combine 2 smaller registers into a bigger register. eax and edx are are classic combo and that's how 64-bit values are returned in 32-bit code using the cdecl calling convention.

On question 2: what means are you using to do this? do you mean by using int 0x13? if so then yes that you are correct, it should be es == 0x0010. you can read about it here.

I can't help on question 3. I'm not familiar enough with the ELF format to know. sorry :/ I'll read about it and see if I can offer any help.

This post has been edited by ishkabible: 09 April 2012 - 09:55 AM

Was This Post Helpful? 1
  • +
  • -

#3 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

Re: [x86] A few questions

Posted 09 April 2012 - 09:59 AM

Thanks :)

Yes, I am using int 0x13 for the loading.
Was This Post Helpful? 0
  • +
  • -

#4 GenHornet18   User is offline

  • Darken the Radar

Reputation: 36
  • View blog
  • Posts: 629
  • Joined: 19-October 09

Re: [x86] A few questions

Posted 12 April 2012 - 11:40 PM

1.) That looks like real-mode segmentation, segment:offset address(read up on real mode segmentation)

2.)Real mode segmentation again, ES=0x1000(in real mode taken as 20bit register), BX=0x00. Segment:offset (ES:BX), resolves to 0x10000.

3.) Linker scripts are your friend ;)


-Hornet
Was This Post Helpful? 0
  • +
  • -

#5 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

Re: [x86] A few questions

Posted 13 April 2012 - 09:02 AM

Ah, suppose I should have mentioned that I am using a linker script, and this is what it looks like:

SECTIONS {
  . = 0x100000;
  .text ALIGN (0x1000) : {
    *(.text)
  }
  .rodata ALIGN (0x1000) : {
    *(.rodata*)
  }
  .data ALIGN (0x1000) : {
    *(.data)
  }
  .bss : {
    sbss = .;
    *(COMMON)
    *(.bss)
    ebss = .;
  }
}



And I have run into a new and interesting problem of the floppy driver being reset by the hardware (I am guessing while it is trying to run, otherwise I don't see the reason it would warn me about it...). I am attempting to (theoretically) write to 0x100000 as I read in the information from the floppy. As you probably know, you can't access memory higher than 1 MB (0x100000) in real mode, so I have attempted to start A20 mode which enables access to 64 KB above the 1 MB mark.

Here is the corresponding code:
; ... snip ...
reset_drive:
  mov ah, 0
  int 0x13
  or ah, ah
  jnz reset_drive

  xor ax, ax ; set up the stack
  mov ss, ax
  mov sp, 0x600

  xor ax, ax ; load the GDT
  mov ds, ax
  lgdt [gdt_desc] ; end load the GDT

  mov ax, 0x2401 ; enable a20 mode
  int 0x15
  mov al, 'Y'
  call print
  call eNinePrint ; end enable a20 mode

.loadSector:
  mov ax, 0x0010
  mov es, ax
  mov bx, 0x0000 ; 1 MB mark
  mov ah, 0x02
  mov al, 0x12 ; load 18 sectors
  mov ch, 0
  mov cl, 0x02 ; starting at sector 2
  mov dh, 0
  int 0x13 ; load a sector to es:bx
  or ah, ah
  jnz reset_drive ; error occurred

  mov al, '1'
  call eNinePrint
; ... snip ...



As you can see I am resetting the hardware, setting up a basic stack, loading a simple GDT, flipping over to A20, and then attempting to load the sectors from the floppy. It just continually gives me the warning message (in bochs) reading [FDD ] controller reset in software. Any thoughts?
Was This Post Helpful? 0
  • +
  • -

#6 GenHornet18   User is offline

  • Darken the Radar

Reputation: 36
  • View blog
  • Posts: 629
  • Joined: 19-October 09

Re: [x86] A few questions

Posted 13 April 2012 - 04:11 PM

Assuming the A20 line got enabled (it's a pin, not a mode (or more so emulated pin these days)) your trying to load to 0x100000? Your real mode segmentation appears to be incorrect:

mov AX, 0xFFFF
mov ES, AX
mov BX, 0x10

;address resolves to 0x100000 (ES:BX)



When loading more sectors watch for cylinder boundaries (it's easier converting LBA to CHS) and since your loading so high watch for memory wrap-around. Perhaps you may be interested in Unreal-mode since your certain high memory exists.


-Hornet

EDIT: addressing error

This post has been edited by GenHornet18: 13 April 2012 - 04:14 PM

Was This Post Helpful? 1
  • +
  • -

#7 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

Re: [x86] A few questions

Posted 16 April 2012 - 08:48 AM

The plan is to make a micro-kernel and have it simply set up the memory mananger, a way to draw to video memory (simple graphics card driver) and a floppy/ usb/ hard drive driver so it can load more programs then make the kernel responsible for loading the rest of the necessary things. Basically have the bare bones loaded through the bootloader (which I am hoping will fit in the 64 K available with a20 enabled) and load more later as needed (from the kernel actual).

Thanks for the addressing fix, that got it to stop giving me the previous errors and actually load the kernel. Now I am just thinking that there is a problem with my linker script as the string the kernel was supposed to output (which is theoretically positioned at 0x101000) was gibberish instead of the "Hello world" is was supposed to be (it was also only 4 characters).

Here is the main programs' source, nice and small, but I am not exactly sure what is causing the problem (I have been struggling with it for quite some time):

void pout(unsigned short port, unsigned char byte){
  __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (byte));
}
unsigned char pin(unsigned short port){
  unsigned char rv;
  __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (port));
  return rv;
}

void printStr(const char* s){
  unsigned char* vmem = (unsigned char*)0xb8000;
  unsigned short offset;
  unsigned int i;
  pout(0x3d4, 14);
  offset = pin(0x3d5) << 8;
  pout(0x3d4, 15);
  offset |= pin(0x3d5);
  for(i = 0; s[i]; ++i){
    *vmem = s[i];
    *(vmem + 1) = 0x0f;
    vmem += 2;
  }
  *((int*)0x100c) = i; // write the length of the string to memory so we can examine it later
  offset += i;
  pout(0x3d5, (unsigned char)offset);
  pout(0x3d4, 14);
  pout(0x3d5, (unsigned char)(offset >> 8));
}

int main(void){
  const char* msg = "Hello world";
  printStr(msg);

  *((int*)0x1008) = (int)msg; // write the address of msg to a memory location we know and will be able to look at later (using bochs debugger)
  while(1);
  return 0;
}



Thanks for the continued assistance.
Was This Post Helpful? 0
  • +
  • -

#8 GenHornet18   User is offline

  • Darken the Radar

Reputation: 36
  • View blog
  • Posts: 629
  • Joined: 19-October 09

Re: [x86] A few questions

Posted 18 April 2012 - 09:47 PM

Sorry It took so long to post a reply (life is pressing),

What is your development environment? Are compiling to a straight binary and
loading that as a binary image in bochs? Can you confirm (via hex editor) that
the read-only data section is present?

Assuming the development environment is not at fault, are you in the proper processor
mode and is the video mode set accordingly? Hardcode some values to be set in video
memory at the start of your kernel to ensure execution reaches that point.

-Hornet
Was This Post Helpful? 0
  • +
  • -

#9 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

Re: [x86] A few questions

Posted 21 April 2012 - 11:23 AM

No worries, I understand that life has to take presidence.

I am developing in Linux (Ubuntu) using nasm, g++ and ld with bochs as a first-line emulator and debugger and VMware as the second-line "it actually works" test. I am compiling the kernel to binary and then making a floppy image out of it to boot (with the bootloader in the first 512 bytes, as needed).

I can also verify that the rodata section does exist in the kernel binary (as is the string it should be outputting), it just outputs gibberish instead...). I can also verify that it is making it to my kernel by outputting a single character to the screen without trouble (a plus character '+' to be specific).

I went a bit further and checked out what memory location the kernel thought should be the string to see if it matched what the hex dump stated. It turned out the kernel thought the rodata segment had been placed at 0x1000 when it was actually placed at 0x2000. By manually adding 0x1000 to the string I was outputting it finally got to the screen. I am not 100% certain here, but isn't this something that the linker and linker script should be handling? If so, I think we know where to look...
Was This Post Helpful? 0
  • +
  • -

#10 GenHornet18   User is offline

  • Darken the Radar

Reputation: 36
  • View blog
  • Posts: 629
  • Joined: 19-October 09

Re: [x86] A few questions

Posted 22 April 2012 - 03:10 PM

Looks like an alignment issue, although I'm unsure how to fix your script to correct it. I dug around and found my linker script when I was doing some OSDev, perhaps it could be of some assistance (take note that I was loading ELF format).

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)
SECTIONS
{
  . = 0x10000;

  .text :
  { 
    *(.text)
  }

  .rodata ALIGN (0x1000) :
  {
     *(.rodata)
  }

  .data ALIGN (0x1000) : 
  { 
     *(.data)
  }

  .bss : 
  {
    bss = .;
    *(.bss)
    *(COMMON) 
  }
  end = .;
}




-Hornet
Was This Post Helpful? 1
  • +
  • -

#11 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1647
  • View blog
  • Posts: 8,510
  • Joined: 07-September 06

Re: [x86] A few questions

Posted 23 April 2012 - 02:08 PM

Hm, alright. Couldn't figure out my error based off your linker script, but thanks for posting it. I guess it is time to read about all this in more depth and figure out what the heck if going wrong.

Thanks for the help though :)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1