Page 1 of 1
Turbo C and Assembly Won't Work!
Posted: Wed Jan 24, 2007 10:59 pm
by pcmattman
Hello all!
With Turbo C I can compile and link my kernel into a 16-bit exe (which my OS supports). However, the system hangs on the entry point (NASM code):
Code: Select all
extern _main
section _TEXT code
..start:
mov ax,0x9000 ; put stack at 0x98000
mov ss,ax
mov sp,0x8000
mov ax,seg _main ; segment of _main
mov es,ax ; => es
call [es:_main] ; go there now
hangloop:
pause
jmp $
The program hangs on the call to es:_main, but without this contol just falls through to the hang loop.
Also, any ASM function I try to call from within my code don't execute at all - they are pretty much just skipped over without executing instructions.
Posted: Thu Jan 25, 2007 4:51 am
by Combuster
i doubt the call [es:_main] is what you want:
this is assembled as:
make a call to the address in memory location main, using prefix ES
and executed as
target = memory(es * 16 + main)
push ip
mov ip, target
the architecture has no direct opcode for call es:_main (without [ ] ), so either:
- You use a direct far call and either force the same segment (or fix the instruction using self-modyfing code, yuck)
- You create a far pointer in memory and use call far [structure]
- You push everything into place and use RETF
Posted: Thu Jan 25, 2007 8:32 am
by bubach
Why would you need a entry point for a 16-bit EXE program? You'r probably wrecking the EXE header and/or confusing the EXE bootloader.
Posted: Thu Jan 25, 2007 8:55 pm
by pcmattman
I've since been able to boot into the kernel successfully - and use my assembly functions - but the new problem is how to get a byte argument from Turbo C? I look at the disassembly and there is nothing at all pushed onto the stack before my assembly functions run. Why is this happening?
Posted: Fri Jan 26, 2007 2:39 am
by AJ
Hi,
Is it possible to see the code for that part - I don't see any pushes in your code.
If you mean that you would like to pass an argument to '_main', you will need to manually push your arguments before caling it. I use GCC which pushes from right to left, but I guess all C compilers are the same in this respect
If you are expecting arguments from a previous boot loader, you need to retrieve them *before* you move the stack pointer!
Cheers,
Adam
Posted: Fri Jan 26, 2007 3:42 am
by Solar
AJ wrote:I use GCC which pushes from right to left, but I guess all C compilers are the same in this respect
They need not be. Obviously there is the convention to use whatever the system libraries expect, but since we're talking about OS development, calling conventions could be left-to-right, unpadded, register passing or whatever...
Posted: Fri Jan 26, 2007 9:09 pm
by pcmattman
Sorry, the code above is
not the code I was referencing! I've looked at other code to be linked with 'tlink' and they all use the calling convention I would normally use. Here's my assembly:
Code: Select all
global _kputc
section _TEXT
_kputc:
push bp
mov bp,sp
mov al,[ss:bp+4] ; first argument
mov ah,0eh
mov bx,07h
int 10h
pop bp
xor ax,ax ; return 0
retn
Called like so:
Code: Select all
extern kputc( char );
kputc( 'D' );
But I've solved it - the argument to kputc can't be 'char' - it
must be 'int'.
Posted: Fri Jan 26, 2007 11:22 pm
by pcmattman
New problem: functions can only be called once before the linker doesn't work properly anymore!! It says 'fixup overflow' and none of my functions work anymore. Any ideas?