Hi, my toy OS now could load an ELF bin file. But I am totally confused about the instruction "lea". "lea" could calculate the effective address, but it seems to be only an offset, so we need the correct segment to access the memory. Right now my toy OS does not support paging mechenism and the SS, DS are different (DS - 1M~3.5M, SS- 3M~3.5M). When the C program tries to pass the local variable (on stack), I got such things:
Code: Select all
char msg [16];
*( int* )msg = 'tset'; /* Use this form to avoid .rodata and .data
*(( int* )msg + 1) = '\0'; * section coz my toy OS does not load these
* sections, little endian so reverse order */
print( msg );
The machine code is like:
Code: Select all
lea 0xfffffff0(%ebp), %eax ; msg address
mov $0x74736574, (%eax) ; Move "test" to %ds:%eax
lea 0xfffffff0(%ebp), %eax
add $0x4, %eax
mov $0x0, (%eax) ; Move '\0' to %ds:%eax
lea 0xfffffff0(%ebp), %eax
mov %eax, (%esp)
call print
The print function is written in C as well, the machine code is like
Code: Select all
mov 0x8(%ebp), %eax ; msg address
movzwl (%eax), %eax ; eax = [ds:eax]
The code above will print "test" on the screen. However, "test" will be stored in data segment, NOT stack segment. And the function print access data segment as well (which is not desired because I think it will access the local variable on the stack). So if I write the code like:
The corresponding machine code will be:
Code: Select all
movb $0x74, 0xfffffff0(%ebp) ; Move 't' to [ss:ebp]
As you can see, the code will write the byte to ss:ebp on the stack, which is desired by us. Then the print function will NOT behave correctly because it could not touch [ss:eax]. So if I want to make changes to the variable on the stack, I could never ever do that. On Linux, the code behaves correctly because it uses the same SS and DS segments. Any one can provide some explanations on this? I use GCC 4.0 to compile the code.