Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion in Memory segmentation in x86

Tags:

c

x86

assembly

Here I made a code for writing ASCII characters into VGA Memory:

.global _put_in_mem
_put_in_mem:
push bp
mov bp, sp
mov cx, [bp + 4]
mov si, [bp + 6]
mov bx, 0xb800
mov ds, bx
mov [si], cx
add bx, 0x1
mov cx, 0x7
mov [si], cx
pop bp
ret

This is called through a kernel.c file shown below:

void main()
{
 extern void put_in_mem();
 char c = 'e';
 put_in_mem(c, 0xA0);
}

The above code was meant to print "e" on the beginning of the second line in QEmu, but it did not. I tried to debug this using GDB and found that the command

mov bx, 0xb800

in GDB has become

mov    -0x4800,%bx

and the value in ebx after this command is 0x0.
Why has the value not loaded in the bx register?

Further, I thought that the move instructions use ds register as their segment base and offset all the addresses from the contents of ds. So according to this reasoning, I assumed that when

mov [si], cx

instruction the contents of cx register will be placed at the address 0xb8a0. Is this correct? Can mov instruction be affected by any other segement registers (like cs, es etc.) as well?

like image 537
sarthak Avatar asked Feb 24 '15 15:02

sarthak


People also ask

Does x86 use segmentation?

The x86-64 architecture does not use segmentation in long mode (64-bit mode). Four of the segment registers, CS, SS, DS, and ES, are forced to base address 0, and the limit to 264.

What do you understand by memory segmentation?

Memory segmentation is an operating system memory management technique of division of a computer's primary memory into segments or sections. In a computer system using segmentation, a reference to a memory location includes a value that identifies a segment and an offset (memory location) within that segment.

What is memory segmentation in microprocessor?

Segmentation is the process in which the main memory of the computer is logically divided into different segments and each segment has its own base address.

What is maximum physical memory size of segmentation process?

Since each page is 2^13 B long, the maximum addressable physical memory size is 2^32 * 2^13 = 2^45 B (assuming no protection bits are used).


2 Answers

There are a couple of problems with the routine _put_in_mem, it doesn't preserve registers DS and SI which must be preserved according to 16-bit x86 calling conventions, see section 6 of this document, and it doesn't store the character and attribute bytes properly.

.global _put_in_mem
_put_in_mem:
push bp
mov bp, sp
mov cx, [bp + 4]
mov si, [bp + 6]   # si must be preserved across function calls
mov bx, 0xb800
mov ds, bx         # ds must be preserved across function calls
mov [si], cx
add bx, 0x1
mov cx, 0x7        # low byte 0x7, upper byte = character = 0x00
mov [si], cx       # si has not changed... overwriting with 0x0007
pop bp
ret

Here's one way to fix it:

.global _put_in_mem
_put_in_mem:
push bp
mov bp, sp
mov cx, [bp + 4]   # cx = xxcc, where cc is ASCII character
mov ch, 0x7        # attribute byte: light-grey on black
mov bx, [bp + 6]   # bx = offset into VGA video buffer
mov ax, 0xb800     # VGA video buffer base at 0xb800 x 16
mov es, ax         # use ES segment register instead of DS
mov es:[bx], cx    # store ASCII at es:[bx], attribute at es:[bx+1]
pop bp
ret

The VGA attribute byte follows the character byte in text mode. An attribute of 0x7 means to display as light-grey on black background... see http://wiki.osdev.org/Printing_To_Screen and http://en.wikipedia.org/wiki/VGA-compatible_text_mode

like image 103
amdn Avatar answered Oct 08 '22 05:10

amdn


Make sure it isn't a memory reference accidentally. Since your gdb output seems like at&t, it would normally show a $ for immediates. As such, it's suspicious that what you really have is loading bx with the content of memory at address 0xb800. Can you check the machine code?

The machine code is 0xb8001e8b

Indeed, that's machine code for loading from memory. Looking at the as86 manual, you can see:

#      Prefix for immediate operands.
       mov ax,#1234
       Immediate value, ax becomes 1234.

As such, you should prefix your immediates with a # sign. Note this applies to all immediates.

While this fixes the problem you asked about, see @amdn's answer for other issues you have.

like image 3
Jester Avatar answered Oct 08 '22 05:10

Jester